diff --git a/.gitignore b/.gitignore
index af2dade7dc..73b9c1ae31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,7 @@ lib
build
aspnet_client
node_modules
-/tools/jsdoc_toolkit-2.4.0
\ No newline at end of file
+/tools/jsdoc_toolkit-2.4.0
+/package
+/tools/jsdoc_toolkit/jsdoc_toolkit-2.4.0
+/.project
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 43af3292c4..0000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "samples"]
- path = samples
- url = https://github.com/cocos2d/cocos2d-js-tests.git
diff --git a/AUTHORS.txt b/AUTHORS.txt
index ce58b34302..e61d18e5cb 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -10,13 +10,13 @@ Core Developers:
Dingping Lv (David Lv)
- Shengxiang Chen (Nero Chan)
-
Ricardo Quesada
- Xingsen Ma
+ Huabin LING (@pandamicro)
+
+ Sijie Wang (@VisualSJ)
- Huabin LING
+ Jialong Zhai (@JoshuaAstray)
Contributors:
Name GithubID Main contribution
@@ -24,6 +24,7 @@ Name GithubID Main contribution
Dali Kilani @dadilcool added instruction to read me
Chris @hannon235 added node.js api for box2d
+ added SocketIO and SocketIO tests
Jason Aeschliman @jaeschliman fixed cc.Node setposition
@@ -61,6 +62,7 @@ keisuke hata(Square) @Seasons7 Code review, bug fix
Marat Yakupov @moadib Various bug fixes
Liang Wu @akira-cn Touch location fix for designResolution
+ ScrollView on paused bugs fix
Jimmy Sambuo @jsambuo AudioEngine improvements
@@ -84,8 +86,9 @@ Kang-Hao Lu(Opera/Oupeng) @kennyluck Optimize John Resig's inheritance patter
Mark Henderson @MarkEHenderson Code review, LabelTTF and Scale9Sprite bug fix
Jing Wang @06wj CCScheduler improvements
- Js file loading image add
- cc.RectApplyAffineTransform improvements
+ Js file loading image add
+ cc.RectApplyAffineTransform improvements
+ Fixed a bug of cc.Node.setPosition that parameter check is incorrect
Ze Wang @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent
LabelTTF improvements
@@ -112,6 +115,8 @@ XiaoJun Zheng @SmallAiTT _getResType error fix
refactor some public functions in cc to private
add node.js scripts for publishing game
refactor cc.CCBReader
+ cc.view bug fix
+ multiple property object supports in extend function
Guozhu Cheng @bengol cc.SimpleAudioEngine bug fix
@@ -151,16 +156,113 @@ samael @samael65535 CCPhysicsSprite bug fix
NatWeiss @NatWeiss Add analytics plugin protocol ,Flurry plugin and ProtocolAds.js plugin protocol
cc.FileUtils refactoring
+ cc.Audio bugs fix
+ cc.Texture2D bug fix
Andor Salga @asalga typo fix
erykwalder @erykwalder Function.prototype.bind bug fix
ZippoLag @ZippoLag cc.Application.getCurrentLanguage bug fix
+ typo fix
+
+Asano @LaercioAsano cc.Node bug fix
+
+Bruno Assarisse @bassarisse cc.LabelBMFont bug fix
+
+Mykyta Usikov @musikov cc.ClippingNode bugs fix
+ cc.fontLoader bug fix
+ Inverted ClippingNode with DrawNode as stencil bug fix under canvas render mode
+ JumpTo bug with wrong _delta position bug fix
+ cc.ProgressTimer bugs fix
+ cc.Scale9Sprite bugs fix
+ cc.RenderTexture bug fix
+ cc.ParticleSystem bug fix
+
+Han XiaoLong @kpkhxlgy0 cc.ParticleSytem bug fix
+
+AaronRZH @AaronRZH Creation of a sequence objcet or a spawn object by using new method bug fix
+
+Xiaodong Liu @tianxing113 cc.Spawn.create bug fix
+ ccui.LoadingBar.setPercent crash bug fix
+
+Park Hyun Chen @sincntx Touch anywhere of screen to finish input when using cc.EditBox
+ ccui.TextBMFont bug fix
+ cc.game bug fix
+ Fixed an issue of cc.ArmatureAnimation's setMovementEventCallFunc
+
+Ninja Lau @mutoo A typo bug in UILayout fix
+ One-loop CCArmatureAnimation can't finish when setSpeedScale is less than 1.0 bug fix
+ A transform error in CCTransformHelp.js fix
+ ccs.DisplayManager bug fix
+ Fix child armature lost _parentBone issue
+ cc.eventManager bug fix
+ ccs.Bone bug fix
+ ccs.ActionFrame bug fix
+ ccui.Widget bug fix
+ ccui.LoadingBar bug fix
+
+Taras Tovchenko @tovchenko cc.Skin bounding box calculation bug fix under canvas render mode
+
+Minh Quy @MQuy cc.MenuItemSprite bug fix
+ Check empty string for textureData
+ Adds type check functions
+
+Michael Yin @layerssss cc.game refactored
+
+Yang Yuchen @yycdef cc.sys bug fix
+
+K @kiwigrc cc.ParticleSystem bug fix
+
+Claudio Freitas @claudiofreitas ccui.TextField typo fix.
+
+nopakos @nopakos cc.Texture2D bug fix
+
+Robert Rouhani @Robmaister cc.TMXMapInfo bug fix
+ cc.TMXLayer bug fix
+
+Igor Mats @IgorMats cc.Scale9Sprite bug fix
+ Spine runtime update
+ Add getStroke and setStroke method to cc.MotionStreak
+
+Tim @duhaibo0404 ccs.csLoader bug fix
+
+Hermanto @man2 cc.loader bug fix
+
+Long Jiang @jianglong0156 cc.LabelBMFont bug fix
+ KeyCode bug fix
+ ccui.ListView bug fix
+
+Joe Lafiosca @lafiosca Added Javascript file loader
+
+galapagosit @galapagosit ccs.actionManager bug fix
+
+Dany Ellement @DEllement cc.FontDefinition & ccui.RichText improvements
+ cc.LayerGradient improvements
+
+IShm @IShm cc.Screen bug fix
+ cc.ParticleSystem bug fix
+ ccui.PageView bug fix
+
+Thomas Jablonski @thomas-jablonski cc.audioEngine bug fix
+ Cocostudio typo fix
+
+WingGao @WingGao cc.TMXLayer bug fix
+
+Skliar Ihor @igogo5yo Add Bower support
+
+feijing566 @feijing566 cc.Audio bug fix
+
+RackovychV @RackovychV Fixed a bug of `cc.Scheduler`'s `pauseAllTargetsWithMinPriority`
+
+
+Retired Core Developers:
+ Shengxiang Chen (Nero Chan)
+ Xingsen Ma
Cocos2d-x and cocos2d-html5 can not grow so fast without the active community.
-Thanks to all developers who report & trace bugs, dicuss the engine usage in forum & QQ groups!
+Thanks to all developers who report & trace bugs, discuss the engine usage in forum & QQ groups!
Special thanks to Ricardo Quesada for giving us lots of guidances & suggestions.
diff --git a/Base64Images.js b/Base64Images.js
index 8f7cce4362..0d983506be 100644
--- a/Base64Images.js
+++ b/Base64Images.js
@@ -1,7 +1,6 @@
/****************************************************************************
- 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/CCBoot.js b/CCBoot.js
index 4d4d2d3cd7..1be2d4ff3b 100644
--- a/CCBoot.js
+++ b/CCBoot.js
@@ -1,7 +1,6 @@
/****************************************************************************
- 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,8 +23,13 @@
THE SOFTWARE.
****************************************************************************/
+/**
+ * The main namespace of Cocos2d-JS, all engine core classes, functions, properties and constants are defined in this namespace
+ * @namespace
+ * @name cc
+ */
var cc = cc || {};
-var _tmp = _tmp || {};
+cc._tmp = cc._tmp || {};
cc._LogInfos = {};
/** @expose */
@@ -67,22 +71,98 @@ cc._isNodeJs = typeof require !== 'undefined' && require("fs");
* Iterate over an object or an array, executing a function for each matched element.
* @param {object|array} obj
* @param {function} iterator
- * @param {object} context
* @param {object} [context]
*/
cc.each = function (obj, iterator, context) {
- if (!obj) return;
+ if (!obj)
+ return;
if (obj instanceof Array) {
for (var i = 0, li = obj.length; i < li; i++) {
- if (iterator.call(context, obj[i], i) === false) return;
+ if (iterator.call(context, obj[i], i) === false)
+ return;
}
} else {
for (var key in obj) {
- if (iterator.call(context, obj[key], key) === false) return;
+ if (iterator.call(context, obj[key], key) === false)
+ return;
}
}
};
+/**
+ * Copy all of the properties in source objects to target object and return the target object.
+ * @param {object} target
+ * @param {object} *sources
+ * @returns {object}
+ */
+cc.extend = function(target) {
+ var sources = arguments.length >= 2 ? Array.prototype.slice.call(arguments, 1) : [];
+
+ cc.each(sources, function(src) {
+ for(var key in src) {
+ if (src.hasOwnProperty(key)) {
+ target[key] = src[key];
+ }
+ }
+ });
+ return target;
+};
+
+/**
+ * Check the obj whether is function or not
+ * @param {*} obj
+ * @returns {boolean}
+ */
+cc.isFunction = function(obj) {
+ return typeof obj === 'function';
+};
+
+/**
+ * Check the obj whether is number or not
+ * @param {*} obj
+ * @returns {boolean}
+ */
+cc.isNumber = function(obj) {
+ return typeof obj === 'number' || Object.prototype.toString.call(obj) === '[object Number]';
+};
+
+/**
+ * Check the obj whether is string or not
+ * @param {*} obj
+ * @returns {boolean}
+ */
+cc.isString = function(obj) {
+ return typeof obj === 'string' || Object.prototype.toString.call(obj) === '[object String]';
+};
+
+/**
+ * Check the obj whether is array or not
+ * @param {*} obj
+ * @returns {boolean}
+ */
+cc.isArray = function(obj) {
+ return Array.isArray(obj) ||
+ (typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Array]');
+};
+
+/**
+ * Check the obj whether is undefined or not
+ * @param {*} obj
+ * @returns {boolean}
+ */
+cc.isUndefined = function(obj) {
+ return typeof obj === 'undefined';
+};
+
+/**
+ * Check the obj whether is object or not
+ * @param {*} obj
+ * @returns {boolean}
+ */
+cc.isObject = function(obj) {
+ return typeof obj === "object" && Object.prototype.toString.call(obj) === '[object Object]';
+};
+
/**
* Check the url whether cross origin
* @param {String} url
@@ -94,125 +174,206 @@ cc.isCrossOrigin = function (url) {
return false;
}
var startIndex = url.indexOf("://");
- if (startIndex == -1)
+ if (startIndex === -1)
return false;
var endIndex = url.indexOf("/", startIndex + 3);
- var urlOrigin = (endIndex == -1) ? url : url.substring(0, endIndex);
- return urlOrigin != location.origin;
+ var urlOrigin = (endIndex === -1) ? url : url.substring(0, endIndex);
+ return urlOrigin !== location.origin;
};
//+++++++++++++++++++++++++something about async begin+++++++++++++++++++++++++++++++
-cc.async = {
- // Counter for cc.async
- _counterFunc: function (err) {
- var counter = this.counter;
- if (counter.err) return;
- var length = counter.length;
- var results = counter.results;
- var option = counter.option;
- var cb = option.cb, cbTarget = option.cbTarget, trigger = option.trigger, triggerTarget = option.triggerTarget;
- if (err) {
- counter.err = err;
- if (cb) return cb.call(cbTarget, err);
- return;
+/**
+ * Async Pool class, a helper of cc.async
+ * @param {Object|Array} srcObj
+ * @param {Number} limit the limit of parallel number
+ * @param {function} iterator
+ * @param {function} onEnd
+ * @param {object} target
+ * @constructor
+ */
+cc.AsyncPool = function(srcObj, limit, iterator, onEnd, target){
+ var self = this;
+ self._srcObj = srcObj;
+ self._limit = limit;
+ self._pool = [];
+ self._iterator = iterator;
+ self._iteratorTarget = target;
+ self._onEnd = onEnd;
+ self._onEndTarget = target;
+ self._results = srcObj instanceof Array ? [] : {};
+ self._isErr = false;
+
+ cc.each(srcObj, function(value, index){
+ self._pool.push({index : index, value : value});
+ });
+
+ self.size = self._pool.length;
+ self.finishedSize = 0;
+ self._workingSize = 0;
+
+ self._limit = self._limit || self.size;
+
+ self.onIterator = function(iterator, target){
+ self._iterator = iterator;
+ self._iteratorTarget = target;
+ };
+
+ self.onEnd = function(endCb, endCbTarget){
+ self._onEnd = endCb;
+ self._onEndTarget = endCbTarget;
+ };
+
+ self._handleItem = function(){
+ var self = this;
+ if(self._pool.length === 0 || self._workingSize >= self._limit)
+ return; //return directly if the array's length = 0 or the working size great equal limit number
+
+ var item = self._pool.shift();
+ var value = item.value, index = item.index;
+ self._workingSize++;
+ self._iterator.call(self._iteratorTarget, value, index,
+ function(err) {
+ if (self._isErr)
+ return;
+
+ self.finishedSize++;
+ self._workingSize--;
+ if (err) {
+ self._isErr = true;
+ if (self._onEnd)
+ self._onEnd.call(self._onEndTarget, err);
+ return;
+ }
+
+ var arr = Array.prototype.slice.call(arguments, 1);
+ self._results[this.index] = arr[0];
+ if (self.finishedSize === self.size) {
+ if (self._onEnd)
+ self._onEnd.call(self._onEndTarget, null, self._results);
+ return;
+ }
+ self._handleItem();
+ }.bind(item),
+ self);
+ };
+
+ self.flow = function(){
+ var self = this;
+ if(self._pool.length === 0) {
+ if(self._onEnd)
+ self._onEnd.call(self._onEndTarget, null, []);
+ return;
}
- var result = Array.apply(null, arguments).slice(1);
- var l = result.length;
- if (l == 0) result = null;
- else if (l == 1) result = result[0];
- else result = result;
- results[this.index] = result;
- counter.count--;
- if (trigger) trigger.call(triggerTarget, result, length - counter.count, length);
- if (counter.count == 0 && cb) cb.apply(cbTarget, [null, results]);
- },
+ for(var i = 0; i < self._limit; i++)
+ self._handleItem();
+ }
+};
- // Empty function for async.
- _emptyFunc: function () {
+/**
+ * @class
+ */
+cc.async = /** @lends cc.async# */{
+ /**
+ * Do tasks series.
+ * @param {Array|Object} tasks
+ * @param {function} [cb] callback
+ * @param {Object} [target]
+ * @return {cc.AsyncPool}
+ */
+ series : function(tasks, cb, target){
+ var asyncPool = new cc.AsyncPool(tasks, 1, function(func, index, cb1){
+ func.call(target, cb1);
+ }, cb, target);
+ asyncPool.flow();
+ return asyncPool;
},
/**
* Do tasks parallel.
- * @param {array} tasks
- * @param {object|function} [option]
- * @param {function} [cb]
+ * @param {Array|Object} tasks
+ * @param {function} cb callback
+ * @param {Object} [target]
+ * @return {cc.AsyncPool}
*/
- parallel: function (tasks, option, cb) {
- var async = cc.async;
- if (cb !== undefined) {
- if (typeof option == "function") option = {trigger: option};
- option.cb = cb || option.cb;
- }
- else if (option !== undefined) {
- if (typeof option == "function") option = {cb: option};
- } else if (tasks !== undefined) option = {};
- else throw "arguments error!";
- var isArr = tasks instanceof Array;
- var li = isArr ? tasks.length : Object.keys(tasks).length;
- if (li == 0) {
- if (option.cb) option.cb.call(option.cbTarget, null);
- return;
- }
- var results = isArr ? [] : {};
- var counter = { length: li, count: li, option: option, results: results};
+ parallel : function(tasks, cb, target){
+ var asyncPool = new cc.AsyncPool(tasks, 0, function(func, index, cb1){
+ func.call(target, cb1);
+ }, cb, target);
+ asyncPool.flow();
+ return asyncPool;
+ },
- cc.each(tasks, function (task, index) {
- if (counter.err) return false;
- var counterFunc = !option.cb && !option.trigger ? async._emptyFunc : async._counterFunc.bind({counter: counter, index: index});//bind counter and index
- task(counterFunc, index);
- });
+ /**
+ * Do tasks waterfall.
+ * @param {Array|Object} tasks
+ * @param {function} cb callback
+ * @param {Object} [target]
+ * @return {cc.AsyncPool}
+ */
+ waterfall : function(tasks, cb, target){
+ var args = [];
+ var lastResults = [null];//the array to store the last results
+ var asyncPool = new cc.AsyncPool(tasks, 1,
+ function (func, index, cb1) {
+ args.push(function (err) {
+ args = Array.prototype.slice.call(arguments, 1);
+ if(tasks.length - 1 === index) lastResults = lastResults.concat(args);//while the last task
+ cb1.apply(null, arguments);
+ });
+ func.apply(target, args);
+ }, function (err) {
+ if (!cb)
+ return;
+ if (err)
+ return cb.call(target, err);
+ cb.apply(target, lastResults);
+ });
+ asyncPool.flow();
+ return asyncPool;
},
/**
* Do tasks by iterator.
- * The format of the option should be:
- * {
- * cb: function,
- * target: object,
- * iterator: function,
- * iteratorTarget: function
- * }
- * @param {array} tasks
- * @param {object|function} [option]
- * @param {function} [cb]
+ * @param {Array|Object} tasks
+ * @param {function|Object} iterator
+ * @param {function} [callback]
+ * @param {Object} [target]
+ * @return {cc.AsyncPool}
*/
- map: function (tasks, option, cb) {
- var self = this;
- var len = arguments.length;
- if (typeof option == "function")
- option = {iterator: option};
- if (len === 3)
- option.cb = cb || option.cb;
- else if (len == 2);
- else
- throw "arguments error!";
- if (typeof option == "function") option = {iterator: option};
- if (cb !== undefined)
- option.cb = cb || option.cb;
- else if (option !== undefined)
- ;
- else throw "arguments error!";
- var isArr = tasks instanceof Array;
- var li = isArr ? tasks.length : Object.keys(tasks).length;
- if (li == 0) {
- if (option.cb) option.cb.call(option.cbTarget, null);
- return;
+ map : function(tasks, iterator, callback, target){
+ var locIterator = iterator;
+ if(typeof(iterator) === "object"){
+ callback = iterator.cb;
+ target = iterator.iteratorTarget;
+ locIterator = iterator.iterator;
}
- var results = isArr ? [] : {};
- var counter = { length: li, count: li, option: option, results: results};
- cc.each(tasks, function (task, index) {
- if (counter.err) return false;
- var counterFunc = !option.cb ? self._emptyFunc : self._counterFunc.bind({counter: counter, index: index});//bind counter and index
- option.iterator.call(option.iteratorTarget, task, index, counterFunc);
- });
+ var asyncPool = new cc.AsyncPool(tasks, 0, locIterator, callback, target);
+ asyncPool.flow();
+ return asyncPool;
+ },
+
+ /**
+ * Do tasks by iterator limit.
+ * @param {Array|Object} tasks
+ * @param {Number} limit
+ * @param {function} iterator
+ * @param {function} cb callback
+ * @param {Object} [target]
+ */
+ mapLimit : function(tasks, limit, iterator, cb, target){
+ var asyncPool = new cc.AsyncPool(tasks, limit, iterator, cb, target);
+ asyncPool.flow();
+ return asyncPool;
}
};
//+++++++++++++++++++++++++something about async end+++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++something about path begin++++++++++++++++++++++++++++++++
-cc.path = {
-
+/**
+ * @class
+ */
+cc.path = /** @lends cc.path# */{
/**
* Join strings to be a path.
* @example
@@ -227,7 +388,7 @@ cc.path = {
var l = arguments.length;
var result = "";
for (var i = 0; i < l; i++) {
- result = (result + (result == "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");
+ result = (result + (result === "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");
}
return result;
},
@@ -247,6 +408,20 @@ cc.path = {
return temp ? temp[1] : null;
},
+ /**
+ * Get the main name of a file name
+ * @param {string} fileName
+ * @returns {string}
+ */
+ mainFileName: function(fileName){
+ if(fileName){
+ var idx = fileName.lastIndexOf(".");
+ if(idx !== -1)
+ return fileName.substring(0,idx);
+ }
+ return fileName;
+ },
+
/**
* Get the file name of a file path.
* @example
@@ -266,21 +441,27 @@ cc.path = {
var result = reg.exec(pathStr.replace(/(\/|\\\\)$/, ""));
if (!result) return null;
var baseName = result[2];
- if (extname && pathStr.substring(pathStr.length - extname.length).toLowerCase() == extname.toLowerCase())
+ if (extname && pathStr.substring(pathStr.length - extname.length).toLowerCase() === extname.toLowerCase())
return baseName.substring(0, baseName.length - extname.length);
return baseName;
},
/**
- * Get ext name of a file path.
+ * Get dirname of a file path.
* @example
+ * unix
cc.path.driname("a/b/c.png");//-->"a/b"
cc.path.driname("a/b/c.png?a=1&b=2");//-->"a/b"
+ cc.path.dirname("a/b/");//-->"a/b"
+ cc.path.dirname("c.png");//-->""
+ * windows
+ cc.path.driname("a\\b\\c.png");//-->"a\b"
+ cc.path.driname("a\\b\\c.png?a=1&b=2");//-->"a\b"
* @param {string} pathStr
* @returns {*}
*/
dirname: function (pathStr) {
- return pathStr.replace(/(\/|\\\\)$/, "").replace(/(\/|\\\\)[^(\/|\\\\)]+$/, "");
+ return pathStr.replace(/((.*)(\/|\\|\\\\))?(.*?\..*$)?/, '$2');
},
/**
@@ -318,7 +499,7 @@ cc.path = {
* @returns {string}
*/
changeBasename: function (pathStr, basename, isSameExt) {
- if (basename.indexOf(".") == 0) return this.changeExtname(pathStr, basename);
+ if (basename.indexOf(".") === 0) return this.changeExtname(pathStr, basename);
var index = pathStr.indexOf("?");
var tempStr = "";
var ext = isSameExt ? this.extname(pathStr) : "";
@@ -334,7 +515,11 @@ cc.path = {
//+++++++++++++++++++++++++something about path end++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++something about loader start+++++++++++++++++++++++++++
-cc.loader = {
+/**
+ * Loader for resource loading process. It's a singleton object.
+ * @class
+ */
+cc.loader = /** @lends cc.loader# */{
_jsCache: {},//cache for js
_register: {},//register of loaders
_langPathCache: {},//cache for lang path
@@ -360,7 +545,7 @@ cc.loader = {
if (args.length === 1) {
results[1] = a0 instanceof Array ? a0 : [a0];
} else if (args.length === 2) {
- if (typeof a1 == "function") {
+ if (typeof a1 === "function") {
results[1] = a0 instanceof Array ? a0 : [a0];
results[2] = a1;
} else {
@@ -379,23 +564,24 @@ cc.loader = {
* Load js files.
* If the third parameter doesn't exist, then the baseDir turns to be "".
*
- * @param {string} [baseDir] The pre path for jsList.
+ * @param {string} [baseDir] The pre path for jsList or the list of js path.
* @param {array} jsList List of js path.
- * @param {function} [cb] Callback function
+ * @param {function} [cb] Callback function
* @returns {*}
*/
loadJs: function (baseDir, jsList, cb) {
var self = this, localJsCache = self._jsCache,
args = self._getArgs4Js(arguments);
+ var preDir = args[0], list = args[1], callback = args[2];
if (navigator.userAgent.indexOf("Trident/5") > -1) {
- self._loadJs4Dependency(args[0], args[1], 0, args[2]);
+ self._loadJs4Dependency(preDir, list, 0, callback);
} else {
- cc.async.map(args[1], function (item, index, cb1) {
- var jsPath = cc.path.join(args[0], item);
+ cc.async.map(list, function (item, index, cb1) {
+ var jsPath = cc.path.join(preDir, item);
if (localJsCache[jsPath]) return cb1(null);
self._createScript(jsPath, false, cb1);
- }, args[2]);
+ }, callback);
}
},
/**
@@ -417,13 +603,22 @@ cc.loader = {
_createScript: function (jsPath, isAsync, cb) {
var d = document, self = this, s = cc.newElement('script');
s.async = isAsync;
- s.src = jsPath;
self._jsCache[jsPath] = true;
+ if(cc.game.config["noCache"] && typeof jsPath === "string"){
+ if(self._noCacheRex.test(jsPath))
+ s.src = jsPath + "&_t=" + (new Date() - 0);
+ else
+ s.src = jsPath + "?_t=" + (new Date() - 0);
+ }else{
+ s.src = jsPath;
+ }
cc._addEventListener(s, 'load', function () {
+ s.parentNode.removeChild(s);
this.removeEventListener('load', arguments.callee, false);
cb();
}, false);
cc._addEventListener(s, 'error', function () {
+ s.parentNode.removeChild(s);
cb("Load " + jsPath + " failed!");
}, false);
d.body.appendChild(s);
@@ -476,12 +671,14 @@ cc.loader = {
// IE-specific logic here
xhr.setRequestHeader("Accept-Charset", "utf-8");
xhr.onreadystatechange = function () {
- xhr.readyState == 4 && xhr.status == 200 ? cb(null, xhr.responseText) : cb(errInfo);
+ if(xhr.readyState === 4)
+ xhr.status === 200 ? cb(null, xhr.responseText) : cb(errInfo);
};
} else {
if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
xhr.onload = function () {
- xhr.readyState == 4 && xhr.status == 200 ? cb(null, xhr.responseText) : cb(errInfo);
+ if(xhr.readyState === 4)
+ xhr.status === 200 ? cb(null, xhr.responseText) : cb(errInfo);
};
}
xhr.send(null);
@@ -503,7 +700,7 @@ cc.loader = {
if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
}
xhr.send(null);
- if (!xhr.readyState == 4 || xhr.status != 200) {
+ if (!xhr.readyState === 4 || xhr.status !== 200) {
return null;
}
return xhr.responseText;
@@ -513,6 +710,23 @@ cc.loader = {
}
},
+ loadCsb: function(url, cb){
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, true);
+ xhr.responseType = "arraybuffer";
+
+ xhr.onload = function () {
+ var arrayBuffer = xhr.response; // Note: not oReq.responseText
+ if (arrayBuffer) {
+ window.msg = arrayBuffer;
+ }
+ if(xhr.readyState === 4)
+ xhr.status === 200 ? cb(null, xhr.response) : cb("load " + url + " failed!");
+ };
+
+ xhr.send(null);
+ },
+
/**
* Load a single resource as json.
* @param {string} url
@@ -520,10 +734,18 @@ cc.loader = {
*/
loadJson: function (url, cb) {
this.loadTxt(url, function (err, txt) {
- try {
- err ? cb(err) : cb(null, JSON.parse(txt));
- } catch (e) {
- throw "load json [" + url + "] failed : " + e;
+ if (err) {
+ cb(err);
+ }
+ else {
+ try {
+ var result = JSON.parse(txt);
+ }
+ catch (e) {
+ throw "parse json [" + url + "] failed : " + e;
+ return;
+ }
+ cb(null, result);
}
});
},
@@ -536,37 +758,52 @@ cc.loader = {
* Load a single image.
* @param {!string} url
* @param {object} [option]
- * @param {function} cb
- * @param {string} url
- * @param {object} [option]
- * @param {function} [cb]
+ * @param {function} callback
* @returns {Image}
*/
- loadImg: function (url, option, cb) {
+ loadImg: function (url, option, callback) {
var opt = {
isCrossOrigin: true
};
- if (cb !== undefined) {
- opt.isCrossOrigin = option.isCrossOrigin == null ? opt.isCrossOrigin : option.isCrossOrigin;
- }
+ if (callback !== undefined)
+ opt.isCrossOrigin = option.isCrossOrigin === null ? opt.isCrossOrigin : option.isCrossOrigin;
else if (option !== undefined)
- cb = option;
+ callback = option;
+
+ var img = this.getRes(url);
+ if (img) {
+ callback && callback(null, img);
+ return img;
+ }
- var img = new Image();
- if (opt.isCrossOrigin)
+ img = new Image();
+ if (opt.isCrossOrigin && location.origin !== "file://")
img.crossOrigin = "Anonymous";
- cc._addEventListener(img, "load", function () {
- this.removeEventListener('load', arguments.callee, false);
- this.removeEventListener('error', arguments.callee, false);
- if (cb)
- cb(null, img);
- });
- cc._addEventListener(img, "error", function () {
- this.removeEventListener('error', arguments.callee, false);
- if (cb)
- cb("load image failed");
- });
+ var loadCallback = function () {
+ this.removeEventListener('load', loadCallback, false);
+ this.removeEventListener('error', errorCallback, false);
+
+ cc.loader.cache[url] = img;
+ if (callback)
+ callback(null, img);
+ };
+
+ var self = this;
+ var errorCallback = function () {
+ this.removeEventListener('error', errorCallback, false);
+
+ if(img.crossOrigin && img.crossOrigin.toLowerCase() === "anonymous"){
+ opt.isCrossOrigin = false;
+ self.release(url);
+ cc.loader.loadImg(url, opt, callback);
+ }else{
+ typeof callback === "function" && callback("load image failed");
+ }
+ };
+
+ cc._addEventListener(img, "load", loadCallback);
+ cc._addEventListener(img, "error", errorCallback);
img.src = url;
return img;
},
@@ -590,18 +827,30 @@ cc.loader = {
type = cc.path.extname(url);
}
- var obj = self.cache[url];
+ var obj = self.getRes(url);
if (obj)
return cb(null, obj);
- var loader = self._register[type.toLowerCase()];
- if (!loader)
- return cb("loader for [" + type + "] not exists!");
+ var loader = null;
+ if (type) {
+ loader = self._register[type.toLowerCase()];
+ }
+ if (!loader) {
+ cc.error("loader for [" + type + "] not exists!");
+ return cb();
+ }
var basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
var realUrl = self.getUrl(basePath, url);
+ if(cc.game.config["noCache"] && typeof realUrl === "string"){
+ if(self._noCacheRex.test(realUrl))
+ realUrl += "&_t=" + (new Date() - 0);
+ else
+ realUrl += "?_t=" + (new Date() - 0);
+ }
loader.load(realUrl, url, item, function (err, data) {
if (err) {
cc.log(err);
self.cache[url] = null;
+ delete self.cache[url];
cb();
} else {
self.cache[url] = data;
@@ -609,6 +858,7 @@ cc.loader = {
}
});
},
+ _noCacheRex: /\?/,
/**
* Get url with basePath.
@@ -623,12 +873,15 @@ cc.loader = {
var type = path.extname(url);
type = type ? type.toLowerCase() : "";
var loader = self._register[type];
- if (!loader) basePath = self.resPath;
- else basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
+ if (!loader)
+ basePath = self.resPath;
+ else
+ basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
}
- url = cc.path.join(basePath || "", url)
+ url = cc.path.join(basePath || "", url);
if (url.match(/[\/(\\\\)]lang[\/(\\\\)]/i)) {
- if (langPathCache[url]) return langPathCache[url];
+ if (langPathCache[url])
+ return langPathCache[url];
var extname = path.extname(url) || "";
url = langPathCache[url] = url.substring(0, url.length - extname.length) + "_" + cc.sys.language + extname;
}
@@ -637,36 +890,48 @@ cc.loader = {
/**
* Load resources then call the callback.
- * @param {string} res
- * @param {function|Object} [option] option or cb
- * @param {function} [cb]
+ * @param {string} resources
+ * @param {function} [option] callback or trigger
+ * @param {function|Object} [loadCallback]
+ * @return {cc.AsyncPool}
*/
- load: function (res, option, cb) {
- if (cb !== undefined) {
- if (typeof option == "function")
- option = {trigger: option};
- }
- else if (option !== undefined) {
- if (typeof option == "function") {
- cb = option;
- option = {};
+ load : function(resources, option, loadCallback){
+ var self = this;
+ var len = arguments.length;
+ if(len === 0)
+ throw "arguments error!";
+
+ if(len === 3){
+ if(typeof option === "function"){
+ if(typeof loadCallback === "function")
+ option = {trigger : option, cb : loadCallback };
+ else
+ option = { cb : option, cbTarget : loadCallback};
}
- }
- else if (res !== undefined)
+ }else if(len === 2){
+ if(typeof option === "function")
+ option = {cb : option};
+ }else if(len === 1){
option = {};
- else
- throw "arguments error!";
- option.cb = function (err, results) {
- if (err)
- cc.log(err);
- if (cb)
- cb(results);
- };
- if (!(res instanceof Array))
- res = [res];
- option.iterator = this._loadResIterator;
- option.iteratorTarget = this;
- cc.async.map(res, option);
+ }
+
+ if(!(resources instanceof Array))
+ resources = [resources];
+ var asyncPool = new cc.AsyncPool(
+ resources, 0,
+ function (value, index, AsyncPoolCallback, aPool) {
+ self._loadResIterator(value, index, function (err) {
+ if (err)
+ return AsyncPoolCallback(err);
+ var arr = Array.prototype.slice.call(arguments, 1);
+ if (option.trigger)
+ option.trigger.call(option.triggerTarget, arr[0], aPool.size, aPool.finishedSize); //call trigger
+ AsyncPoolCallback(null, arr[0]);
+ });
+ },
+ option.cb, option.cbTarget);
+ asyncPool.flow();
+ return asyncPool;
},
_handleAliases: function (fileNames, cb) {
@@ -706,27 +971,29 @@ cc.loader = {
*
*
*
called once per frame. time a value between 0 and 1
- -For example:
- - 0 means that the action just started
- - 0.5 means that the action is in the middle
- - 1 means that the action is over
Base class actions that do have a finite time duration.
+ * Base class actions that do have a finite time duration.
* Possible actions:
- * - An action with a duration of 0 seconds
- * - An action with a duration of 35.5 seconds
Returns the Cardinal Spline position for a given set of control points, tension and time CatmullRom Spline formula:
- * s(-ttt + 2tt - t)P1 + s(-ttt + tt)P2 + (2ttt - 3tt + 1)P2 + s(ttt - 2tt + t)P3 + (-2ttt + 3tt)P3 + s(ttt - tt)P4
- *
- * An action that moves the target with a CatmullRom curve to a destination point.
- * A Catmull Rom is a Cardinal Spline with a tension of 0.5.
- * http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline
- *
- * An action that moves the target with a CatmullRom curve by a certain distance.
- * A Catmull Rom is a Cardinal Spline with a tension of 0.5.
- * http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline
- *
+ * Executes an action in reverse order, from time=duration to time=0
+ * @warning Use this action carefully. This action is not sequenceable.
+ * Use it as the default "reversed" method of your own actions, but using it outside the "reversed"
* scope is not recommended.
+ *
@@ -2640,14 +3445,16 @@ cc.Animate.create = function (animation) { *
* @class * @extends cc.ActionInterval + * @param {cc.Node} target + * @param {cc.FiniteTimeAction} action */ cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{ _action:null, _forcedTarget:null, /** - * Create an action with the specified action and forced target - * @constructor + * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
* cc.StopGrid action.
* @warning Don't call this action if another grid action is active.
* Call if you want to remove the the grid effect. Example:
- * cc.Sequence.create(Lens.action(...), cc.StopGrid.create(...), null);
+ * cc.sequence(Lens.action(...), cc.stopGrid(...), null);
*
* cc.ClippingNode is a subclass of cc.Node.
- * It draws its content (childs) clipped using a stencil.
+ * It draws its content (children) 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).
*
+ * Event callback that is invoked every time when node 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().
+ *
+ * Event callback that is invoked when the node enters in the 'stage'.
+ * If the node 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()
+ *
+ * callback that is called every time the node leaves the 'stage'.
+ * If the 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()
+ *
+ * callback that is called every time the node leaves the 'stage'.
+ * If the 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().
+ *
- * cc.director is a singleton of DisplayLinkDirector type director.
+ *
+ * ATTENTION: USE cc.director INSTEAD OF cc.Director.
+ * cc.director is a singleton object which manage your game's logic flow.
* Since the cc.director is a singleton, you don't need to call any constructor or create functions,
* the standard way to use it is by calling:
* - cc.director.methodName();
*
* It creates and handle the main Window and manages how and when to execute the Scenes.
*
- * The cc.Director is also responsible for:
+ * The cc.director is also responsible for:
* - initializing the OpenGL context
* - setting the OpenGL pixel format (default on is RGB565)
* - setting the OpenGL pixel format (default on is RGB565)
* - setting the OpenGL buffer depth (default one is 0-bit)
* - setting the projection (default one is 3D)
- * - setting the orientation (default one is Protrait)
+ * - setting the orientation (default one is Portrait)
*
*
* The cc.director also sets the default OpenGL context:
@@ -62,70 +64,67 @@ cc.GLToClipTransform = function (transformOut) {
* - GL_TEXTURE_COORD_ARRAY is enabled
*
- * With DisplayLinkDirector functionality, cc.director synchronizes timers with the refresh rate of the display.
+ * cc.director also synchronizes timers with the refresh rate of the display.
* Features and Limitations:
* - Scheduled timers & drawing are synchronizes with the refresh rate of the display
* - Only supports animation intervals of 1/60 1/30 & 1/15
*
get the size in pixels of the surface. It could be different than the screen size.
- * High-res devices might have a higher surface size than the screen size.
- * Only available when compiled using SDK >= 4.0.
- *
- * This object will be visited after the main scene is visited.
- * This object MUST implement the "visit" selector.
- * Useful to hook a notification object, like CCNotifications (http://github.com/manucorporat/CCNotifications)
- *
- * returns the size of the OpenGL view in points.
- * It takes into account any possible rotation (device orientation) of the window
- *
- * returns the size of the OpenGL view in pixels.
- * It takes into account any possible rotation (device orientation) of the window.
- * On Mac winSize and winSizeInPixels return the same value.
- *
- * Pops out a scene from the queue.
- * This scene will replace the running one.
- * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated.
- * ONLY call it if there is a running scene.
- *
- * Suspends the execution of the running scene, pushing it on the stack of suspended scenes.
- * The new scene will be executed.
- * Try to avoid big stacks of pushed scenes to reduce memory allocation.
- * ONLY call it if there is a running scene.
- *
- * The size in pixels of the surface. It could be different than the screen size.
- * High-res devices might have a higher surface size than the screen size.
- * Only available when compiled using SDK >= 4.0.
- *
- * Whether or not the replaced scene will receive the cleanup message.
- * If the new scene is pushed, then the old scene won't receive the "cleanup" message.
- * If the new scene replaces the old one, the it will receive the "cleanup" message.
- *
- * Pops out all scenes from the queue until the root scene in the queue.
- * This scene will replace the running one.
- * Internally it will call `popToSceneStackLevel(1)`
- *
- * Pops out all scenes from the queue until it reaches `level`.
- * If level is 0, it will end the director.
- * If level is 1, it will pop all scenes until it reaches to root scene.
- * If level is <= than the current stack level, it won't do anything.
- *
- * converts a UIKit coordinate to an OpenGL coordinate
- * Useful to convert (multi) touches coordinates to the current layout (portrait or landscape)
- *
converts an OpenGL coordinate to a UIKit coordinate
- * Useful to convert node points to window points for calls such as glScissor
* Scheduler is responsible of triggering the scheduled callbacks.
@@ -276,43 +284,78 @@ cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{
*
* @example
* //register a schedule to scheduler
- * cc.director.getScheduler().scheduleSelector(callback, this, interval, !this._isRunning);
+ * cc.director.getScheduler().schedule(callback, this, interval, !this._isRunning);
*/
cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
_timeScale:1.0,
- _updates : null, //_updates[0] list of priority < 0, _updates[1] list of priority == 0, _updates[2] list of priority > 0,
-
- _hashForUpdates:null, // hash used to fetch quickly the list entries for pause,delete,etc
- _arrayForUpdates:null,
+ //_updates : null, //_updates[0] list of priority < 0, _updates[1] list of priority == 0, _updates[2] list of priority > 0,
+ _updatesNegList: null,
+ _updates0List: null,
+ _updatesPosList: null,
_hashForTimers:null, //Used for "selectors with interval"
- _arrayForTimes:null,
+ _arrayForTimers:null, //Speed up indexing
+ _hashForUpdates:null, // hash used to fetch quickly the list entries for pause,delete,etc
+ //_arrayForUpdates:null, //Speed up indexing
_currentTarget:null,
_currentTargetSalvaged:false,
_updateHashLocked:false, //If true unschedule will not remove anything from a hash. Elements will only be marked for deletion.
- /**
- * Constructor
- */
+
ctor:function () {
- var self = this;
- self._timeScale = 1.0;
- self._updates = [[], [], []];
+ this._timeScale = 1.0;
+ this._updatesNegList = [];
+ this._updates0List = [];
+ this._updatesPosList = [];
- self._hashForUpdates = {};
- self._arrayForUpdates = [];
+ this._hashForUpdates = {};
+ this._hashForTimers = {};
+ this._currentTarget = null;
+ this._currentTargetSalvaged = false;
+ this._updateHashLocked = false;
- self._hashForTimers = {};
- self._arrayForTimers = [];
+ this._arrayForTimers = [];
+ //this._arrayForUpdates = [];
- self._currentTarget = null;
- self._currentTargetSalvaged = false;
- self._updateHashLocked = false;
},
//-----------------------private method----------------------
+
+ _schedulePerFrame: function(callback, target, priority, paused){
+ var hashElement = this._hashForUpdates[target.__instanceId];
+ if (hashElement && hashElement.entry){
+ // check if priority has changed
+ if (hashElement.entry.priority !== priority){
+ if (this._updateHashLocked){
+ cc.log("warning: you CANNOT change update priority in scheduled function");
+ hashElement.entry.markedForDeletion = false;
+ hashElement.entry.paused = paused;
+ return;
+ }else{
+ // will be added again outside if (hashElement).
+ this.unscheduleUpdate(target);
+ }
+ }else{
+ hashElement.entry.markedForDeletion = false;
+ hashElement.entry.paused = paused;
+ return;
+ }
+ }
+
+ // most of the updates are going to be 0, that's way there
+ // is an special list for updates with priority 0
+ if (priority === 0){
+ this._appendIn(this._updates0List, callback, target, paused);
+ }else if (priority < 0){
+ this._priorityIn(this._updatesNegList, callback, target, priority, paused);
+ }else{
+ // priority > 0
+ this._priorityIn(this._updatesPosList, callback, target, priority, paused);
+ }
+ },
+
_removeHashElement:function (element) {
delete this._hashForTimers[element.target.__instanceId];
cc.arrayRemoveObject(this._arrayForTimers, element);
@@ -328,7 +371,7 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
cc.arrayRemoveObject(element.list, element.entry);
delete self._hashForUpdates[element.target.__instanceId];
- cc.arrayRemoveObject(self._arrayForUpdates, element);
+ //cc.arrayRemoveObject(self._hashForUpdates, element);
element.entry = null;
//hash entry
@@ -336,8 +379,9 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
}
},
- _priorityIn:function (ppList, target, priority, paused) {
- var self = this, listElement = new cc.ListEntry(null, null, target, priority, paused, false);
+ _priorityIn:function (ppList, callback, target, priority, paused) {
+ var self = this,
+ listElement = new cc.ListEntry(null, null, callback, target, priority, paused, false);
// empey list ?
if (!ppList) {
@@ -355,21 +399,17 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
}
//update hash entry for quick access
- var hashElement = new cc.HashUpdateEntry(ppList, listElement, target, null);
- self._arrayForUpdates.push(hashElement);
- self._hashForUpdates[target.__instanceId] = hashElement;
+ self._hashForUpdates[target.__instanceId] = new cc.HashUpdateEntry(ppList, listElement, target, null);
return ppList;
},
- _appendIn:function (ppList, target, paused) {
- var self = this, listElement = new cc.ListEntry(null, null, target, 0, paused, false);
+ _appendIn:function (ppList, callback, target, paused) {
+ var self = this, listElement = new cc.ListEntry(null, null, callback, target, 0, paused, false);
ppList.push(listElement);
//update hash entry for quicker access
- var hashElement = new cc.HashUpdateEntry(ppList, listElement, target, null);
- self._arrayForUpdates.push(hashElement);
- self._hashForUpdates[target.__instanceId] = hashElement;
+ self._hashForUpdates[target.__instanceId] = new cc.HashUpdateEntry(ppList, listElement, target, null, null);
},
//-----------------------public method-------------------------
@@ -388,7 +428,7 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
},
/**
- * returns time scale of scheduler
+ * Returns time scale of scheduler
* @return {Number}
*/
getTimeScale:function () {
@@ -400,33 +440,40 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
* @param {Number} dt delta time
*/
update:function (dt) {
- var self = this;
- var locUpdates = self._updates, locArrayForTimers = self._arrayForTimers;
- var tmpEntry, elt, i, li;
- self._updateHashLocked = true;
-
- if (this._timeScale != 1.0) {
+ this._updateHashLocked = true;
+ if(this._timeScale !== 1)
dt *= this._timeScale;
+
+ var i, list, len, entry;
+
+ for(i=0,list=this._updatesNegList, len = list.length; i
*
- * 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.
- *
- * Unschedule a callback function for a given target.
- * If you want to unschedule the "update", use unscheudleUpdateForTarget.
- *
- * Unschedules all function callbacks from all targets.
- * You should NEVER call this method, unless you know what you are doing.
- *
- * Unschedules all function callbacks from all targets with a minimum priority.
- * You should only call this with kCCPriorityNonSystemMin or higher.
- *
+ * 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.
+ *
+ * Unschedule a callback function for a given target.
+ * If you want to unschedule the "update", use unscheudleUpdateForTarget.
+ *
+ * Unschedules all function callbacks from all targets.
+ * You should NEVER call this method, unless you know what you are doing.
+ *
+ * Unschedules all function callbacks from all targets with a minimum priority.
+ * You should only call this with kCCPriorityNonSystemMin or higher.
+ *
cc.AtlasNode is a subclass of cc.Node that implements the cc.RGBAProtocol and
- * cc.TextureProtocol protocol
cc.AtlasNode is a subclass of cc.Node, it knows how to render a TextureAtlas object.
* - * 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)
If you are going to render a TextureAtlas consider subclassing cc.AtlasNode (or a subclass of cc.AtlasNode)
+ * + *All features from cc.Node are valid
+ * + *You can create a cc.AtlasNode with an Atlas file, the width, the height of each item and the quantity of items to render
* - * All features from cc.Node are valid, plus the following features:
- * - opacity and RGB colors
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 - * @example - * var node = new cc.AtlasNode("pathOfTile", 16, 16, 1); */ ctor: function (tile, tileWidth, tileHeight, itemsToRender) { - cc.NodeRGBA.prototype.ctor.call(this); - this._colorUnmodified = cc.color.WHITE; + 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); }, - /** updates the Atlas (indexed vertex array). - * Shall be overridden in subclasses + _createRenderCmd: function(){ + if(cc._renderType === cc._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.AtlasNode.updateAtlasValues(): Shall be overridden in subclasses"); + cc.log(cc._LogInfos.AtlasNode_updateAtlasValues); }, - /** cc.AtlasNode - RGBA protocol + /** + * Get color value of the atlas node + * @function * @return {cc.Color} */ getColor: function () { if (this._opacityModifyRGB) - return this._colorUnmodified; - return cc.NodeRGBA.prototype.getColor.call(this); + 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.color = oldColor; + this.setColor(oldColor); }, /** + * Get whether color should be changed with the opacity value + * @function * @return {Boolean} */ isOpacityModifyRGB: function () { return this._opacityModifyRGB; }, - /** cc.AtlasNode - CocosNodeTexture protocol + /** + * Get node's blend function + * @function * @return {cc.BlendFunc} */ getBlendFunc: function () { @@ -122,7 +142,9 @@ cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ }, /** - * BlendFunc setter + * 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 */ @@ -134,13 +156,17 @@ cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ }, /** - * @param {cc.TextureAtlas} value + * 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 () { @@ -148,6 +174,8 @@ cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ }, /** + * Get the number of quads to be rendered + * @function * @return {Number} */ getQuadsToDraw: function () { @@ -155,23 +183,21 @@ cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ }, /** + * Set the number of quads to be rendered + * @function * @param {Number} quadsToDraw */ setQuadsToDraw: function (quadsToDraw) { this.quadsToDraw = quadsToDraw; }, - _textureForCanvas: null, - _originalTexture: null, - - _uniformColor: null, - _colorF32Array: null, - - /** initializes an cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render - * @param {String} tile - * @param {Number} tileWidth - * @param {Number} tileHeight - * @param {Number} itemsToRender + /** + * 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) { @@ -182,216 +208,52 @@ cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ }, /** - * initializes an CCAtlasNode with a texture the width and height of each item measured in points and the quantity of items to render - * @param {cc.Texture2D} texture - * @param {Number} tileWidth - * @param {Number} tileHeight - * @param {Number} 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: null, - - _initWithTextureForCanvas: function (texture, tileWidth, tileHeight, itemsToRender) { - this._itemWidth = tileWidth; - this._itemHeight = tileHeight; - - this._opacityModifyRGB = true; - this._originalTexture = texture; - if (!this._originalTexture) { - cc.log("cocos2d: Could not initialize cc.AtlasNode. Invalid Texture."); - return false; - } - this._textureForCanvas = this._originalTexture; - this._calculateMaxItems(); - - this.quadsToDraw = itemsToRender; - return true; - }, - - _initWithTextureForWebGL: function (texture, tileWidth, tileHeight, itemsToRender) { - this._itemWidth = tileWidth; - this._itemHeight = tileHeight; - this._colorUnmodified = cc.color.WHITE; - this._opacityModifyRGB = true; - - this._blendFunc.src = cc.BLEND_SRC; - this._blendFunc.dst = cc.BLEND_DST; - - var locRealColor = this._realColor; - this._colorF32Array = new Float32Array([locRealColor.r / 255.0, locRealColor.g / 255.0, locRealColor.b / 255.0, this._realOpacity / 255.0]); - this.textureAtlas = new cc.TextureAtlas(); - this.textureAtlas.initWithTexture(texture, itemsToRender); - - if (!this.textureAtlas) { - cc.log("cocos2d: Could not initialize cc.AtlasNode. Invalid Texture."); - return false; - } - - this._updateBlendFunc(); - this._updateOpacityModifyRGB(); - this._calculateMaxItems(); - this.quadsToDraw = itemsToRender; - - //shader stuff - this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR); - this._uniformColor = cc._renderContext.getUniformLocation(this.shaderProgram.getProgram(), "u_color"); - return true; - }, - - draw: null, - - /** - * @param {WebGLRenderingContext} ctx renderContext - */ - _drawForWebGL: function (ctx) { - var context = ctx || cc._renderContext; - cc.nodeDrawSetup(this); - cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); - context.uniform4fv(this._uniformColor, this._colorF32Array); - this.textureAtlas.drawNumberOfQuads(this.quadsToDraw, 0); + initWithTexture: function(texture, tileWidth, tileHeight, itemsToRender){ + return this._renderCmd.initWithTexture(texture, tileWidth, tileHeight, itemsToRender); }, /** + * Set node's color * @function - * @param {cc.Color} color3 + * @param {cc.Color} color Color object created with cc.color(r, g, b). */ - setColor: null, - - _setColorForCanvas: function (color3) { - var locRealColor = this._realColor; - if ((locRealColor.r == color3.r) && (locRealColor.g == color3.g) && (locRealColor.b == color3.b)) - return; - var temp = cc.color(color3.r, color3.g, color3.b); - this._colorUnmodified = color3; - - if (this._opacityModifyRGB) { - var locDisplayedOpacity = this._displayedOpacity; - temp.r = temp.r * locDisplayedOpacity / 255; - temp.g = temp.g * locDisplayedOpacity / 255; - temp.b = temp.b * locDisplayedOpacity / 255; - } - cc.NodeRGBA.prototype.setColor.call(this, color3); - - if (this.texture) { - var element = this._originalTexture.getHtmlElementObj(); - if (!element) - return; - var cacheTextureForColor = cc.textureCache.getTextureColors(element); - if (cacheTextureForColor) { - var textureRect = cc.rect(0, 0, element.width, element.height); - element = cc.generateTintImage(element, cacheTextureForColor, this._realColor, textureRect); - var locTexture = new cc.Texture2D(); - locTexture.initWithElement(element); - locTexture.handleLoadedTexture(); - this.texture = locTexture; - } - } - }, - - _setColorForWebGL: function (color3) { - var temp = cc.color(color3.r, color3.g, color3.b); - this._colorUnmodified = color3; - var locDisplayedOpacity = this._displayedOpacity; - if (this._opacityModifyRGB) { - temp.r = temp.r * locDisplayedOpacity / 255; - temp.g = temp.g * locDisplayedOpacity / 255; - temp.b = temp.b * locDisplayedOpacity / 255; - } - cc.NodeRGBA.prototype.setColor.call(this, color3); - var locDisplayedColor = this._displayedColor; - this._colorF32Array = new Float32Array([locDisplayedColor.r / 255.0, locDisplayedColor.g / 255.0, - locDisplayedColor.b / 255.0, locDisplayedOpacity / 255.0]); + setColor: function(color){ + this._renderCmd.setColor(color); }, /** + * Set node's opacity * @function - * @param {Number} opacity + * @param {Number} opacity The opacity value */ setOpacity: function (opacity) { + this._renderCmd.setOpacity(opacity); }, - _setOpacityForCanvas: function (opacity) { - cc.NodeRGBA.prototype.setOpacity.call(this, opacity); - // special opacity for premultiplied textures - if (this._opacityModifyRGB) { - this.color = this._colorUnmodified; - } - }, - - _setOpacityForWebGL: function (opacity) { - cc.NodeRGBA.prototype.setOpacity.call(this, opacity); - // special opacity for premultiplied textures - if (this._opacityModifyRGB) { - this.color = this._colorUnmodified; - } else { - var locDisplayedColor = this._displayedColor; - this._colorF32Array = new Float32Array([locDisplayedColor.r / 255.0, locDisplayedColor.g / 255.0, - locDisplayedColor.b / 255.0, this._displayedOpacity / 255.0]); - } - }, - - // cc.Texture protocol /** - * returns the used texture + * Get the current texture * @function * @return {cc.Texture2D} */ - getTexture: null, - - _getTextureForCanvas: function () { - return this._textureForCanvas; - }, - - _getTextureForWebGL: function () { - return this.textureAtlas.texture; + getTexture: function(){ + return this._renderCmd.getTexture(); }, /** - * sets a new texture. it will be retained + * Replace the current texture with a new one * @function - * @param {cc.Texture2D} texture + * @param {cc.Texture2D} texture The new texture */ - setTexture: null, - - _setTextureForCanvas: function (texture) { - this._textureForCanvas = texture; - }, - - _setTextureForWebGL: function (texture) { - this.textureAtlas.texture = texture; - this._updateBlendFunc(); - this._updateOpacityModifyRGB(); - }, - - _calculateMaxItems: null, - - _calculateMaxItemsForCanvas: function () { - var selTexture = this.texture; - var size = selTexture.getContentSize(); - - this._itemsPerColumn = 0 | (size.height / this._itemHeight); - this._itemsPerRow = 0 | (size.width / this._itemWidth); - }, - - _calculateMaxItemsForWebGL: function () { - var selTexture = this.texture; - var size = selTexture.getContentSize(); - if (this._ignoreContentScaleFactor) - size = selTexture.getContentSizeInPixels(); - - this._itemsPerColumn = 0 | (size.height / this._itemHeight); - this._itemsPerRow = 0 | (size.width / this._itemWidth); - }, - - _updateBlendFunc: function () { - if (!this.textureAtlas.texture.hasPremultipliedAlpha()) { - this._blendFunc.src = cc.SRC_ALPHA; - this._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA; - } - }, - - _updateOpacityModifyRGB: function () { - this._opacityModifyRGB = this.textureAtlas.texture.hasPremultipliedAlpha(); + setTexture: function(texture){ + this._renderCmd.setTexture(texture); }, _setIgnoreContentScaleFactor: function (ignoreContentScaleFactor) { @@ -399,25 +261,8 @@ cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ } }); -var _p = cc.AtlasNode.prototype; -if (cc._renderType === cc._RENDER_TYPE_WEBGL) { - _p.initWithTexture = _p._initWithTextureForWebGL; - _p.draw = _p._drawForWebGL; - _p.setColor = _p._setColorForWebGL; - _p.setOpacity = _p._setOpacityForWebGL; - _p.getTexture = _p._getTextureForWebGL; - _p.setTexture = _p._setTextureForWebGL; - _p._calculateMaxItems = _p._calculateMaxItemsForWebGL; -} else { - _p.initWithTexture = _p._initWithTextureForCanvas; - _p.draw = cc.Node.prototype.draw; - _p.setColor = _p._setColorForCanvas; - _p.setOpacity = _p._setOpacityForCanvas; - _p.getTexture = _p._getTextureForCanvas; - _p.setTexture = _p._setTextureForCanvas; - _p._calculateMaxItems = _p._calculateMaxItemsForCanvas; -} +var _p = cc.AtlasNode.prototype; // Override properties cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity); cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor); @@ -431,18 +276,19 @@ _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 +/** + * 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} - * @example - * // example - * var node = cc.AtlasNode.create("pathOfTile", 16, 16, 1); */ 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..64e557c966 --- /dev/null +++ b/cocos2d/core/base-nodes/CCAtlasNodeCanvasRenderCmd.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. + ****************************************************************************/ + +/** + * cc.AtlasNode's rendering objects of Canvas + */ +(function(){ + cc.AtlasNode.CanvasRenderCmd = function(renderableObject){ + cc.Node.CanvasRenderCmd.call(this, renderableObject); + this._needDraw = false; + this._colorUnmodified = cc.color.WHITE; + this._originalTexture = null; + this._texture = 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; + this._originalTexture = texture; + if (!this._originalTexture) { + cc.log(cc._LogInfos.AtlasNode__initWithTexture); + return false; + } + this._texture = this._originalTexture; + 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(); + }; + + if(cc.sys._supportCanvasNewBlendModes) + proto._changeTextureColor = function(){ + var node = this._node; + var locTexture = node.getTexture(); + if (locTexture && this._originalTexture) { + var element = this._originalTexture.getHtmlElementObj(); + if(!element) + return; + var locElement = locTexture.getHtmlElementObj(); + var textureRect = cc.rect(0, 0, element.width, element.height); + if (locElement instanceof HTMLCanvasElement) + cc.Sprite.CanvasRenderCmd._generateTintImageWithMultiply(element, this._colorUnmodified, textureRect, locElement); + else { + locElement = cc.Sprite.CanvasRenderCmd._generateTintImageWithMultiply(element, this._colorUnmodified, textureRect); + locTexture = new cc.Texture2D(); + locTexture.initWithElement(locElement); + locTexture.handleLoadedTexture(); + node.setTexture(locTexture); + } + } + }; + else + proto._changeTextureColor = function(){ + var node = this._node; + var locElement, locTexture = node.getTexture(); + if (locTexture && this._originalTexture) { + locElement = locTexture.getHtmlElementObj(); + if (!locElement) + return; + var element = this._originalTexture.getHtmlElementObj(); + var cacheTextureForColor = cc.textureCache.getTextureColors(element); + if (cacheTextureForColor) { + var textureRect = cc.rect(0, 0, element.width, element.height); + if (locElement instanceof HTMLCanvasElement) + cc.Sprite.CanvasRenderCmd._generateTintImage(locElement, cacheTextureForColor, this._displayedColor, textureRect, locElement); + else { + locElement = cc.Sprite.CanvasRenderCmd._generateTintImage(locElement, cacheTextureForColor, this._displayedColor, textureRect); + locTexture = new cc.Texture2D(); + locTexture.initWithElement(locElement); + locTexture.handleLoadedTexture(); + node.setTexture(locTexture); + } + } + } + }; + + 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.getTexture = function(){ + return this._texture; + }; + + proto.setTexture = function (texture) { + this._texture = texture; + }; + + proto._calculateMaxItems = function(){ + var node = this._node; + var selTexture = this._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..d398f20eef --- /dev/null +++ b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js @@ -0,0 +1,145 @@ +/**************************************************************************** + 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){ + cc.Node.WebGLRenderCmd.call(this, renderableObject); + this._needDraw = true; + this._textureAtlas = null; + this._colorUnmodified = cc.color.WHITE; + this._colorF32Array = null; + this._uniformColor = null; + + //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; + + this._shaderProgram.use(); + this._shaderProgram._setUniformForMVPMatrixWithMat4(this._stackMatrix); + + 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(){ + var locDisplayedColor = this._displayedColor; + this._colorF32Array = new Float32Array([locDisplayedColor.r / 255.0, locDisplayedColor.g / 255.0, + locDisplayedColor.b / 255.0, 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); + }; +})(); \ No newline at end of file diff --git a/cocos2d/core/base-nodes/CCNode.js b/cocos2d/core/base-nodes/CCNode.js index 8435931689..5184a42b9c 100644 --- a/cocos2d/core/base-nodes/CCNode.js +++ b/cocos2d/core/base-nodes/CCNode.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,104 +30,103 @@ * @type Number */ cc.NODE_TAG_INVALID = -1; -/** - * Node on enter - * @constant - */ -cc.NODE_ON_ENTER = null; -/** - * Node on exit - * @constant - */ -cc.NODE_ON_EXIT = null; /** - * 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. - * @type Number + * 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 main element. Anything thats 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.
The main features of a cc.Node are:
- - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc)
- - They can schedule periodic callback (schedule, unschedule, etc)
- - They can execute actions (runAction, stopAction, etc)
Some cc.Node nodes provide extra functionality for them or their children.
- -Subclassing a cc.Node usually means (one/all) of:
- - overriding init to initialize resources and schedule callbacks
- - create callbacks to handle the advancement of time
- - overriding draw to render the node
Features of cc.Node:
- - position
- - scale (x, y)
- - rotation (in degrees, clockwise)
- - anchor point
- - size
- - visible
- - z-order
- - openGL z position
Default values:
- - rotation: 0
- - position: (x=0,y=0)
- - scale: (x=1,y=1)
- - contentSize: (x=0,y=0)
- - anchorPoint: (x=0,y=0)
Limitations:
- - A cc.Node is a "void" object. It doesn't have a texture
Order in transformations with grid disabled
- -# The node will be translated (position)
- -# The node will be rotated (rotation)
- -# The node will be scaled (scale)
-
-
Order in transformations with grid enabled
- -# The node will be translated (position)
- -# The node will be rotated (rotation)
- -# The node will be scaled (scale)
- -# The grid will capture the screen
- -# The node will be moved according to the camera values (camera)
- -# The grid will render the captured screen
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.
The main features of a cc.Node are:
+ * - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc)
+ * - They can schedule periodic callback (schedule, unschedule, etc)
+ * - They can execute actions (runAction, stopAction, etc)
Some cc.Node nodes provide extra functionality for them or their children.
+ * + *Subclassing a cc.Node usually means (one/all) of:
+ * - overriding constructor function "ctor" to initialize resources and schedule callbacks
+ * - create callbacks to handle the advancement of time
Features of cc.Node:
+ * - position
+ * - scale (x, y)
+ * - rotation (in degrees, clockwise)
+ * - anchor point
+ * - size
+ * - color
+ * - opacity
+ * - visible
+ * - z-order
+ * - WebGL z position
Default values:
+ * - rotation: 0
+ * - position: (x=0,y=0)
+ * - scale: (x=1,y=1)
+ * - contentSize: (x=0,y=0)
+ * - anchorPoint: (x=0,y=0)
+ * - color: (r=255,g=255,b=255)
+ * - opacity: 255
Limitations:
+ * - A cc.Node is a "void" object. It doesn't have a texture
Order in transformations with grid disabled
+ * -# The node will be translated (position)
+ * -# The node will be rotated (rotation)
+ * -# The node will be scaled (scale)
+ *
+ *
Order in transformations with grid enabled
+ * -# The node will be translated (position)
+ * -# The node will be rotated (rotation)
+ * -# The node will be scaled (scale)
+ * -# The grid will capture the screen
+ * -# The node will be moved according to the camera values (camera)
+ * -# The grid will render the captured screen
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) { @@ -301,12 +308,13 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ }, /** - *get 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.
- *
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.
+ *
- * 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.
+ * 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.
*
get the skew degrees in Y
+ *
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.
*
* 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.
*
* Sets the Y rotation (angle) of the node in degrees which performs a vertical rotational skew.
- *
- * 0 is the default rotation angle.
- * Positive values rotate node clockwise, and negative values for anti-clockwise.
+ * (support only in WebGL rendering mode)
+ * 0 is the default rotation angle.
+ * Positive values rotate node clockwise, and negative values for anti-clockwise.
*
* Changes the scale factor on X axis of this node
- * The deafult value is 1.0 if you haven't changed it before
+ * The default value is 1.0 if you haven't changed it before
*
- * Changes the position (x,y) of the node in OpenGL coordinates
- * Usually we use ccp(x,y) to compose CCPoint object.
- * The original point (0,0) is at the left-bottom corner of screen.
- * and Passing two numbers (x,y) is much efficient than passing CCPoint object.
+ * 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.
*
+ * Sets the position (x,y) using values between 0 and 1.
+ * The positions in pixels is calculated like the following:
+ * _position = _normalizedPosition * parent.getContentSize()
+ *
Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner.
- * @const + *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 () { @@ -645,6 +697,16 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ }, /** + * 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 () { @@ -652,14 +714,18 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ }, /** - * @param {Number} 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.setNodeDirty(); + this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); }, /** + *Returns the y axis position of the node in cocos2d coordinates.
+ * @function * @return {Number} */ getPositionY: function () { @@ -667,15 +733,18 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ }, /** - * @param {Number} 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.setNodeDirty(); + this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); }, /** - * Get the amount of children. + * Returns the amount of children. + * @function * @return {Number} The amount of children. */ getChildrenCount: function () { @@ -683,23 +752,25 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ }, /** - * Return an array of childrenanchorPoint is the point around which all transformations and positioning manipulations take place.
+ *
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 anchorPoint is (0.5,0.5), so it starts in the center of the node.
* Sets the anchor point in percent.
*
- * anchorPoint is the point around which all transformations and positioning manipulations take place.
+ * 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 anchorPoint is (0.5,0.5), so it starts in the center of the node.
+ * The default anchor point is (0.5,0.5), so it starts at the center of the node.
*
The untransformed size of the node.
+ *
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.
- * Sets whether the anchor point will be (0,0) when you position this node.
- *
+ * 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
*
- * Sets a custom user data pointer
- * You can set everything in UserData pointer, a data block, a structure or an object, etc.
+ * Sets a custom user data reference
+ * You can set everything in UserData reference, a data block, a structure or an object, etc.
*
- * Returns a user assigned CCObject
- * Similar to UserData, but instead of holding a void* it holds an object.
- * The UserObject will be retained once in this method, and the previous UserObject (if existed) will be release.
+ * 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.
*
Gets the CCActionManager object that is used by all actions.
+ *
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.)
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) { + if (this._actionManager !== actionManager) { this.stopAllActions(); this._actionManager = actionManager; } @@ -1051,27 +1135,28 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ /** *
- * cc.Scheduler 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.
+ * Returns the cc.Scheduler object used to schedule all "updates" and timers.
*
* 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.
*
"add" logic MUST only be on this method
"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} [tag=] A integer to identify the node easily. Please refer to setTag(int) */ addChild: function (child, localZOrder, tag) { + localZOrder = localZOrder === undefined ? child._localZOrder : localZOrder; + var name, setTag = false; + if(cc.isUndefined(tag)){ + tag = undefined; + name = child._name; + } else if(cc.isString(tag)){ + name = tag; + tag = undefined; + } else if(cc.isNumber(tag)){ + 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"); - if (child === this) { - cc.log(cc._LogInfos.Node_addChild); - return; - } + this._addChildHelper(child, localZOrder, tag, name, setTag); + }, - if (child._parent !== null) { - cc.log(cc._LogInfos.Node_addChild_2); - return; - } + _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); - var tmpzOrder = (localZOrder != null) ? localZOrder : child._localZOrder; - child.tag = (tag != null) ? tag : child.tag; - this._insertChild(child, tmpzOrder); - child._parent = this; - this._cachedParent && (child._cachedParent = this._cachedParent); + child.setParent(this); + child.setOrderOfArrival(cc.s_globalOrderOfArrival++); - if (this._running) { + if( this._running ){ child.onEnter(); // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter if (this._isTransitionFinished) child.onEnterTransitionDidFinish(); } + if (this._cascadeColorEnabled) + child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty); + if (this._cascadeOpacityEnabled) + child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty); }, // composition: REMOVE @@ -1165,12 +1298,13 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks.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
+ *
"remove" logic MUST only be on this method
* If a class wants to extend the 'removeChild' behavior it only needs
* to override this method
Override this method to draw your own node.
- * The following GL states will be enabled by default:
- - glEnableClientState(GL_VERTEX_ARRAY);
- - glEnableClientState(GL_COLOR_ARRAY);
- - glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- - glEnable(GL_TEXTURE_2D);
AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE
- -But if you enable any other GL state, you should disable it after drawing your node.
- * @param {CanvasContext} ctx + /** + * 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 @@ -1370,12 +1496,9 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ // DON'T draw your stuff outside this method }, - /** performs OpenGL view-matrix transformation of it's ancestors.
* 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 one, e.g. CCNode::onEnterTransitionDidFinish()
+ * If you override onEnterTransitionDidFinish, you shall call its parent's onEnterTransitionDidFinish with this._super()
*
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.
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.
+ * If you are running 7 Sequences of 2 actions, it will return 7.
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.
+ * Only one "update" method could be scheduled per node.
Schedules a custom selector.
+ * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.
unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.
+ * Actions are not affected by this method.
Resumes all scheduled selectors and actions.
+ * This method is called internally by onEnter
Pauses all scheduled selectors and actions.
+ * This method is called internally by onExit
Pauses all scheduled selectors and actions.
+ * This method is called internally by onExit
Sets the additional transform.
- * The additional transform will be concatenated at the end of nodeToParentTransform.
+ *
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).
*
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.
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.
Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.
+ * The matrix is in Pixels.
Returns a grid object that is used when applying effects.
+ * This function have been deprecated, please use cc.NodeGrid to run grid actions
Changes a grid object that is used when applying effects
+ * This function have been deprecated, please use cc.NodeGrid to run grid actions
- * cc.NodeRGBA is a subclass of cc.Node that implements the CCRGBAProtocol protocol.
- *
- * All features from CCNode are valid, plus the following new features:
- * - opacity
- * - RGB colors
- *
- * Opacity/Color propagates into children that conform to the CCRGBAProtocol if cascadeOpacity/cascadeColor is enabled.
- *
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.
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.
+ *
Create a identity transformation matrix:
+ * [ 1, 0, 0,
+ * 0, 1, 0 ]
Create a identity transformation matrix:
+ * [ 1, 0, 0,
+ * 0, 1, 0 ]
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 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.
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.
- * This class manages event listener subscriptions and event dispatching.
+ *
+ * cc.eventManager is a singleton object which manages event listener subscriptions and event dispatching.
*
- * The EventListener list is managed in such a way that event listeners can be added and removed even
- * from within an EventListener, while events are being dispatched.
+ * The EventListener list is managed in such way so that event listeners can be added and removed
+ * while events are being dispatched.
*
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.
Constructor of cc.Layer, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
*/ ctor: function () { var nodep = cc.Node.prototype; @@ -47,306 +41,102 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ this._ignoreAnchorPointForPosition = true; nodep.setAnchorPoint.call(this, 0.5, 0.5); nodep.setContentSize.call(this, cc.winSize); - } -}); - -/** - * 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(); - return ret; - -}; - -/** - *
- * 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
- *
* CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.
* All features from CCLayer are valid, plus the following new features:
- *
@@ -563,61 +304,75 @@ delete _tmp.PrototypeLayerColor;
* @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} compresseInterpolation - Indicate whether or not the interpolation will be compressed
+ * @property {Number} compressedInterpolation - Indicate whether or not the interpolation will be compressed
*/
cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
- _startColor: null,
_endColor: null,
_startOpacity: 255,
_endOpacity: 255,
_alongVector: null,
_compressedInterpolation: false,
- _gradientStartPoint: null,
- _gradientEndPoint: null,
_className: "LayerGradient",
+ _colorStops: [],
/**
- * @constructor
- * @param {cc.Color} start starting color
+ * Constructor of cc.LayerGradient
+ * @param {cc.Color} start
* @param {cc.Color} end
- * @param {cc.Point|Null} v
- */
- ctor: function (start, end, v) {
- var _t = this;
- cc.LayerColor.prototype.ctor.call(_t);
-
- _t._startColor = cc.color(0, 0, 0, 255);
- _t._endColor = cc.color(0, 0, 0, 255);
- _t._alongVector = cc.p(0, -1);
- _t._startOpacity = 255;
- _t._endOpacity = 255;
- _t._gradientStartPoint = cc.p(0, 0);
- _t._gradientEndPoint = cc.p(0, 0);
- cc.LayerGradient.prototype.init.call(_t, start, end, v);
- },
-
- /**
+ * @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) {
+ 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 locStartColor = _t._startColor, locEndColor = _t._endColor;
- locStartColor.r = start.r;
- locStartColor.g = start.g;
- locStartColor.b = start.b;
+ var locEndColor = _t._endColor;
_t._startOpacity = start.a;
locEndColor.r = end.r;
@@ -627,44 +382,41 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
_t._alongVector = v;
_t._compressedInterpolation = true;
- _t._gradientStartPoint = cc.p(0, 0);
- _t._gradientEndPoint = cc.p(0, 0);
cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255));
- cc.LayerGradient.prototype._updateColor.call(_t);
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty|cc.Node._dirtyFlags.gradientDirty);
return true;
},
/**
* Sets the untransformed size of the LayerGradient.
- * @override
* @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._updateColor();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
},
_setWidth: function (width) {
cc.LayerColor.prototype._setWidth.call(this, width);
- this._updateColor();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
},
_setHeight: function (height) {
cc.LayerColor.prototype._setHeight.call(this, height);
- this._updateColor();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
},
/**
- * get the starting color
+ * Returns the starting color
* @return {cc.Color}
*/
getStartColor: function () {
- return this._realColor;
+ return cc.color(this._realColor);
},
/**
- * set the starting color
+ * Sets the starting color
* @param {cc.Color} color
* @example
* // Example
@@ -673,10 +425,18 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
*/
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;
+ }
},
/**
- * set the end gradient color
+ * Sets the end gradient color
* @param {cc.Color} color
* @example
* // Example
@@ -684,29 +444,44 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
* //set the ending gradient to red
*/
setEndColor: function (color) {
- this._endColor = color;
- this._updateColor();
+ 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);
},
/**
- * get the end color
+ * Returns the end color
* @return {cc.Color}
*/
getEndColor: function () {
- return this._endColor;
+ return cc.color(this._endColor);
},
/**
- * set starting gradient opacity
+ * Sets starting gradient opacity
* @param {Number} o from 0 to 255, 0 is transparent
*/
setStartOpacity: function (o) {
this._startOpacity = o;
- this._updateColor();
+ //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);
},
/**
- * get the starting gradient opacity
+ * Returns the starting gradient opacity
* @return {Number}
*/
getStartOpacity: function () {
@@ -714,16 +489,19 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
},
/**
- * set the end gradient opacity
+ * Sets the end gradient opacity
* @param {Number} o
*/
setEndOpacity: function (o) {
this._endOpacity = o;
- this._updateColor();
+ var stops = this._colorStops;
+ if(stops && stops.length > 0)
+ stops[stops.length -1].color.a = o;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
},
/**
- * get the end gradient opacity
+ * Returns the end gradient opacity
* @return {Number}
*/
getEndOpacity: function () {
@@ -731,23 +509,25 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
},
/**
- * set vector
+ * 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._updateColor();
+ 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);
},
- /** is Compressed Interpolation
+ /**
+ * Returns whether compressed interpolation is enabled
* @return {Boolean}
*/
isCompressedInterpolation: function () {
@@ -755,80 +535,100 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
},
/**
+ * Sets whether compressed interpolation is enabled
* @param {Boolean} compress
*/
setCompressedInterpolation: function (compress) {
this._compressedInterpolation = compress;
- this._updateColor();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
},
- _draw: null,
+ /**
+ * 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);
+ },
- _updateColor: null
+ _createRenderCmd: function(){
+ if (cc._renderType === cc._RENDER_TYPE_CANVAS)
+ return new cc.LayerGradient.CanvasRenderCmd(this);
+ else
+ return new cc.LayerGradient.WebGLRenderCmd(this);
+ }
});
/**
- * creates a gradient layer
+ * 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) {
- return new cc.LayerGradient(start, end, v);
+cc.LayerGradient.create = function (start, end, v, stops) {
+ return new cc.LayerGradient(start, end, v, stops);
};
-
-
-if (cc._renderType === cc._RENDER_TYPE_CANVAS) {
- //cc.LayerGradient define start
- var _p = cc.LayerGradient.prototype;
- _p.draw = function (ctx) {
- var context = ctx || cc._renderContext, _t = this;
- if (_t._isLighterMode)
- context.globalCompositeOperation = 'lighter';
-
- context.save();
- var locEGLViewer = cc.view, opacityf = _t._displayedOpacity / 255.0;
- var tWidth = _t.width * locEGLViewer.getScaleX(), tHeight = _t.height * locEGLViewer.getScaleY();
- var tGradient = context.createLinearGradient(_t._gradientStartPoint.x, _t._gradientStartPoint.y,
- _t._gradientEndPoint.x, _t._gradientEndPoint.y);
- var locDisplayedColor = _t._displayedColor, locEndColor = _t._endColor;
- tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + ","
- + Math.round(locDisplayedColor.b) + "," + (opacityf * (_t._startOpacity / 255)).toFixed(4) + ")");
- tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + ","
- + Math.round(locEndColor.b) + "," + (opacityf * (_t._endOpacity / 255)).toFixed(4) + ")");
- context.fillStyle = tGradient;
- context.fillRect(0, 0, tWidth, -tHeight);
-
- if (_t._rotation != 0)
- context.rotate(_t._rotationRadians);
- context.restore();
- };
- _p._updateColor = function () {
- var _t = this;
- var locAlongVector = _t._alongVector, tWidth = _t.width * 0.5, tHeight = _t.height * 0.5;
-
- _t._gradientStartPoint.x = tWidth * (-locAlongVector.x) + tWidth;
- _t._gradientStartPoint.y = tHeight * locAlongVector.y - tHeight;
- _t._gradientEndPoint.x = tWidth * locAlongVector.x + tWidth;
- _t._gradientEndPoint.y = tHeight * (-locAlongVector.y) - tHeight;
- };
- //cc.LayerGradient define end
- _p = null;
-} else {
- _tmp.WebGLLayerGradient();
- delete _tmp.WebGLLayerGradient;
-}
-_tmp.PrototypeLayerGradient();
-delete _tmp.PrototypeLayerGradient;
+//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:
*
- * 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.
- *
@@ -52,17 +50,19 @@ cc.ENGINE_VERSION = "Cocos2d-html5-v3.0 alpha 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
*
+ * 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"
+ *
- * The resolution translate on EGLView - *
+ * Sets the resolution translate on EGLView * @param {Number} offsetLeft * @param {Number} offsetTop */ @@ -291,9 +457,7 @@ cc.EGLView = cc.Class.extend(/** @lends cc.view# */{ }, /** - *- * get the resolution translate on EGLView - *
+ * Returns the resolution translate on EGLView * @return {cc.Size|Object} */ getContentTranslateLeftTop: function () { @@ -301,8 +465,9 @@ cc.EGLView = cc.Class.extend(/** @lends cc.view# */{ }, /** - * Get the frame size of EGL view. - * In general, it returns the screen size since the EGL view is a fullscreen view. + * Returns the frame size of the view.
* This class manages all events of input. include: touch, mouse, accelerometer, keyboard
*
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, - _length : 0, - _count : 0, _label : null, _className:"LoaderScene", + cb: null, + target: null, + /** + * Contructor of cc.LoaderScene + * @returns {boolean} + */ init : function(){ var self = this; - var winSize = cc.director.getWinSize(); - //logo var logoWidth = 160; var logoHeight = 200; - var centerPos = cc.p(winSize.width / 2, winSize.height / 2); // bg - var bgLayer = self._bgLayer = cc.LayerColor.create(cc.color(32, 32, 32, 255)); - bgLayer.setPosition(0, 0); + var bgLayer = self._bgLayer = new cc.LayerColor(cc.color(32, 32, 32, 255)); self.addChild(bgLayer, 0); //image move to CCSceneFile.js @@ -52,14 +58,14 @@ cc.LoaderScene = cc.Scene.extend({ cc.loader.loadImg(cc._loaderImage, {isCrossOrigin : false }, function(err, img){ logoWidth = img.width; logoHeight = img.height; - self._initStage(img, centerPos); + self._initStage(img, cc.visibleRect.center); }); fontSize = 14; lblHeight = -logoHeight / 2 - 10; } //loading percent - var label = self._label = cc.LabelTTF.create("Loading... 0%", "Arial", fontSize); - label.setPosition(cc.pAdd(centerPos, cc.p(0, lblHeight))); + 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; @@ -70,19 +76,23 @@ cc.LoaderScene = cc.Scene.extend({ var texture2d = self._texture2d = new cc.Texture2D(); texture2d.initWithElement(img); texture2d.handleLoadedTexture(); - var logo = self._logo = cc.Sprite.create(texture2d); + 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%"; @@ -93,41 +103,51 @@ cc.LoaderScene = cc.Scene.extend({ * init with resources * @param {Array} resources * @param {Function|String} cb + * @param {Object} target */ - initWithResources: function (resources, cb) { - if(typeof resources == "string") resources = [resources]; + 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; - self._length = res.length; - cc.loader.load(res, function(result, count){ self._count = count; }, function(){ - self.cb(); - }); - self.schedule(self._updatePercent); - }, - - _updatePercent: function () { - var self = this; - var count = self._count; - var length = self._length; - var percent = (count / length * 100) | 0; - percent = Math.min(percent, 100); - self._label.setString("Loading... " + percent + "%"); - if(count >= length) self.unschedule(self._updatePercent); + 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); + }); } }); -cc.LoaderScene.preload = function(resources, cb){ +/** + *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.loaderScene.initWithResources(resources, cb); + _cc.loaderScene.initWithResources(resources, cb, target); cc.director.runScene(_cc.loaderScene); return _cc.loaderScene; diff --git a/cocos2d/core/scenes/CCScene.js b/cocos2d/core/scenes/CCScene.js index af8bd9f754..a54a179dcd 100644 --- a/cocos2d/core/scenes/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,10 +36,12 @@ *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 () { @@ -52,12 +54,8 @@ cc.Scene = cc.Node.extend(/** @lends cc.Scene# */{ /** * 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/core/scenes/CCSceneFile.js b/cocos2d/core/scenes/CCSceneFile.js deleted file mode 100644 index f0a881e45e..0000000000 --- a/cocos2d/core/scenes/CCSceneFile.js +++ /dev/null @@ -1,27 +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._loaderImage = "data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAlAAD/4QMpaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjAtYzA2MCA2MS4xMzQ3NzcsIDIwMTAvMDIvMTItMTc6MzI6MDAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjM4MDBEMDY2QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjM4MDBEMDY1QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU2RTk0OEM4OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2RTk0OEM5OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4ADkFkb2JlAGTAAAAAAf/bAIQADQkJCQoJDQoKDRMMCwwTFhENDREWGhUVFhUVGhkUFhUVFhQZGR0fIB8dGScnKionJzk4ODg5QEBAQEBAQEBAQAEODAwOEA4RDw8RFA4RDhQVERISERUfFRUXFRUfKB0ZGRkZHSgjJiAgICYjLCwoKCwsNzc1NzdAQEBAQEBAQEBA/8AAEQgAyACgAwEiAAIRAQMRAf/EALAAAAEFAQEAAAAAAAAAAAAAAAQAAgMFBgcBAQEAAwEBAAAAAAAAAAAAAAAAAQMEAgUQAAIBAgIEBwoLBgQGAwAAAAECAwAEEQUhMRIGQVFxsTITFGGBwdEiQlKSMzWRoeFicqKyI1NzFYJjJDQWB9KjVCbxwkNkJWXik3QRAAIBAgMFBQcDBQEAAAAAAAABAhEDIRIEMUFRcTJhwVIUBZGhsSJyEzOB0ULhYpIjUxX/2gAMAwEAAhEDEQA/AMJSpUqAVKlXuFAeUq9wpUB5XuFe4V6ooDzZHDox0CnGMinzwl7Z8NajaHeoO3vmTBZBtp9YUIqTEV5ROxHKnWRnaU8VRMhFBUjpV7hSoSeUq9pUB5Sr2lhQHlKvcK8oBV7hSFSRrtaKAZs07YNPM1pG2xJIAw1jSeandry/8X4m8VCKkWwaWwam7Xl/4v1W8VLtmX/i/VbxUoKkWwakSM407tmX/i/VbxUmzGwjQsjdY41IARie/U0IbZO0kNtCXnOCkEBeFu4KI3Bs7DNb27ya+jDx3kJeEnpJJEcQVbWDsk17u5urd591ucZkWhym2Vnd9RkCDEpFxDRpbw0bunu5mlp2De2FMLYXOD2wB2xbOeraUcYGJ72mlSUiqzzdzMd3Z3mixltA2yzcK/NlHM1DQyRXce1HocdNOEfJXZ88y9ZojOqhiBszIRiHQ8Y4cK5TvHuzLljHNMqxNoDjLFraHHnjPxcNCGVbxEUzYNTx5jZSxhpW6qTzlwJ+DCvO2Zf+L9VvFSgqyHYNLYNTdssPxfibxUu15f8Ai/VPiqCakOwa82DU/a8v/F+JvFTDdWPBL8R8VKCvYRYV5UzoMAy6QdIIqI0B4KJtxiRQwou16QoGUkntH5Tz0RbZbmF2hktraSVBo2lUkY8tDye0flPPXTslVUyiyVRsjqUOA4yMT8dW2ram2m6UVTNq9S7EIyUVJydMTn/6DnP+im9Wl+g5z/opvVrpteEhQWY4AaSTwAVf5WPiZh/9S5/zj7zltzlmYWkfWXNvJDGTgGcYDHirR7i7mSbwXParsFMrgb7w6jKw/wCmnc9I14kF3vpvCljbMyWMOJL4aEiB8qU/ObUK7HYWVrl1pFZWiCOCBQqKOLjPGTrNZZqKbUXVHq2nNwTuJRk1VpbgXN8s7Rk5ym0UQQzhIG2NAjhxHWbI+gCBVjBBFbwxwQqEiiUJGg1BVGAFe7dV28WYLYZFmF2Th1UD7JGjymGyn1iK5OyzIBGB1HgrLZhamzumQAGJwSqnSCh1q3GOCodxt4cxurdcpzuN4cyhiWaF5Bg09udUmnWw1H/jV9nFuJ7Quo+8h8peThFA+047vduyMtk7fYqTl07YFdfUufMPzT5p71UdtlmYXaGS2t3mQHAsgxANdadYJopLe4QS2867EsZ4QfCNYrCFbjdDPmgkYyWFxgVf04ifJf6ScNdRUW1XBb6FU5TjF5EpSSrGu/s5lN+g5z/opvVpfoOc/wCim9WtdHnatvObJXDW7xLGhB8nrPaY9/HCr+tEdPCVaSeDoYLnqF63lzW4/PFSW3ecxbI84VSzWUwUaSdg0DXXK5nvAipnd6qgKvWnQO7pri9ZUEmm3Vl2j1kr8pRlFRyquBNZjGxQ/S56Y1S2fu9OVueon11Szahoou06QoQUXadIVCD2FJJ7R+U89dMydv8Axdn+TH9muZye0flPPXQstlK5Tbka1gUjlC1q0vVLkeb6r+O3Tx9xcY1nt8c0NrZCyiOE1108NYjGv1joo7Js1jzKyScYLIvkzL6LDwHXVJksH9Sb49dKNq0tj1jA6uriOCL+02FWX7iVtZX1/AzaHTyeoauKn2MX9W79zebiZCuR5MjSrhfXuEtwTrUeZH+yNfdrRNcxI6IzhXlJEak6WIGJ2Rw4ChWnChndtlVBLMdQA0k1gbXNMzzDfDLs6mjaPKppJbWwJ1bOwwxw43OnHh71YT3DpfWUJmFlb5jHHDdeXBHIsrRea5TSqvxqG04cNN62vetoCS4tre5mgnkGE9q+3DKOkuI2WX6LDQRRHWDh1UCtwj7QRg2wdl8Djgw1qe7XvW0BQ3kfZ7mSLgU+T9E6RVbnuVrnWVSWqj+Lt8ZbRuHEdKPkYVcZ2MJY5fSGyeVar45+rkWQHAqccalPE5km1htWK5nK4Wnt5FuUBUwOMG4nGkA/BXUrW4S6torlOjMgcd/xVn7rLo7zKs0uEjCNeSvdwoBhgsZxX1l2j36k3Lu+uyprdj5Vs5A+i/lD48a0aaVJOPi7jB6lbzWozpjB48pf1NDXNN4vfl7+Z4BXS65pvF78vfzPAK71XTHmZ/S/yT+jvJ7L3fHytz1E+upbL+Qj5W56jfXWRnsIYKLtekKEFGWvSFQgyjk9o/Keet3YthlMP/5x9msJJ7R+U89biyb/AMXEv7gD6tadL1T+kwepRrC39ZkLDMbiwMvUHRPG0bjlGg8ore/23sxBldxfMPLupNhT8yL/AORNZbdzJ484scytxgLqJY5LZj6Q2sV5G1Vud1mjjyG0ij0NEGSZToKyhjtqw4waztuiXA3qKTbSxltfGhbZlE95ZtZqxVbgiOZhrER9ph3Svk9+pJILZ4Y4DGBFCUMKjRsGPobPFhUfW0NJmljE2xJcIrcI2vFUEln1lRXd6lrazXT9GCNpD+yNqoI7mOVduNw6nzlOIoPOUa6yye1XXcbMR5GdQ3xY0BSbj31/FcTQZirJ+q431q7anbHCTZ72Bw7lbPrKBMcBWNNgbMBBh+bsjBdni0VJ1lARZs6yWiupxCuMDy6KpS2IwOo6DTr3Mre3e5tZZVUM4ZBjqOOJoWO4jkXajcOOMHGgDISvWIrdAkKR80+TzVl908bPPL3LzxOuHdifxVfiTAg92qI/w+/8gGgSyN/mR7XPVlp0lF/3L3mbVKtu5Hjbk/8AHE2Fc03i9+Xv5ngFdKNc13i9+Xv5ngFaNV0x5nn+l/kn9HeEWXu+PlbnqJ9dS2Xu9OVueon11kZ7CGCjLXpCgxRlr0hUIPYUcntH5Tz1s8vb+Bt1/dqPirGSe0flPPWusG/g4Py15q06XqlyMWvVYQ+ruI9xJOqzO9hOto/sP8tbGOFIrmWeM7IuMDMnAXXQJOUjQeOsJk0nY96ip0CYunrjaHx1t+srPJUbXBm2LrFPikwTOb+T+VhbZxGMrDXp83x1QSy2tucJpUjPETp+Cn5/ftaRvKvtp3Kx48HG3erHMzOxZiWZtLMdJNQSbbL71Vk6yynViOkqnEEfOWtPbXi3EQkGg6mXiNckjeSJxJGxR10qw0GtxuxmvbImD4CZMFlA4fRfv0BqesqqzTMZNMEDbIHtHH2QeCiZJSqMQdOGiue53mz3czQwsRbIcNHnkec3c4qAMuriz68gTIToxwOOnlp0MjxMJYW741Gs3RVldtbygE/dMcHX/moDaxTiWNZB53B3arb8/wC+4SOF4sf/AKxU9kcBsfOGHfoUHtG/RbzY5Die5HHhXdvavqiZ9Q8Jdlq4/gbKua7xe/L38zwCuhpf2Uk/Zo50kmwJKIdogDjw1VzzeL35e/meAVp1LTgqY4nn+mRauzqmqwrjzCLL3fHytz1E+upLL+Qj5W56jfXWRnroYKLtekKEFF2vSFQg9hSSe0flPPWosm/hIfoLzVl5PaPynnrRWb/w0X0F5q06XqlyM2sVYx5gmbFre/t71NY2T+0h8VbSO5SWNJUOKSAMp7jDGspmMPaLRlXS6eWve1/FRO7WYdbZm1Y/eW/R7qHxHRXGojlm3ulid6aVbaW+OALvgCLq2Hm9WxHKWqjhj6xsK1e8dm15l4niG1LZkswGsxtrPeOmsvayBJA1VItlWjptLuTdPMo7LtjRDq9naK4+WF9IrUW7BaHOljGqVHB7w2hzVoZt87d8vaNYSLl02CcRsDEbJbj71Uu7UBkvJ7/D7q2QoDxySaAO8MTXdxRVMpRp5XZOWdF/ms7R5XdyKfKWJsO/5PhrG5XlNxmEywW6bTnTxAAcJNbGSMXkM1pjgbiNo1PziPJ+Os7u7m/6ReM00ZOgxSpqYYHT3wRXMKN4ll9zUG4bQfNshu8sZVuEA2hirA4qe/VOwwrVbzbww5mI44UKRRYkbWG0S3JWctbd7u5WFfOOLHiUdJqmaipfLsIsObhWe001lMkMVvJNjhghIALMcBxCs7fxXQmkupx1bXDswGPlaTidVaEyKNXkoo4eBV+Sq7L7Vs9zcBgeyQ4GQ/MB1crmoim2orezqcowTuSeEY48jQ7oZX2PLzdyLhNd6RjrEY6I7+uspvH78vfzPAK6UAAAFGAGgAcArmu8Xvy9/M8ArTfio24RW5nnaG67uou3H/KPuqT2X8hHytz1G+upLL3enK3PUb66ys9RDBRdr0hQgou06QqEGUkntH5Tz1e238vF9BeaqKT2j8p56vbb+Xi+gvNWjTdUuRn1XTHmTh8KrJTJlt8t1CPIY44cGnpJVjTJYkmjaN9Ib4u7V923njTethRauZJV3PaW1rfLIiXEDYg6R4VYc9CXW7thfOZbKdbGZtLW8uPVY/u3GrkNUkM9zlcxUjbhfWOA90cRq4gv4LhdqN+VToNYWmnRm9NNVWNTyHc6VWBv8wt4YeHqm6xyPmroq1Z7WGFLSxTq7WLSuPSdjrkfumq5yHXDUeA92oO2SKpVumNAaoJLMXH3myp0rpJ4uKhc3tbDM5BMri1zAj79j7KTiY8TcdBpcsith0286o+sPCagEX9Pzg4zXUCp6QYse8oouCG3tk6m1BYv05W6T+IdyolxbHDAAa2OgDlNCz3ryN2WxBd5PJMg1t81eId2ukqnLlTBbfcuY+9uJLiRcvtPvHdsHK+cfRHcHDWsyawjyy0WBcDI3lTP6TeIcFV+S5OmXx9bJg1048o8Cj0V8Jq2DVu09nL80up7OxHi+oal3P8AXB/IsZS8T/YOV65zvCcc7vfzPAK3ivWCz445zeH954BXOr6I8yfSfyz+jvCLP3fHytz1G+upLP3fHytz1E+usbPaQ0UXadIUIKLtekKhB7Ckk9o/Keer22/l4/oLzVRSe0flPPV7b/y8X0F5q0abqlyM+q6Y8yQsBTDMor1o8aiaE1pbluMqS3sbLLHIhSRQyngqukhaJ9uBjo+H5aOa3ao2t34qouRlLajTalGP8v0IY8ylXQ+PKPFU/bYXOLPge6CKia0LaxTOxHu1Q7cuBd9yPEJ7TbjXKO8CajbMIF6CNIeNvJHjqIWJ7tSpYkalqVblwIdyG+RGXur0hXYJFxal+Dhq5y3slkv3Y2pD0pTr+QUClpJRUdo9XW4OLrTHtM16cZLLWkeC7y4jvlNEpcRtw1Ux27Ci448NZrTFy3nn3IQWxlgGrDZ3pza7/M8ArZo+ArF5171uvp+CqdV0R5l/psUrs2vB3hdl7vTlbnqJ9dS2Xu+PlbnqJ9dY2eshooq16QoQUXa9IVCD2FLJ7RuU89WNtmUSQqkgYMgw0accKrpPaPynnrZWG4Vi+VWmY5tnMWXG+XrIYnA0rhj0mdcTgdNdwnKDqjmduM1SRR/qlr8/4KX6pa8T/BVzDuLZXudRZblmbxXcPUNPc3KqCIwrbOzgrHEnHjoyD+3eSXkht7DeKG4umDGOJVUklfouThXfmbnZ7Cvy1vt9pmv1W1+d8FL9VteJvgq5yrcOGfLmzHN80iyyETPbptAEFo2ZG8pmUa1OFNn3Ky6W/sbDKM5hv5bx2WTZA+7RF2y52WOPJTzE+z2Dy1vt9pT/AKpacTerS/U7Tib1a04/t7kDXPY03jhN0W6sQ7K7W3q2dnrMccaDy/8At80kuZfqWYxWNtlcvUPPhiGYhWDeUy7IwYU8xPs9g8tb7faUn6pacTerTxm9oOBvVq3v9z927aynuId44LiWKNnjhAXF2UYhRg516qpsryjLr21665zFLSTaK9U2GOA87SwqY37knRU+BzOzags0s1Oyr+BKM6sxwP6tSDPLMen6vy0rvdm3Sxlu7K/S7WDDrFUDUTxgnTU826eXW7KlxmqQuwDBXUKcD+1Xee/wXuKX5XDGWLapSVcOyhEM/seJ/V+WnjeGx4pPV+Wkm6kKZlFay3Jlt7iFpYZY8ASVK6DjtDDA0f8A0Tl340/1f8Ndx8xJVWXB0KbktFFpNzdVXAC/qOwA0CQni2flrO3Vwbm5lnI2TKxbDirX/wBE5d+NcfV/wVR7xZPa5U9utvI8nWhmbbw0YEAYYAVxfhfy5rlKR4Fulu6X7mW1mzT8S4Yis/5CPlbnqJ9dSWfu9OVueon11mZvQ2i7XpChKKtekKhBlNJ7R+U89bDfGTb3a3ZX0Lcj6kdY+T2j8p560288m1kWQr6MJ+ylSAr+2cnV5renjs3H1loX+3j9XvbbtxLN9lqW4UnV5jdnjtXHxihtyZNjeSBu5J9k1BJe7xy7W5CJ/wCzuD/mTVTf2+fq97LJuLrPsNRueS7W6aJ/38x+vLVXuY+xvHaNxbf2GoCezf8A36j/APsSf8w1sLnqczTefJluYoLm5uo5F61sBshItP1cNFYe1f8A3ir/APfE/wCZUe9bB94r5jwuPsrQFhmG4l/Z2M17HdW90tuu3IkTHaCjWdIw0VVZdks9/C06yJFEp2dp+E1bbqybGTZ8vpQD7L1XRv8A7blT96Oda7tpNuuNE37Cq9KSisjyuUoxrStKllHbLlWTXsMs8chuSuwEPDqwoLe5y+YRE/gLzmqRekvKKtd4327yM/ulHxmrHJStySWVRyrjxKI2XC/CTlnlPPKTpTdFbP0L1bgrf5Lp0G3dPhQHwV0S1lzBsns3sESR8Crh9WAJGjSOKuU3E+zdZQ3oJh8IArdZXFDmOTpHa3i2+YrI2KtKy4ricBsBuHHgFXSo440+Wa2qqxjvM9uMoy+WvzWpLCWWWE28HxL6e43ojgkeSCBY1Ri5BGIUDT51cl3vm276BBqSEH4WbxV0tlkyXJcxTMb+OW6uY9mGHrCzDQwwAbTp2uKuTZ9N1uYsfRRR8WPhrm419mSSjRyiqxVK7y23B/ftuTm2oSdJyzNVw3BFn7vTlbnqF9dS2fu9OVueon11lZuQ2iLdsGFD05H2dNQGV0ntG5Tz1dWm9N1b2kVq8EVwsI2UaQaQOKhmitZGLOmk68DhSFvY+gfWNSAg7z3Qvo7yKCKIohiaNR5LKxx8qpxvjcqS0VpbxvwOAcRQPZ7D0G9Y0uz2HoH1jUCpLY7zXlpbm3eKO5QuzjrBqZji3x17PvNcyT288VvDBJbMWUovS2hslW7mFQ9nsPQPrGl2ew9A+saCod/WNxtbYsrfb17WBxx5ddD2281xC88klvDcSXEnWuzrqOGGC9zRUPZ7D0G9Y0uzWHoH1jQVCLreq6ntZbaO3it1mGy7RjTs1X2mYy20ZiCq8ZOODcdEdmsPQb1jS7PYegfWNdJuLqnQiSUlRqpFLmryxtH1Ma7Qw2gNNPOdSt0oI27p007s9h6B9Y0uz2HoH1jXX3Z+I4+1b8IJdX89xLHKQFMXQUahpxoiPN5P+onfU+A0/s9h6DesaXZ7D0D6xpG7OLbUtu0StW5JJx2bBsmbtiSiEk+cxoCWWSaVpZOk2vDVo0VYdnsPQb1jSNvZcCH1jSd2c+p1XAmFqEOmOPEfaH+BQd1ueo211IzrgFUYKNAAqI1WztCpUqVCRUqVKgFSpUqAVKlSoBUqVKgFSpUqAVKlSoBUqVKgFSpUqAVKlSoD/9k="; diff --git a/cocos2d/core/sprites/CCAnimation.js b/cocos2d/core/sprites/CCAnimation.js index 41ac829eb9..1c653a0bea 100644 --- a/cocos2d/core/sprites/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.
* 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.
*
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.
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.
- * 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");
*
- * Adds an animation from an NSDictionary
- * Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
- *
- * 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.
*
cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) )
*
@@ -240,11 +47,33 @@ cc.cutRotateImageToCanvas = function (texture, rect) {
*
* The default anchorPoint in cc.Sprite is (0.5, 0.5).
- * Returns the flag which indicates whether the sprite is flipped horizontally or not.
+ * 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);
- * Initializes a sprite with an image filename.
+ * 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).
+ * 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.
*
- * 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.
@@ -50,21 +41,43 @@ cc.DEFAULT_SPRITE_BATCH_CAPACITY = 29;
* @class
* @extends cc.Node
*
+ * @param {String|cc.Texture2D} fileImage
+ * @param {Number} capacity
+ * @example
+ *
+ * // 1. create a SpriteBatchNode with image path
+ * var spriteBatchNode = new cc.SpriteBatchNode("res/animations/grossini.png", 50);
+ *
+ * // 2. create a SpriteBatchNode with texture
+ * var texture = cc.textureCache.addImage("res/animations/grossini.png");
+ * var spriteBatchNode = new cc.SpriteBatchNode(texture,50);
+ *
* @property {cc.TextureAtlas} textureAtlas - The texture atlas
* @property {Array} descendants - <@readonly> Descendants of sprite batch 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,
_className: "SpriteBatchNode",
+ ctor: function (fileImage, capacity) {
+ cc.Node.prototype.ctor.call(this);
+ this._descendants = [];
+ this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
+
+ var texture2D;
+ capacity = capacity || cc.SpriteBatchNode.DEFAULT_CAPACITY;
+ 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, capacity);
+ },
+
/**
*
* This is the opposite of "addQuadFromSprite.
@@ -76,7 +89,6 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
* @return {cc.SpriteBatchNode}
*/
addSpriteWithoutQuad: function (child, z, aTag) {
-
cc.assert(child, cc._LogInfos.SpriteBatchNode_addSpriteWithoutQuad_2);
if (!(child instanceof cc.Sprite)) {
@@ -88,12 +100,12 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
child.atlasIndex = z;
// XXX: optimize with a binary search
- var i = 0, locDescendants = this._descendants;
+ var i = 0, len, locDescendants = this._descendants;
if (locDescendants && locDescendants.length > 0) {
- for (var index = 0; index < locDescendants.length; index++) {
- var obj = locDescendants[index];
+ for (i = 0, len = locDescendants.length; i < len; i++) {
+ var obj = locDescendants[i];
if (obj && (obj.atlasIndex >= z))
- ++i;
+ break;
}
}
locDescendants.splice(i, 0, child);
@@ -112,7 +124,7 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
* @return {cc.TextureAtlas}
*/
getTextureAtlas: function () {
- return this.textureAtlas;
+ return this._renderCmd.getTextureAtlas();
},
/**
@@ -120,9 +132,7 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
* @param {cc.TextureAtlas} textureAtlas
*/
setTextureAtlas: function (textureAtlas) {
- if (textureAtlas != this.textureAtlas) {
- this.textureAtlas = textureAtlas;
- }
+ this._renderCmd.getTextureAtlas(textureAtlas);
},
/**
@@ -130,67 +140,59 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
* @return {Array}
*/
getDescendants: function () {
- return this._descendants;
+ return this._descendants;
},
/**
*
- * initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of 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.
+ * 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.
*
* 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.
+ * 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.
*
- * Constructor
- * 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.
- *
* Updates a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array.
@@ -442,70 +377,24 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
* @param {cc.Sprite} sprite
* @param {Number} index
*/
- updateQuadFromSprite: null,
-
- _updateQuadFromSpriteForCanvas: function (sprite, 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;
}
+ this._renderCmd.checkAtlasCapacity();
//
// update the quad directly. Don't add the sprite to the scene graph
//
sprite.batchNode = this;
sprite.atlasIndex = index;
-
sprite.dirty = true;
// UpdateTransform updates the textureAtlas quad
sprite.updateTransform();
},
- _updateQuadFromSpriteForWebGL: function (sprite, index) {
-
- cc.assert(sprite, cc._LogInfos.CCSpriteBatchNode_updateQuadFromSprite);
-
- if (!(sprite instanceof cc.Sprite)) {
- cc.log(cc._LogInfos.CCSpriteBatchNode_updateQuadFromSprite);
- return;
- }
-
- // make needed room
- var locCapacity = this.textureAtlas.capacity;
- while (index >= locCapacity || locCapacity == this.textureAtlas.totalQuads) {
- this.increaseAtlasCapacity();
- }
-
- //
- // update the quad directly. Don't add the sprite to the scene graph
- //
- sprite.batchNode = this;
- sprite.atlasIndex = index;
-
- sprite.dirty = true;
- // UpdateTransform updates the textureAtlas quad
- sprite.updateTransform();
- },
-
- _swap: function (oldIndex, newIndex) {
- var locDescendants = this._descendants;
- var locTextureAtlas = this.textureAtlas;
- var quads = locTextureAtlas.quads;
- var tempItem = locDescendants[oldIndex];
- var tempIteQuad = cc.V3F_C4B_T2F_QuadCopy(quads[oldIndex]);
-
- //update the index of other swapped item
- locDescendants[newIndex].atlasIndex = 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.
@@ -516,16 +405,13 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
* @param {cc.Sprite} sprite
* @param {Number} index
*/
- insertQuadFromSprite: null,
-
- _insertQuadFromSpriteForCanvas: function (sprite, index) {
-
+ insertQuadFromSprite: function (sprite, index) {
cc.assert(sprite, cc._LogInfos.CCSpriteBatchNode_insertQuadFromSprite_2);
-
if (!(sprite instanceof cc.Sprite)) {
cc.log(cc._LogInfos.CCSpriteBatchNode_insertQuadFromSprite);
return;
}
+ this._renderCmd.insertQuad(sprite, index);
//
// update the quad directly. Don't add the sprite to the scene graph
@@ -537,150 +423,41 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
// XXX: so, it should be AFTER the insertQuad
sprite.dirty = true;
sprite.updateTransform();
- this._children.splice(index, 0, sprite);
- },
-
- _insertQuadFromSpriteForWebGL: function (sprite, index) {
-
- cc.assert(sprite, cc._LogInfos.Sprite_insertQuadFromSprite_2);
-
- if (!(sprite instanceof cc.Sprite)) {
- cc.log(cc._LogInfos.Sprite_insertQuadFromSprite);
- return;
- }
-
- // make needed room
- var locTextureAtlas = this.textureAtlas;
- while (index >= locTextureAtlas.capacity || locTextureAtlas.capacity === locTextureAtlas.totalQuads)
- this.increaseAtlasCapacity();
-
- //
- // update the quad directly. Don't add the sprite to the scene graph
- //
- sprite.batchNode = this;
- sprite.atlasIndex = index;
- locTextureAtlas.insertQuad(sprite.quad, index);
-
- // XXX: updateTransform will update the textureAtlas too, using updateQuad.
- // XXX: so, it should be AFTER the insertQuad
- sprite.dirty = true;
- sprite.updateTransform();
- },
-
- _updateAtlasIndex: function (sprite, curIndex) {
- var count = 0;
- var pArray = sprite.children;
- if (pArray)
- count = pArray.length;
-
- var oldIndex = 0;
- if (count === 0) {
- oldIndex = sprite.atlasIndex;
- sprite.atlasIndex = curIndex;
- sprite.arrivalOrder = 0;
- if (oldIndex != curIndex)
- this._swap(oldIndex, curIndex);
- curIndex++;
- } else {
- var needNewIndex = true;
- if (pArray[0].zIndex >= 0) {
- //all children are in front of the parent
- oldIndex = sprite.atlasIndex;
- sprite.atlasIndex = curIndex;
- sprite.arrivalOrder = 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.zIndex >= 0) {
- oldIndex = sprite.atlasIndex;
- sprite.atlasIndex = curIndex;
- sprite.arrivalOrder = 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.atlasIndex;
- sprite.atlasIndex = curIndex;
- sprite.arrivalOrder = 0;
- if (oldIndex != curIndex) {
- this._swap(oldIndex, curIndex);
- }
- curIndex++;
- }
- }
-
- return curIndex;
- },
-
- _updateBlendFunc: function () {
- if (!this.textureAtlas.texture.hasPremultipliedAlpha()) {
- this._blendFunc.src = cc.SRC_ALPHA;
- this._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
- }
+ this._renderCmd.cutting(sprite, index);
},
/**
*
- * 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.
+ * Initializes a cc.SpriteBatchNode with a texture2d and capacity of children.
+ * The capacity will be increased in 33% in runtime if it run out of space.
+ * Please pass parameters to constructor to initialize the sprite batch node, do not call this function yourself.
*
Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
- * (override removeAllChildren of cc.Node)
* 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.
*
- * 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.
- *
- * return is rotated of SpriteFrame.
- *
* 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.
*
- * Singleton that handles the loading of the sprite frames. It saves in a cache the sprite frames.
+ *
+ * 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);
*
- * 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 method.
- *
+ * 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 method.
+ *
* Removes all Sprite Frames associated with the specified textures.
- * It is convinient to call this method when a specific texture needs to be removed.
+ * It is convenient to call this method when a specific texture needs to be removed.
*
Creates a TextureAtlas with an filename and with an initial capacity for Quads.
* The TextureAtlas capacity can be increased in runtime.
Creates a TextureAtlas with an filename and with an initial capacity for Quads.
* The TextureAtlas capacity can be increased in runtime.
@@ -38,6 +38,7 @@ _tmp.WebGLTexture2D = function () {
* @extends cc.Class
*
* @property {WebGLTexture} name - <@readonly> WebGLTexture Object
+ * @property {Number} defaultPixelFormat - The default pixel format
* @property {Number} pixelFormat - <@readonly> Pixel format of the texture
* @property {Number} pixelsWidth - <@readonly> Width in pixels
* @property {Number} pixelsHeight - <@readonly> Height in pixels
@@ -63,19 +64,23 @@ _tmp.WebGLTexture2D = function () {
shaderProgram: null,
- _isLoaded: false,
+ _textureLoaded: false,
_htmlElementObj: null,
_webTextureObj: null,
url: null,
- _loadedEventListeners: null,
- /*public:*/
+ /**
+ * 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);
@@ -129,24 +134,42 @@ _tmp.WebGLTexture2D = function () {
return this._contentSize.height / cc.contentScaleFactor();
},
+ /**
+ * get content size in pixels
+ * @return {cc.Size}
+ */
getContentSizeInPixels: function () {
return this._contentSize;
},
- /** texture max S */
+ /**
+ * texture max S
+ * @return {Number}
+ */
getMaxS: function () {
return this.maxS;
},
+ /**
+ * set texture max S
+ * @param {Number} maxS
+ */
setMaxS: function (maxS) {
this.maxS = maxS;
},
- /** texture max T */
+ /**
+ * get texture max T
+ * @return {Number}
+ */
getMaxT: function () {
return this.maxT;
},
+ /**
+ * set texture max T
+ * @param {Number} maxT
+ */
setMaxT: function (maxT) {
this.maxT = maxT;
},
@@ -175,10 +198,18 @@ _tmp.WebGLTexture2D = 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 "
Draws n quads from an index (offset).
* n + start can't be greater than the capacity of the atlas
- 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 | + *
+ * @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 + * @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) { + 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, dum, 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(); + indxr[i] = irow; + indxc[i] = icol; + if (a.get(icol, icol) === 0.0) + return false; - cc.kmMat4Assign(inv, pM); - cc.kmMat4Identity(tmp); - - if (cc.kmMat4._gaussj(inv, tmp) == cc.KM_FALSE) - return null; + 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); - cc.kmMat4Assign(pOut, inv); - return pOut; -}; + for (l = 0; l < m; l++) + b.set(icol, l, b.get(icol, l) * pivinv); -/** - * 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; -}; + for (ll = 0; ll < n; ll++) { + if (ll !== icol) { + dum = 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) * dum); -/** - * 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(ll, l, a.get(ll, l) - b.get(icol, l) * dum); + } + } + } + // 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; + }; -/** - * 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; -}; + 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); + if (cc.math.Matrix4._gaussj(inv, identityMatrix) === false) + return null; + pOut.assignFrom(inv); + return pOut; + }; -/** - * Assigns the value of pIn to pOut - */ -cc.kmMat4Assign = function (pOut, pIn) { - if(pOut == pIn) { - cc.log("cc.kmMat4Assign(): pOut equals pIn"); + /** + * 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); + if (cc.math.Matrix4._gaussj(inv, identityMatrix) === 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; - } + }; - var outArr = pOut.mat; - var inArr = pIn.mat; + /** + * 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; + } - outArr[0] = inArr[0]; - outArr[1] = inArr[1]; - outArr[2] = inArr[2]; - outArr[3] = inArr[3]; + var outArr = pOut.mat; + var inArr = pIn.mat; - outArr[4] = inArr[4]; - outArr[5] = inArr[5]; - outArr[6] = inArr[6]; - outArr[7] = inArr[7]; + outArr[0] = inArr[0]; + outArr[1] = inArr[1]; + outArr[2] = inArr[2]; + outArr[3] = inArr[3]; - outArr[8] = inArr[8]; - outArr[9] = inArr[9]; - outArr[10] = inArr[10]; - outArr[11] = inArr[11]; + outArr[4] = inArr[4]; + outArr[5] = inArr[5]; + outArr[6] = inArr[6]; + outArr[7] = inArr[7]; - outArr[12] = inArr[12]; - outArr[13] = inArr[13]; - outArr[14] = inArr[14]; - outArr[15] = inArr[15]; - return pOut; -}; + outArr[8] = inArr[8]; + outArr[9] = inArr[9]; + outArr[10] = inArr[10]; + outArr[11] = inArr[11]; -/** - * Returns KM_TRUE if the 2 matrices are equal (approximately) - */ -cc.kmMat4AreEqual = function (pMat1, pMat2) { - if(pMat1 == pMat2){ - cc.log("cc.kmMat4AreEqual(): pMat1 and pMat2 are same object."); - return true; - } + outArr[12] = inArr[12]; + outArr[13] = inArr[13]; + outArr[14] = inArr[14]; + outArr[15] = inArr[15]; + return pOut; + }; - 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; + /** + * 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; } - } - 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 | - + 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; + }; - 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); + /** + * 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; - pOut.mat[0] = s.x; - pOut.mat[4] = s.y; - pOut.mat[8] = s.z; + 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(); - pOut.mat[1] = u.x; - pOut.mat[5] = u.y; - pOut.mat[9] = u.z; + var s = new cc.math.Vec3(f); + s.cross(up); + s.normalize(); - pOut.mat[2] = -f.x; - pOut.mat[6] = -f.y; - pOut.mat[10] = -f.z; + var u = new cc.math.Vec3(s); + u.cross(f); + s.normalize(); - cc.kmMat4Translation(translate, -pEye.x, -pEye.y, -pEye.z); - cc.kmMat4Multiply(pOut, pOut, translate); + pOut.identity(); - return pOut; -}; + pOut.mat[0] = s.x; + pOut.mat[4] = s.y; + pOut.mat[8] = s.z; -/** - * 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); + pOut.mat[1] = u.x; + pOut.mat[5] = u.y; + pOut.mat[9] = u.z; - var normalizedAxis = new cc.kmVec3(); - cc.kmVec3Normalize(normalizedAxis, axis); + pOut.mat[2] = -f.x; + pOut.mat[6] = -f.y; + pOut.mat[10] = -f.z; - 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; + 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); - 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; + var normalizedAxis = new cc.math.Vec3(axis); + normalizedAxis.normalize(); - 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[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[12] = 0.0; - pOut.mat[13] = 0.0; - pOut.mat[14] = 0.0; - pOut.mat[15] = 1.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; - return pOut; -}; + 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; -/** - * 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.log("cc.kmMat4ExtractPlane(): Invalid plane index"); - break; - } - - 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; -}; + pOut.mat[12] = 0.0; + pOut.mat[13] = 0.0; + pOut.mat[14] = 0.0; + pOut.mat[15] = 1.0; -/** - * 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; -}; + 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/plane.js b/cocos2d/kazmath/plane.js index 5470415f1a..94ab4e9b71 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. @@ -27,156 +29,109 @@ /** * @ignore */ -cc.KM_PLANE_LEFT = 0; +(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 + Planed = −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); -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. - */ -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){ - throw "cc.kmPlaneIntersectLine() hasn't been implemented."; - /* - 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.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.log("cc.kmPlaneScale() has not been implemented."); -}; - -/** - * 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 54e1de8e17..ac926ebec2 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,463 +26,425 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * The Quaternion class - * @param {Number} x - * @param {Number} y - * @param {Number} z - * @param {Number} w - * @constructor - */ -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); - if(Math.abs(length) <= cc.kmEpsilon) - throw "cc.kmQuaternionNormalize(): pIn is an invalid value"; - 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; + }; + cc.kmQuaternion = cc.math.Quaternion; + var proto = cc.math.Quaternion.prototype; - 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; - - 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 "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.
+ *
The main namespace of Cocos2d-html5's math library,
+ * all math core classes, functions, properties and constants are defined in this namespace
- * Create a label atlas.
- * It accepts two groups of parameters:
- * a) string, fntFile
- * b) label, textureFilename, width, height, startChar
+ * 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
*
- * 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
+ * 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
*
- * Create a label atlas.
- * It accepts two groups of parameters:
- * a) string, fntFile
- * b) label, textureFilename, width, height, startChar
+ * 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
*
Features and Limitation:
+ *
Features and Limitation:
* - You can add MenuItem objects in runtime using addChild:
* - But the only accepted children are MenuItem objects
+ * 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().
+ *
+ * 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().
+ *
+ * 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().
+ *
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.
NodeGrid class is a class serves as a decorator of cc.Node,
- * Grid node can run grid actions over all its children
- * 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
- *
+ // 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
+ //
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
return the string found by key in dict.
* This plist files can be create manually or with Particle Designer:
* http://particledesigner.71squared.com/
*
Switch between different kind of emitter modes:
- * - CCPARTICLE_MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration
- * - CCPARTICLE_MODE_RADIUS: uses radius movement + rotation
+ * - CCParticleSystem.MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration
+ * - CCParticleSystem.MODE_RADIUS: uses radius movement + rotation
*
return the string found by key in dict.
+ * This plist files can be create manually or with Particle Designer:
+ * http://particledesigner.71squared.com/
+ *
A Node that draws the components of a physics engine.
* Supported physics engines:
@@ -125,50 +151,62 @@ cc.CONSTRAINT_COLOR = cc.color(0, 255, 0, 128);
* @property {cp.Space} space Physic world space
*/
cc.PhysicsDebugNode = cc.DrawNode.extend({
- space:null,
-
- _spaceObj: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.space;
+ return this._space;
},
+ /**
+ * set space
+ * @param {cp.Space} space
+ */
setSpace:function (space) {
- this.space = space;
+ this._space = space;
},
+ /**
+ * draw
+ * @param {object} context
+ */
draw:function (context) {
- if (!this.space)
+ if (!this._space)
return;
- this.space.eachShape(cc.DrawShape.bind(this));
- this.space.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.space = space.space;
- return node;
+ _createRenderCmd: function(){
+ if(cc._renderType === cc._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.space = 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..be1f6f14ba
--- /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){
+ cc.Node.CanvasRenderCmd.call(this, 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/extensions/pluginx/samples/HelloSocial/main.js b/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js
similarity index 50%
rename from extensions/pluginx/samples/HelloSocial/main.js
rename to cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js
index 183e53c1c5..38ddf9f630 100644
--- a/extensions/pluginx/samples/HelloSocial/main.js
+++ b/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js
@@ -1,11 +1,8 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ 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
@@ -24,36 +21,33 @@
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;
- var designSize = cc.size(800, 450);
-
- cc.view.setDesignResolutionSize(designSize.width, designSize.height, cc.ResolutionPolicy.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.runScene(new this.startScene());
- }, this);
-
- return true;
- }
-});
-
-var myApp = new cocos2dApp(MyScene);
\ No newline at end of file
+
+/**
+ * cc.PhysicsDebugNode's rendering objects of WebGL
+ */
+(function(){
+ cc.PhysicsDebugNode.WebGLRenderCmd = function (renderableObject) {
+ cc.Node.WebGLRenderCmd.call(this, renderableObject);
+ this._needDraw = true;
+ };
+
+ 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));
+
+ //cc.DrawNode.prototype.draw.call(node);
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+ this._shaderProgram.use();
+ this._shaderProgram._setUniformForMVPMatrixWithMat4(this._stackMatrix);
+ node._render();
+
+ node.clear();
+ };
+})();
\ No newline at end of file
diff --git a/cocos2d/physics/CCPhysicsSprite.js b/cocos2d/physics/CCPhysicsSprite.js
index 455ac7c322..2fa248da8f 100644
--- a/cocos2d/physics/CCPhysicsSprite.js
+++ b/cocos2d/physics/CCPhysicsSprite.js
@@ -1,4 +1,8 @@
-/** Copyright (c) 2012 Scott Lembcke and Howling Moon Software
+/**
+ * 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
@@ -39,13 +43,13 @@
_rotation:1,
/**
* Create a PhysicsSprite with filename and rect
- * @constructor
+ * 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 = cc.PhysicsSprite.create("res/HelloHTML5World.png");
+ * 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.
@@ -55,7 +59,7 @@
* 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
+ * 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);
@@ -67,7 +71,7 @@
if (fileName === undefined) {
cc.PhysicsSprite.prototype.init.call(this);
- }else if (typeof(fileName) === "string") {
+ }else if (cc.isString(fileName)) {
if (fileName[0] === "#") {
//init with a sprite frame name
var frameName = fileName.substr(1, fileName.length - 1);
@@ -77,7 +81,7 @@
//init with filename and rect
this.init(fileName, rect);
}
- }else if (typeof(fileName) === "object") {
+ }else if (cc.isObject(fileName)) {
if (fileName instanceof cc.Texture2D) {
//init with texture and rect
this.initWithTexture(fileName, rect);
@@ -86,33 +90,80 @@
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.radiansToDegress(this._rotationRadians) : cc.radiansToDegress(this._body.GetAngle()));
+ 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;
@@ -132,6 +183,9 @@
_syncRotation:function () {
this._rotationRadians = this._body.GetAngle();
},
+ /**
+ * visit
+ */
visit:function () {
if (this._body && this._PTMRatio) {
this._syncPosition();
@@ -143,10 +197,16 @@
}
this._super();
},
+
+ /**
+ * set whether to ingore body's rotation
+ * @param {Boolean} b
+ */
setIgnoreBodyRotation: function(b) {
this._ignoreBodyRotation = b;
}
};
+
var chipmunkAPI = {
_ignoreBodyRotation:false,
_body:null, //physics body
@@ -154,16 +214,16 @@
/**
* Create a PhysicsSprite with filename and rect
- * @constructor
+ * 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 = cc.PhysicsSprite.create("res/HelloHTML5World.png");
+ * 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.
+ * 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
@@ -182,7 +242,7 @@
if (fileName === undefined) {
cc.PhysicsSprite.prototype.init.call(this);
- }else if (typeof(fileName) === "string") {
+ }else if (cc.isString(fileName)) {
if (fileName[0] === "#") {
//init with a sprite frame name
var frameName = fileName.substr(1, fileName.length - 1);
@@ -192,7 +252,7 @@
//init with filename and rect
this.init(fileName, rect);
}
- }else if (typeof(fileName) === "object") {
+ }else if (cc.isObject(fileName)) {
if (fileName instanceof cc.Texture2D) {
//init with texture and rect
this.initWithTexture(fileName, rect);
@@ -201,26 +261,61 @@
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;
@@ -231,10 +326,20 @@
}
//this._syncPosition();
},
+
+ /**
+ * set position x
+ * @param {Number} xValue
+ */
setPositionX:function (xValue) {
this._body.p.x = xValue;
//this._syncPosition();
},
+
+ /**
+ * set position y
+ * @param {Number} yValue
+ */
setPositionY:function (yValue) {
this._body.p.y = yValue;
//this._syncPosition();
@@ -242,13 +347,23 @@
_syncPosition:function () {
var locPosition = this._position, locBody = this._body;
- if (locPosition.x != locBody.p.x || locPosition.y != locBody.p.y) {
+ 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 ? cc.radiansToDegress(this._rotationRadiansX) : -cc.radiansToDegress(this._body.a);
+ 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);
@@ -258,94 +373,41 @@
}
},
_syncRotation:function () {
- if (this._rotationRadiansX != -this._body.a) {
- cc.Sprite.prototype.setRotation.call(this, -cc.radiansToDegress(this._body.a));
+ if (this._rotationX !== -cc.radiansToDegrees(this._body.a)) {
+ cc.Sprite.prototype.setRotation.call(this, -cc.radiansToDegrees(this._body.a));
}
},
- nodeToParentTransform:function () {
- if(cc._renderType === cc._RENDER_TYPE_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.dirty) {
- 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;
+ /**
+ * 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._RENDER_TYPE_CANVAS)
+ return new cc.PhysicsSprite.CanvasRenderCmd(this);
+ else
+ return new cc.PhysicsSprite.WebGLRenderCmd(this);
}
};
cc.PhysicsSprite = cc.Sprite.extend(chipmunkAPI);
@@ -362,31 +424,24 @@
/**
* Create a PhysicsSprite with filename and rect
- * @constructor
+ * @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}
- * @example
- *
- * 1.Create a sprite with image path and rect
- * var physicsSprite1 = cc.PhysicsSprite.create("res/HelloHTML5World.png");
- * var physicsSprite2 = cc.PhysicsSprite.create("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 = cc.PhysicsSprite.create('#grossini_dance_01.png');
- *
- * 3.Create a sprite with a sprite frame
- * var spriteFrame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
- * var physicsSprite = cc.PhysicsSprite.create(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 = cc.PhysicsSprite.create(texture);
- * var physicsSprite2 = cc.PhysicsSprite.create(texture, cc.rect(0,0,480,320));
- *
*/
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..ae95d94df9
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsSpriteCanvasRenderCmd.js
@@ -0,0 +1,93 @@
+/****************************************************************************
+ 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){
+ cc.Sprite.CanvasRenderCmd.call(this, 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);
+ };
+
+ proto.getNodeToParentTransform = function(){
+ var node = this._node;
+
+ var t = this._transform;// quick reference
+ // base position
+ var locBody = node._body, locScaleX = node._scaleX, locScaleY = node._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 && !node._ignoreBodyRotation) {
+ 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;
+ }
+
+ return this._transform;
+ };
+
+})();
\ No newline at end of file
diff --git a/cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js b/cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js
new file mode 100644
index 0000000000..332c8e5d6f
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js
@@ -0,0 +1,87 @@
+/****************************************************************************
+ 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){
+ cc.Sprite.WebGLRenderCmd.call(this, renderableObject);
+ this._needDraw = true;
+ };
+
+ var proto = cc.PhysicsSprite.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
+ proto.constructor = cc.PhysicsSprite.WebGLRenderCmd;
+
+ proto.rendering = function(ctx){
+ // 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.WebGLRenderCmd.prototype.rendering.call(this, ctx);
+ };
+
+ proto.getNodeToParentTransform = function(){
+ var node = this._node;
+ var locBody = node._body, locAnchorPIP = this._anchorPointInPoints, locScaleX = node._scaleX, locScaleY = node._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, c = 1, s=0;
+ if (radians && !node._ignoreBodyRotation) {
+ c = Math.cos(radians);
+ 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;
+ };
+
+ proto.updateTransform = function(){
+ this._dirty = this._node.isDirty();
+ cc.Sprite.WebGLRenderCmd.prototype.updateTransform.call(this);
+ };
+})();
\ No newline at end of file
diff --git a/cocos2d/progress-timer/CCActionProgressTimer.js b/cocos2d/progress-timer/CCActionProgressTimer.js
index 6245b0024a..026af89750 100644
--- a/cocos2d/progress-timer/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,6 +29,10 @@
* 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,
@@ -34,11 +40,9 @@ cc.ProgressTo = cc.ActionInterval.extend(/** @lends cc.ProgressTo# */{
/**
* Creates a ProgressTo action with a duration and a percent
- * @constructor
- * @param {Number} duration duration in seconds
- * @param {Number} percent
- * @example
- * var to = new cc.ProgressTo(2, 100);
+ * Constructor of cc.ProgressTo
+ * @param {Number} duration duration in seconds
+ * @param {Number} percent
*/
ctor: function(duration, percent){
cc.ActionInterval.prototype.ctor.call(this);
@@ -60,32 +64,35 @@ 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.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.percentage;
-
- // XXX: Is this correct ?
- // Adding it to support CCRepeat
- if (this._from == 100)
- this._from = 0;
},
/**
+ * custom update
* @param {Number} time time in seconds
*/
update:function (time) {
@@ -94,22 +101,39 @@ cc.ProgressTo = cc.ActionInterval.extend(/** @lends cc.ProgressTo# */{
}
});
-/** 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) {
+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,
@@ -117,12 +141,10 @@ cc.ProgressFromTo = cc.ActionInterval.extend(/** @lends cc.ProgressFromTo# */{
/**
* Creates and initializes the action with a duration, a "from" percentage and a "to" percentage
- * @constructor
- * @param {Number} duration duration in seconds
- * @param {Number} fromPercentage
- * @param {Number} toPercentage
- * @example
- * var fromTo = new cc.ProgressFromTo(2, 100.0, 0.0);
+ * 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);
@@ -146,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);
@@ -157,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) {
@@ -177,14 +203,25 @@ cc.ProgressFromTo = cc.ActionInterval.extend(/** @lends cc.ProgressFromTo# */{
});
/** 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) {
+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
index ee35370fea..3ad05586f0 100644
--- a/cocos2d/progress-timer/CCProgressTimer.js
+++ b/cocos2d/progress-timer/CCProgressTimer.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2011 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
@@ -23,38 +25,12 @@
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
+ * @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
@@ -65,12 +41,13 @@ cc.PROGRESS_TEXTURE_COORDS = 0x4b;
* 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)
- * 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.
- *
- * 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.
- *
+ * 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.
+ *
+ * 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.
+ *
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.
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.
+ * 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/CCGLStateCache.js b/cocos2d/shaders/CCGLStateCache.js index c8d890ae32..f048ce03e3 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 @@ -46,6 +46,7 @@ if (cc.ENABLE_GL_STATE_CACHE) { /** * Invalidates the GL state cache.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.
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.
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.
Return the dictionary for the specific object name.
* It will return the 1st object found on the array for the given name.
Return the dictionary for the specific object name.
+ * It will return the 1st object found on the array for the given name.
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
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.
Returns a tile from position x,y.
- * For the moment only channel R is used.
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.
+ * 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().
+ *
+ * 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().
+ *
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, + _gridProxy: null, _className:"TransitionPageTurn", /** @@ -67,9 +85,9 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu */ 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 }, /** @@ -87,19 +105,33 @@ 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.onEnter(); + gridProxy.runAction( cc.sequence(action,cc.callFunc(this.finish, this),cc.stopGrid())); } else { + gridProxy.setTarget(this._inScene); + gridProxy.onEnter(); // to prevent initial flicker this._inScene.visible = false; - this._inScene.runAction( - cc.Sequence.create(cc.Show.create(),action, cc.CallFunc.create(this.finish, this), cc.StopGrid.create()) + gridProxy.runAction( + cc.sequence(action, cc.callFunc(this.finish, this), cc.stopGrid()) ); + this._inScene.runAction(cc.show()); } }, + 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; } @@ -109,16 +141,12 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu * Creates a base transition with duration and incoming scene.
+ * 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...
+ *
+ * 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.
+ *
+ * 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
+ *
+ * Event callback that is invoked when the Node enters in the 'stage'.
+ * If the Node enters the 'stage' with a transition, this event is called when the transition finishes.
+ * If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. Node::onEnterTransitionDidFinish()
+ *
+ * Event callback that is called every time the Node leaves the 'stage'.
+ * If the Node leaves the 'stage' with a transition, this callback is called when the transition starts.
+ *
+ * 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.
+ * @note: it will refactor in v3.1
+ * @see http://yannickloriot.com/library/ios/cccontrolextension/Classes/CCScale9Sprite.html
+ *
+ * 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 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);
+ *
+ * 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
+ *
+ * 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
+ *
+ * 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;
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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(); }, /** @@ -888,8 +1002,8 @@ ccui.Widget = ccui.Node.extend(/** @lends ccui.Widget# */{ * @param {cc.Point} touchPoint */ onTouchCancelled: function (touchPoint) { - this.setFocused(false); - this.cancelUpEvent(); + this.setHighlighted(false); + this._cancelUpEvent(); }, /** @@ -901,71 +1015,74 @@ ccui.Widget = ccui.Node.extend(/** @lends ccui.Widget# */{ }, //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, ccui.Widget.TOUCH_BEGAN); - } - } + _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._touchEventListener && this._touchEventSelector) { - if (this._touchEventSelector) { - this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_MOVED); - } - } + _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._touchEventListener && this._touchEventSelector) { - if (this._touchEventSelector) { - this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_ENDED); - } - } + _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._touchEventSelector) { + _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 menu item + * Sets the touch event target/selector of the ccui.Widget * @param {Function} selector * @param {Object} target */ addTouchEventListener: function (selector, target) { - this._touchEventSelector = selector; - this._touchEventListener = 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} + * @returns {boolean} true if the point is in widget's space, false otherwise. */ hitTest: function (pt) { - var nsp = this.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; + var bb = cc.rect(0,0, this._contentSize.width, this._contentSize.height); + return cc.rectContainsPoint(bb, this.convertToNodeSpace(pt)); }, /** - * Checks a point if in parent's area. - * @param {cc.Point} pt + * returns whether clipping parent widget contains point. + * @param {cc.Point} pt location point * @returns {Boolean} */ - clippingParentAreaContainPoint: function (pt) { + isClippingParentContainsPoint: function(pt){ this._affectByClipping = false; var parent = this.getParent(); var clippingParent = null; @@ -980,209 +1097,235 @@ ccui.Widget = ccui.Node.extend(/** @lends ccui.Widget# */{ parent = parent.getParent(); } - if (!this._affectByClipping) { + if (!this._affectByClipping) return true; - } - if (clippingParent) { - var bRet = false; - if (clippingParent.hitTest(pt)) { - bRet = true; - } - if (bRet) { - return clippingParent.clippingParentAreaContainPoint(pt); - } + if (clippingParent.hitTest(pt)) + return clippingParent.isClippingParentContainsPoint(pt); return false; } return true; }, /** - * Sends the touch event to widget's parent + * 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) { + if (widgetParent) widgetParent.checkChildInfo(handleState, sender, touchPoint); - } }, /** * Changes the position (x,y) of the widget . - * @param {cc.Point||Number} pos - * @param {Number} posY + * 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._running) { + if (!this._usingLayoutComponent && this._running) { var widgetParent = this.getWidgetParent(); if (widgetParent) { - var pSize = widgetParent.getSize(); + var pSize = widgetParent.getContentSize(); if (pSize.width <= 0 || pSize.height <= 0) { this._positionPercent.x = 0; this._positionPercent.y = 0; - } - else { - if(posY){ - this._positionPercent.x = pos / pSize.width; - this._positionPercent.y = posY / pSize.height; - }else{ + } 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.apply(this, arguments); - }, - - 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); - }, + 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) { - this._positionPercent = percent; - if (this._running) { - var widgetParent = this.getWidgetParent(); - if(widgetParent){ - var parentSize = widgetParent.getSize(); - this.setPosition(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y); - } + 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) { - this._positionPercent.x = percent; - if (this._running) { - var widgetParent = this.getWidgetParent(); - if(widgetParent){ - var absX = widgetParent.width * percent; - this.setPositionX(absX); - } - } - }, - _setYPercent: function (percent) { - this._positionPercent.y = percent; - if (this._running) { - var widgetParent = this.getWidgetParent(); - if(widgetParent){ - var absY = widgetParent.height * percent; - this.setPositionY(absY); - } - } - }, - - updateAnchorPoint:function(){ - this.setAnchorPoint(this.getAnchorPoint()); + _setXPercent: function (percent) { + if (this._usingLayoutComponent){ + var component = this._getOrCreateLayoutComponent(); + component.setPositionPercentX(percent.x); + component.refreshLayout(); + return; + } + this._positionPercent.x = percent; + }, + _setYPercent: function (percent) { + if (this._usingLayoutComponent){ + var component = this._getOrCreateLayoutComponent(); + component.setPositionPercentY(percent.x); + component.refreshLayout(); + return; + } + this._positionPercent.y = percent; }, /** * Gets the percent (x,y) of the widget - * @returns {cc.Point} + * @returns {cc.Point} The percent (x,y) of the widget in OpenGL coordinates */ getPositionPercent: function () { - return this._positionPercent; + 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; }, - _getXPercent: function () { - return this._positionPercent.x; - }, - _getYPercent: function () { - return this._positionPercent.y; - }, /** * Changes the position type of the widget - * @param {ccui.Widget.POSITION_ABSOLUTE|ccui.Widget.POSITION_PERCENT} type + * @param {Number} type the position type of widget */ setPositionType: function (type) { - this.positionType = 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 {cc.pPositionType} + * @returns {Number} the position type of widget */ getPositionType: function () { - return this.positionType; + return this._positionType; }, /** - * Set flipped x - * @param {Boolean} flipX + * 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.updateFlippedX(); + this.setScaleX(realScale); }, /** - * Get flipped x - * @returns {Boolean} + *
+ * 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 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);
+ *
+ * Calls adaptRenderers (its subclass will override it.) and do layout. + * If clippingEnabled is true, it will clip/scissor area. + *
+ * @override + * @param {cc.Node.RenderCmd} [parentCmd] + */ + visit: function (parentCmd) { + if (!this._visible) return; - } + this._adaptRenderers(); + this._doLayout(); + if (this._clippingEnabled) { switch (this._clippingType) { case ccui.Layout.CLIPPING_STENCIL: - this.stencilClippingVisit(ctx); + this._renderCmd.stencilClippingVisit(parentCmd); break; case ccui.Layout.CLIPPING_SCISSOR: - this.scissorClippingVisit(ctx); + this._renderCmd.scissorClippingVisit(parentCmd); break; default: break; } - } - else { - cc.Node.prototype.visit.call(this,ctx); - } - }, - - sortAllChildren: function () { - ccui.Widget.prototype.sortAllChildren.call(this); - this._doLayout(); - }, - - stencilClippingVisit : null, - - _stencilClippingVisitForWebGL: 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._clippingStencil || !this._clippingStencil.isVisible()) { - 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. - ccui.Layout._layer = -1; - - // all the _stencilBits are in use? - if (ccui.Layout._layer + 1 == cc.stencilBits) { - // warn once - ccui.Layout._visit_once = true; - if (ccui.Layout._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._visit_once = false; - } - // draw everything, as if there where no stencil - cc.Node.prototype.visit.call(this, ctx); - return; - } - - /////////////////////////////////// - // INIT - - // increment the current layer - ccui.Layout._layer++; - - // mask of the current layer (ie: for layer 3: 00000100) - var mask_layer = 0x1 << ccui.Layout._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.checkGLErrorDebug(); - - // 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(gl.ZERO, 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.p(0,0), cc.pFromSize(cc.director.getWinSize()), cc.color(255, 255, 255, 255)); - - /////////////////////////////////// - // 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(gl.REPLACE, gl.KEEP, gl.KEEP); - - - // 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._clippingStencil.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 - ccui.Layout._layer--; - }, - - _stencilClippingVisitForCanvas: function (ctx) { - // return fast (draw nothing, or draw everything if in inverted mode) if: - // - nil stencil node - // - or stencil node invisible: - if (!this._clippingStencil || !this._clippingStencil.isVisible()) { - return; - } - var context = ctx || cc._renderContext; - // Composition mode, costy but support texture stencil - if (this._cangodhelpme() || this._clippingStencil instanceof cc.Sprite) { - // Cache the current canvas, for later use (This is a little bit heavy, replace this solution with other walkthrough) - var canvas = context.canvas; - var locCache = ccui.Layout._getSharedCache(); - locCache.width = canvas.width; - locCache.height = canvas.height; - var locCacheCtx = locCache.getContext("2d"); - locCacheCtx.drawImage(canvas, 0, 0); - - context.save(); - // Draw everything first using node visit function - cc.Node.prototype.visit.call(this, context); - - context.globalCompositeOperation = "destination-in"; - - this.transform(context); - this._clippingStencil.visit(); - - context.restore(); - - // Redraw the cached canvas, so that the cliped area shows the background etc. - context.save(); - context.setTransform(1, 0, 0, 1, 0, 0); - context.globalCompositeOperation = "destination-over"; - context.drawImage(locCache, 0, 0); - context.restore(); - } - // Clip mode, fast, but only support cc.DrawNode - else { - var i, children = this._children, locChild; - - context.save(); - this.transform(context); - this._clippingStencil.visit(context); - context.clip(); - - // Clip mode doesn't support recusive stencil, so once we used a clip stencil, - // so if it has ClippingNode as a child, the child must uses composition stencil. - this._cangodhelpme(true); - var len = children.length; - if (len > 0) { - this.sortAllChildren(); - // draw children zOrder < 0 - for (i = 0; i < len; i++) { - locChild = children[i]; - if (locChild._localZOrder < 0) - locChild.visit(context); - else - break; - } - this.draw(context); - for (; i < len; i++) { - children[i].visit(context); - } - } else - this.draw(context); - this._cangodhelpme(false); - - context.restore(); - } - }, - - _godhelpme:false, - _cangodhelpme: function (godhelpme) { - if (godhelpme === true || godhelpme === false) - cc.ClippingNode.prototype._godhelpme = godhelpme; - return cc.ClippingNode.prototype._godhelpme; - }, - - scissorClippingVisit : null, - _scissorClippingVisitForWebGL: function (ctx) { - var clippingRect = this.getClippingRect(); - var gl = ctx || cc._renderContext; - if (this._handleScissor) { - gl.enable(gl.SCISSOR_TEST); - } - cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height); - cc.Node.prototype.visit.call(this); - if (this._handleScissor) { - gl.disable(gl.SCISSOR_TEST); - } + } else + ccui.Widget.prototype.visit.call(this, parentCmd); }, /** * Changes if layout can clip it's content and locChild. - * @param {Boolean} able + * 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) { + if (able === this._clippingEnabled) return; - } this._clippingEnabled = able; switch (this._clippingType) { case ccui.Layout.CLIPPING_STENCIL: - if (able) { - this.setStencilClippingSize(this._size); - } - else { + if (able){ + this._clippingStencil = new cc.DrawNode(); + this._renderCmd.rebindStencilRendering(this._clippingStencil); + if (this._running) + this._clippingStencil.onEnter(); + this._setStencilClippingSize(this._contentSize); + } else { + if (this._running && this._clippingStencil) + this._clippingStencil.onExit(); this._clippingStencil = null; } break; @@ -472,11 +363,14 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Set clipping type + * Sets clipping type to ccui.Layout * @param {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR} type */ setClippingType: function (type) { - if (type == this._clippingType) { + if (type === this._clippingType) + return; + if(cc._renderType === cc._RENDER_TYPE_CANVAS && type === ccui.Layout.CLIPPING_SCISSOR){ + cc.log("Only supports STENCIL on canvas mode."); return; } var clippingEnabled = this.isClippingEnabled(); @@ -486,15 +380,15 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Get clipping type + * Gets clipping type of ccui.Layout * @returns {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR} */ - getClippingType : function(){ + getClippingType: function () { return this._clippingType; }, - setStencilClippingSize: function (size) { - if (this._clippingEnabled && this._clippingType == ccui.Layout.CLIPPING_STENCIL) { + _setStencilClippingSize: function (size) { + if (this._clippingEnabled && this._clippingType === ccui.Layout.CLIPPING_STENCIL) { var rect = []; rect[0] = cc.p(0, 0); rect[1] = cc.p(size.width, 0); @@ -506,39 +400,25 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ } }, - rendererVisitCallBack: function () { - this._doLayout(); - }, - - getClippingRect: function () { - if (this._clippingRectDirty){ - this._handleScissor = true; + _getClippingRect: function () { + if (this._clippingRectDirty) { var worldPos = this.convertToWorldSpace(cc.p(0, 0)); - var t = this.nodeToWorldTransform(); - var scissorWidth = this._size.width * t.a; - var scissorHeight = this._size.height * t.d; + var t = this.getNodeToWorldTransform(); + var scissorWidth = this._contentSize.width * t.a; + var scissorHeight = this._contentSize.height * t.d; var parentClippingRect; var parent = this; - var firstClippingParentFounded = false; + while (parent) { parent = parent.getParent(); - if (parent && parent instanceof ccui.Layout) { - if (parent.isClippingEnabled()) { - if (!firstClippingParentFounded) { - this._clippingParent = parent; - firstClippingParentFounded = true; - } - - if (parent._clippingType == ccui.Layout.CLIPPING_SCISSOR) { - this._handleScissor = false; - break; - } - } + if (parent && parent instanceof ccui.Layout && parent.isClippingEnabled()) { + this._clippingParent = parent; + break; } } if (this._clippingParent) { - parentClippingRect = this._clippingParent.getClippingRect(); + parentClippingRect = this._clippingParent._getClippingRect(); var finalX = worldPos.x - (scissorWidth * this._anchorPoint.x); var finalY = worldPos.y - (scissorHeight * this._anchorPoint.y); var finalWidth = scissorWidth; @@ -550,30 +430,25 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ finalWidth += leftOffset; } var rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.x + parentClippingRect.width); - if (rightOffset > 0) { + if (rightOffset > 0) finalWidth -= rightOffset; - } var topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.y + parentClippingRect.height); - if (topOffset > 0) { + if (topOffset > 0) finalHeight -= topOffset; - } var bottomOffset = worldPos.y - parentClippingRect.y; if (bottomOffset < 0) { finalY = parentClippingRect.x; finalHeight += bottomOffset; } - if (finalWidth < 0) { + if (finalWidth < 0) finalWidth = 0; - } - if (finalHeight < 0) { + if (finalHeight < 0) finalHeight = 0; - } this._clippingRect.x = finalX; this._clippingRect.y = finalY; this._clippingRect.width = finalWidth; this._clippingRect.height = finalHeight; - } - else { + } else { this._clippingRect.x = worldPos.x - (scissorWidth * this._anchorPoint.x); this._clippingRect.y = worldPos.y - (scissorHeight * this._anchorPoint.y); this._clippingRect.width = scissorWidth; @@ -584,55 +459,43 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ return this._clippingRect; }, - onSizeChanged: function () { - ccui.Widget.prototype.onSizeChanged.call(this); - this.setContentSize(this._size); - this.setStencilClippingSize(this._size); + _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(this._size.width / 2.0, this._size.height / 2.0); - if (this._backGroundScale9Enabled) { - 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); + 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 + * @param {Boolean} able true that use scale9 renderer, false otherwise. */ setBackGroundImageScale9Enabled: function (able) { - if (this._backGroundScale9Enabled == able) { + if (this._backGroundScale9Enabled === able) return; - } - cc.Node.prototype.removeChild.call(this, this._backGroundImage, true); + this.removeProtectedChild(this._backGroundImage); this._backGroundImage = null; this._backGroundScale9Enabled = able; - if (this._backGroundScale9Enabled) { - this._backGroundImage = cc.Scale9Sprite.create(); - } - else { - this._backGroundImage = cc.Sprite.create(); - } - cc.Node.prototype.addChild.call(this, this._backGroundImage, ccui.Layout.BACKGROUND_IMAGE_ZORDER, -1); + this._addBackGroundImage(); this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType); this.setBackGroundImageCapInsets(this._backGroundImageCapInsets); }, /** - * Get background image is use scale9 renderer. + * Get whether background image is use scale9 renderer. * @returns {Boolean} */ - isBackGroundImageScale9Enabled:function(){ + isBackGroundImageScale9Enabled: function () { return this._backGroundScale9Enabled; }, @@ -642,53 +505,59 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType */ setBackGroundImage: function (fileName, texType) { - if (!fileName) { + if (!fileName) return; - } texType = texType || ccui.Widget.LOCAL_TEXTURE; - if (this._backGroundImage == null) { - this.addBackGroundImage(); + 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: - this._backGroundImage.initWithFile(fileName); + locBackgroundImage.initWithFile(fileName); break; case ccui.Widget.PLIST_TEXTURE: - this._backGroundImage.initWithSpriteFrameName(fileName); + locBackgroundImage.initWithSpriteFrameName(fileName); break; default: break; } - if (this._backGroundScale9Enabled) { - this._backGroundImage.setPreferredSize(this._size); - } - this._backGroundImageTextureSize = this._backGroundImage.getContentSize(); - this._backGroundImage.setPosition(this._size.width / 2.0, this._size.height / 2.0); - this.updateBackGroundImageColor(); + 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 + * 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) { - this._backGroundImageCapInsets = capInsets; - if (this._backGroundScale9Enabled) { + 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); - } }, /** - * Get background image cap insets. + * Gets background image capinsets of ccui.Layout. * @returns {cc.Rect} */ - getBackGroundImageCapInsets:function(){ - return this._backGroundImageCapInsets; + getBackGroundImageCapInsets: function () { + return cc.rect(this._backGroundImageCapInsets); }, - supplyTheLayoutParameterLackToChild: function (locChild) { + _supplyTheLayoutParameterLackToChild: function (locChild) { if (!locChild) { return; } @@ -698,77 +567,70 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ case ccui.Layout.LINEAR_HORIZONTAL: case ccui.Layout.LINEAR_VERTICAL: var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.LINEAR); - if (!layoutParameter) { - locChild.setLayoutParameter(ccui.LinearLayoutParameter.create()); - } + if (!layoutParameter) + locChild.setLayoutParameter(new ccui.LinearLayoutParameter()); break; case ccui.Layout.RELATIVE: var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.RELATIVE); - if (!layoutParameter) { - locChild.setLayoutParameter(ccui.RelativeLayoutParameter.create()); - } + if (!layoutParameter) + locChild.setLayoutParameter(new ccui.RelativeLayoutParameter()); break; default: break; } }, - /** - * init background image renderer. - */ - addBackGroundImage: function () { + _addBackGroundImage: function () { + var contentSize = this._contentSize; if (this._backGroundScale9Enabled) { - this._backGroundImage = cc.Scale9Sprite.create(); - this._backGroundImage.setPreferredSize(this._size); - } - else { - this._backGroundImage = cc.Sprite.create(); - } - cc.Node.prototype.addChild.call(this, this._backGroundImage, ccui.Layout.BACKGROUND_IMAGE_ZORDER, -1); - this._backGroundImage.setPosition(this._size.width / 2.0, this._size.height / 2.0); + 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 layout. + * Remove the background image of ccui.Layout. */ removeBackGroundImage: function () { - if (!this._backGroundImage) { + if (!this._backGroundImage) return; - } - cc.Node.prototype.removeChild.call(this, this._backGroundImage, true); + this.removeProtectedChild(this._backGroundImage); this._backGroundImage = null; this._backGroundImageFileName = ""; - this._backGroundImageTextureSize = cc.size(0, 0); + this._backGroundImageTextureSize.width = 0; + this._backGroundImageTextureSize.height = 0; }, /** - * Sets Color Type for layout. + * 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) { + if (this._colorType === type) return; - } switch (this._colorType) { case ccui.Layout.BG_COLOR_NONE: if (this._colorRender) { - cc.Node.prototype.removeChild.call(this, this._colorRender, true); + this.removeProtectedChild(this._colorRender); this._colorRender = null; } if (this._gradientRender) { - cc.Node.prototype.removeChild.call(this, this._gradientRender, true); + this.removeProtectedChild(this._gradientRender); this._gradientRender = null; } break; case ccui.Layout.BG_COLOR_SOLID: if (this._colorRender) { - cc.Node.prototype.removeChild.call(this, this._colorRender, true); + this.removeProtectedChild(this._colorRender); this._colorRender = null; } break; case ccui.Layout.BG_COLOR_GRADIENT: if (this._gradientRender) { - cc.Node.prototype.removeChild.call(this, this._gradientRender, true); + this.removeProtectedChild(this._gradientRender); this._gradientRender = null; } break; @@ -780,20 +642,20 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ case ccui.Layout.BG_COLOR_NONE: break; case ccui.Layout.BG_COLOR_SOLID: - this._colorRender = cc.LayerColor.create(); - this._colorRender.setContentSize(this._size); + this._colorRender = new cc.LayerColor(); + this._colorRender.setContentSize(this._contentSize); this._colorRender.setOpacity(this._opacity); this._colorRender.setColor(this._color); - cc.Node.prototype.addChild.call(this, this._colorRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1); + this.addProtectedChild(this._colorRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1); break; case ccui.Layout.BG_COLOR_GRADIENT: - this._gradientRender = cc.LayerGradient.create(cc.color(255, 0, 0, 255), cc.color(0, 255, 0, 255)); - this._gradientRender.setContentSize(this._size); + 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); - cc.Node.prototype.addChild.call(this, this._gradientRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1); + this.addProtectedChild(this._gradientRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1); break; default: break; @@ -801,67 +663,69 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Get color type. + * 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(){ + 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 + * @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) { + 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) { + if (this._gradientRender) this._gradientRender.setStartColor(color); - } - this._endColor = endColor; - if (this._gradientRender) { + + this._endColor.r = endColor.r; + this._endColor.g = endColor.g; + this._endColor.b = endColor.b; + if (this._gradientRender) this._gradientRender.setEndColor(endColor); - } } }, /** - * Get back ground color + * Gets background color of ccui.Layout, if color type is Layout.COLOR_SOLID. * @returns {cc.Color} */ - getBackGroundColor:function(){ - return this._color; + getBackGroundColor: function () { + var tmpColor = this._color; + return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a); }, /** - * Get back ground start color + * Gets background start color of ccui.Layout * @returns {cc.Color} */ - getBackGroundStartColor:function(){ - return this._startColor; + getBackGroundStartColor: function () { + var tmpColor = this._startColor; + return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a); }, /** - * Get back ground end color + * Gets background end color of ccui.Layout * @returns {cc.Color} */ - getBackGroundEndColor:function(){ - return this._endColor; + getBackGroundEndColor: function () { + var tmpColor = this._endColor; + return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a); }, /** - * Sets background opacity layout. + * Sets background opacity to ccui.Layout. * @param {number} opacity */ setBackGroundColorOpacity: function (opacity) { @@ -881,10 +745,10 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Get background opacity value. + * Get background opacity value of ccui.Layout. * @returns {Number} */ - getBackGroundColorOpacity:function(){ + getBackGroundColorOpacity: function () { return this._opacity; }, @@ -901,15 +765,15 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Get background color value. + * Gets background color vector of ccui.Layout, if color type is Layout.COLOR_GRADIENT * @returns {cc.Point} */ - getBackGroundColorVector:function(){ + getBackGroundColorVector: function () { return this._alongVector; }, /** - * Set backGround image color + * Sets backGround image color * @param {cc.Color} color */ setBackGroundImageColor: function (color) { @@ -917,14 +781,11 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ this._backGroundImageColor.g = color.g; this._backGroundImageColor.b = color.b; - this.updateBackGroundImageColor(); - if (color.a !== undefined && !color.a_undefined) { - this.setBackGroundImageOpacity(color.a); - } + this._updateBackGroundImageColor(); }, /** - * Get backGround image color + * Sets backGround image Opacity * @param {Number} opacity */ setBackGroundImageOpacity: function (opacity) { @@ -933,7 +794,7 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Get backGround image color + * Gets backGround image color * @returns {cc.Color} */ getBackGroundImageColor: function () { @@ -942,15 +803,16 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Get backGround image opacity + * Gets backGround image opacity * @returns {Number} */ getBackGroundImageOpacity: function () { return this._backGroundImageColor.a; }, - updateBackGroundImageColor: function () { - this._backGroundImage.setColor(this._backGroundImageColor); + _updateBackGroundImageColor: function () { + if(this._backGroundImage) + this._backGroundImage.setColor(this._backGroundImageColor); }, /** @@ -962,22 +824,23 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * Sets LayoutType. + * 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._widgetChildren; + var layoutChildrenArray = this._children; var locChild = null; for (var i = 0; i < layoutChildrenArray.length; i++) { locChild = layoutChildrenArray[i]; - this.supplyTheLayoutParameterLackToChild(locChild); + if(locChild instanceof ccui.Widget) + this._supplyTheLayoutParameterLackToChild(locChild); } this._doLayoutDirty = true; }, /** - * Gets LayoutType. + * Gets LayoutType of ccui.Layout. * @returns {null} */ getLayoutType: function () { @@ -985,489 +848,563 @@ ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{ }, /** - * request do layout + * request to refresh widget layout, it will do layout at visit calls */ requestDoLayout: function () { this._doLayoutDirty = true; }, - doLayout_LINEAR_VERTICAL: function () { - var layoutChildrenArray = this._widgetChildren; - var layoutSize = this.getSize(); - var topBoundary = layoutSize.height; - for (var i = 0; i < layoutChildrenArray.length; ++i) { - var locChild = layoutChildrenArray[i]; - var locLayoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.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 ccui.LINEAR_GRAVITY_NONE: - case ccui.LINEAR_GRAVITY_LEFT: - break; - case ccui.LINEAR_GRAVITY_RIGHT: - locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width); - break; - case ccui.LINEAR_GRAVITY_CENTER_HORIZONTAL: - locFinalPosX = layoutSize.width / 2 - locSize.width * (0.5 - locAP.x); - break; - default: - break; + _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; } - var locMargin = locLayoutParameter.getMargin(); - locFinalPosX += locMargin.left; - locFinalPosY -= locMargin.top; - locChild.setPosition(locFinalPosX, locFinalPosY); - topBoundary = locChild.getBottomInParent() - locMargin.bottom; } } + + //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; }, - doLayout_LINEAR_HORIZONTAL: function () { - var layoutChildrenArray = this._widgetChildren; - var layoutSize = this.getSize(); - var leftBoundary = 0; - for (var i = 0; i < layoutChildrenArray.length; ++i) { - var locChild = layoutChildrenArray[i]; - var locLayoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.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 ccui.LINEAR_GRAVITY_NONE: - case ccui.LINEAR_GRAVITY_TOP: - break; - case ccui.LINEAR_GRAVITY_BOTTOM: - locFinalPosY = locAP.y * locSize.height; - break; - case ccui.LINEAR_GRAVITY_CENTER_VERTICAL: - locFinalPosY = layoutSize.height / 2 - locSize.height * (0.5 - locAP.y); - break; - default: - break; + + /** + * When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child
+ * 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);
+ *
+ * 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/
+ *
+ * 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
+ *
+ * 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.
+ *
+ * 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
+ *
+ * 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
+ *
+ * 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 = []; - if (!boneData) { + this._decoDisplayList.length = 0; + if (!boneData) return; - } - var displayList = boneData.displayDataList; + var displayList = boneData.displayDataList, decoList = this._decoDisplayList, locBone = this._bone; for (var i = 0; i < displayList.length; i++) { var displayData = displayList[i]; - var decoDisplay = ccs.DecorativeDisplay.create(); + var decoDisplay = new ccs.DecorativeDisplay(); decoDisplay.setDisplayData(displayData); - - ccs.DisplayFactory.createDisplay(this._bone, decoDisplay); - - this._decoDisplayList.push(decoDisplay); + 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) { - var p = cc.p(0, 0); - if (y === undefined) { - p.x = point.x; - p.y = point.y; - } else { - p.x = point; - p.y = y; - } - if (!this._visible || this._displayIndex < 0) { + if (!this._visible || this._displayIndex < 0) return false; - } - var ret = false; - switch (this._currentDecoDisplay.getDisplayData().displayType) { - case 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 outPoint = cc.p(0, 0); - var sprite = this._currentDecoDisplay.getDisplay(); - sprite = sprite.getChildByTag(0); - ret = ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, p, outPoint); - break; - default: - break; + 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 ret; + return false; }, + /** + *
+ * Sets whether the display is visible
+ * The default value is true, a node is default to visible
+ *
- * The sprite frame cache helper
+ * ccs.spriteFrameCacheHelper is a singleton object, it's a sprite frame cache helper
+ * @class
+ * @name ccs.spriteFrameCacheHelper
*/
-ccs.spriteFrameCacheHelper = /** @lends cc.spriteFrameCacheHelper# */ {
+ccs.spriteFrameCacheHelper = /** @lends ccs.spriteFrameCacheHelper# */ {
_textureAtlasDic:{},
_imagePaths:[],
+ /**
+ * Adds sprite frame from file
+ * @param plistPath
+ * @param imagePath
+ */
addSpriteFrameFromFile:function (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.create(texture, 20);
+ atlas = new cc.TextureAtlas(texture, 20);
this._textureAtlasDic[textureName] = atlas;
}
return atlas;
},
+ /**
+ * Clear the sprite frame cache's data.
+ */
clear: function () {
this._textureAtlasDic = {};
this._imagePaths = [];
diff --git a/extensions/cocostudio/armature/utils/CCTransformHelp.js b/extensions/cocostudio/armature/utils/CCTransformHelp.js
index d2430c2b10..0d6228d5cd 100644
--- a/extensions/cocostudio/armature/utils/CCTransformHelp.js
+++ b/extensions/cocostudio/armature/utils/CCTransformHelp.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,38 +24,86 @@
****************************************************************************/
/**
- * @ignore
+ * 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.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
- * @return {cc.AffineTransform}
* Constructor
*/
-ccs.TransformHelp.transformFromParent = function (bone, parentBone) {
+ccs.TransformHelp.transformFromParent = function (bone, parentNode) {
this.nodeToMatrix(bone, this.helpMatrix1);
- this.nodeToMatrix(parentBone, this.helpMatrix2);
+ this.nodeToMatrix(parentNode, this.helpMatrix2);
- this.helpMatrix2 = cc.AffineTransformInvert(this.helpMatrix2);
- this.helpMatrix1 = cc.AffineTransformConcat(this.helpMatrix1, 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) {
+ if (node.skewX === -node.skewY) {
var sine = Math.sin(node.skewX);
var cosine = Math.cos(node.skewX);
matrix.a = node.scaleX * cosine;
@@ -65,7 +114,7 @@ ccs.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.d = node.scaleY * Math.cos(node.skewX);
}
matrix.tx = node.x;
matrix.ty = node.y;
@@ -73,6 +122,7 @@ ccs.TransformHelp.nodeToMatrix = function (node, matrix) {
/**
* @function
+ * @static
* @param {cc.AffineTransform} matrix
* @param {ccs.BaseData} node
*/
@@ -83,13 +133,13 @@ ccs.TransformHelp.matrixToNode = function (matrix, node) {
*/
this.helpPoint1.x = 0;
this.helpPoint1.y = 1;
- this.helpPoint1 = cc.PointApplyAffineTransform(this.helpPoint1, matrix);
+ 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 = cc.pointApplyAffineTransform(this.helpPoint2, matrix);
this.helpPoint2.x -= matrix.tx;
this.helpPoint2.y -= matrix.ty;
@@ -104,6 +154,7 @@ ccs.TransformHelp.matrixToNode = function (matrix, node) {
/**
* @function
+ * @static
* @param {ccs.BaseData} target
* @param {ccs.BaseData} source
*/
@@ -118,6 +169,7 @@ ccs.TransformHelp.nodeConcat = function (target, source) {
/**
* @function
+ * @static
* @param {ccs.BaseData} target
* @param {ccs.BaseData} source
*/
diff --git a/extensions/cocostudio/armature/utils/CCTweenFunction.js b/extensions/cocostudio/armature/utils/CCTweenFunction.js
index 15a71cc16f..7ced7fad96 100644
--- a/extensions/cocostudio/armature/utils/CCTweenFunction.js
+++ b/extensions/cocostudio/armature/utils/CCTweenFunction.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
@@ -27,165 +28,177 @@
* @type Object
*/
ccs.TweenType = {
- customEasing: -1,
- linear: 0,
+ CUSTOM_EASING: -1,
+ LINEAR: 0,
- sineEaseIn: 1,
- sineEaseOut: 2,
- sineEaseInOut: 3,
+ SINE_EASEIN: 1,
+ SINE_EASEOUT: 2,
+ SINE_EASEINOUT: 3,
- quadEaseIn: 4,
- quadEaseOut: 5,
- quadEaseInOut: 6,
+ QUAD_EASEIN: 4,
+ QUAD_EASEOUT: 5,
+ QUAD_EASEINOUT: 6,
- cubicEaseIn: 7,
- cubicEaseOut: 8,
- cubicEaseInOut: 9,
+ CUBIC_EASEIN: 7,
+ CUBIC_EASEOUT: 8,
+ CUBIC_EASEINOUT: 9,
- quartEaseIn: 10,
- quartEaseOut: 11,
- quartEaseInOut: 12,
+ QUART_EASEIN: 10,
+ QUART_EASEOUT: 11,
+ QUART_EASEINOUT: 12,
- quintEaseIn: 13,
- quintEaseOut: 14,
- quintEaseInOut: 15,
+ QUINT_EASEIN: 13,
+ QUINT_EASEOUT: 14,
+ QUINT_EASEINOUT: 15,
- expoEaseIn: 16,
- expoEaseOut: 17,
- expoEaseInOut: 18,
+ EXPO_EASEIN: 16,
+ EXPO_EASEOUT: 17,
+ EXPO_EASEINOUT: 18,
- circEaseIn: 19,
- eircEaseOut: 20,
- circEaseInOut: 21,
+ CIRC_EASEIN: 19,
+ CIRC_EASEOUT: 20,
+ CIRC_EASEINOUT: 21,
- elasticEaseIn: 22,
- elasticEaseOut: 23,
- elasticEaseInOut: 24,
+ ELASTIC_EASEIN: 22,
+ ELASTIC_EASEOUT: 23,
+ ELASTIC_EASEINOUT: 24,
- backEaseIn: 25,
- backEaseOut: 26,
- backEaseInOut: 27,
+ BACK_EASEIN: 25,
+ BACK_EASEOUT: 26,
+ BACK_EASEINOUT: 27,
- bounceEaseIn: 28,
- bounceEaseOut: 29,
- bounceEaseInOut: 30,
+ BOUNCE_EASEIN: 28,
+ BOUNCE_EASEOUT: 29,
+ BOUNCE_EASEINOUT: 30,
- tweenEasingMax: 10000
+ TWEEN_EASING_MAX: 10000
};
ccs.TweenFunction = ccs.TweenFunction || ccs.Class.extend({});
-ccs.M_PI_X_2 = Math.PI * 2;
-ccs.M_PI_2 = Math.PI / 2;
+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.customEasing:
+ case ccs.TweenType.CUSTOM_EASING:
delta = this.customEase(time, easingParam);
break;
- case ccs.TweenType.linear:
+ case ccs.TweenType.LINEAR:
delta = this.linear(time);
break;
- case ccs.TweenType.sineEaseIn:
+ case ccs.TweenType.SINE_EASEIN:
delta = this.sineEaseIn(time);
break;
- case ccs.TweenType.sineEaseOut:
+ case ccs.TweenType.SINE_EASEOUT:
delta = this.sineEaseOut(time);
break;
- case ccs.TweenType.sineEaseInOut:
+ case ccs.TweenType.SINE_EASEINOUT:
delta = this.sineEaseInOut(time);
break;
- case ccs.TweenType.quadEaseIn:
+ case ccs.TweenType.QUAD_EASEIN:
delta = this.quadEaseIn(time);
break;
- case ccs.TweenType.quadEaseOut:
+ case ccs.TweenType.QUAD_EASEOUT:
delta = this.quadEaseOut(time);
break;
- case ccs.TweenType.quadEaseInOut:
+ case ccs.TweenType.QUAD_EASEINOUT:
delta = this.quadEaseInOut(time);
break;
- case ccs.TweenType.cubicEaseIn:
+ case ccs.TweenType.CUBIC_EASEIN:
delta = this.cubicEaseIn(time);
break;
- case ccs.TweenType.cubicEaseOut:
+ case ccs.TweenType.CUBIC_EASEOUT:
delta = this.cubicEaseOut(time);
break;
- case ccs.TweenType.cubicEaseInOut:
+ case ccs.TweenType.CUBIC_EASEINOUT:
delta = this.cubicEaseInOut(time);
break;
- case ccs.TweenType.quartEaseIn:
+ case ccs.TweenType.QUART_EASEIN:
delta = this.quartEaseIn(time);
break;
- case ccs.TweenType.quartEaseOut:
+ case ccs.TweenType.QUART_EASEOUT:
delta = this.quartEaseOut(time);
break;
- case ccs.TweenType.quartEaseInOut:
+ case ccs.TweenType.QUART_EASEINOUT:
delta = this.quartEaseInOut(time);
break;
- case ccs.TweenType.quintEaseIn:
+ case ccs.TweenType.QUINT_EASEIN:
delta = this.quintEaseIn(time);
break;
- case ccs.TweenType.quintEaseOut:
+ case ccs.TweenType.QUINT_EASEOUT:
delta = this.quintEaseOut(time);
break;
- case ccs.TweenType.quintEaseInOut:
+ case ccs.TweenType.QUINT_EASEINOUT:
delta = this.quintEaseInOut(time);
break;
- case ccs.TweenType.expoEaseIn:
+ case ccs.TweenType.EXPO_EASEIN:
delta = this.expoEaseIn(time);
break;
- case ccs.TweenType.expoEaseOut:
+ case ccs.TweenType.EXPO_EASEOUT:
delta = this.expoEaseOut(time);
break;
- case ccs.TweenType.expoEaseInOut:
+ case ccs.TweenType.EXPO_EASEINOUT:
delta = this.expoEaseInOut(time);
break;
- case ccs.TweenType.circEaseIn:
+ case ccs.TweenType.CIRC_EASEIN:
delta = this.circEaseIn(time);
break;
- case ccs.TweenType.eircEaseOut:
+ case ccs.TweenType.CIRC_EASEOUT:
delta = this.circEaseOut(time);
break;
- case ccs.TweenType.circEaseInOut:
+ case ccs.TweenType.CIRC_EASEINOUT:
delta = this.circEaseInOut(time);
break;
- case ccs.TweenType.elasticEaseIn:
- delta = this.elasticEaseIn(time, easingParam);
+ 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.elasticEaseOut:
- delta = this.elasticEaseOut(time, easingParam);
+ 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.elasticEaseInOut:
- delta = this.elasticEaseInOut(time, easingParam);
+ 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.backEaseIn:
+ case ccs.TweenType.BACK_EASEIN:
delta = this.backEaseIn(time);
break;
- case ccs.TweenType.backEaseOut:
+ case ccs.TweenType.BACK_EASEOUT:
delta = this.backEaseOut(time);
break;
- case ccs.TweenType.backEaseInOut:
+ case ccs.TweenType.BACK_EASEINOUT:
delta = this.backEaseInOut(time);
break;
- case ccs.TweenType.bounceEaseIn:
+ case ccs.TweenType.BOUNCE_EASEIN:
delta = this.bounceEaseIn(time);
break;
- case ccs.TweenType.bounceEaseOut:
+ case ccs.TweenType.BOUNCE_EASEOUT:
delta = this.bounceEaseOut(time);
break;
- case ccs.TweenType.bounceEaseInOut:
+ case ccs.TweenType.BOUNCE_EASEINOUT:
delta = this.bounceEaseInOut(time);
break;
@@ -206,10 +219,10 @@ ccs.TweenFunction.linear = function (time) {
// Sine Ease
ccs.TweenFunction.sineEaseIn = function (time) {
- return -1 * Math.cos(time * ccs.M_PI_2) + 1;
+ return -1 * Math.cos(time * ccs.HALF_PI) + 1;
};
ccs.TweenFunction.sineEaseOut = function (time) {
- return Math.sin(time * ccs.M_PI_2);
+ return Math.sin(time * ccs.HALF_PI);
};
ccs.TweenFunction.sineEaseInOut = function (time) {
return -0.5 * (Math.cos(ccs.M_PI * time) - 1);
@@ -285,10 +298,10 @@ ccs.TweenFunction.quintEaseInOut = function (time) {
// Expo Ease
ccs.TweenFunction.expoEaseIn = function (time) {
- return time == 0 ? 0 : Math.pow(2, 10 * (time - 1)) - 0.001;
+ 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);
+ return time === 1 ? 1 : (-Math.pow(2, -10 * time) + 1);
};
ccs.TweenFunction.expoEaseInOut = function (time) {
time /= 0.5;
@@ -329,13 +342,13 @@ ccs.TweenFunction.elasticEaseIn = function (time, easingParam) {
}
var newT = 0;
- if (time == 0 || time == 1) {
+ 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.M_PI_X_2 / period);
+ newT = -Math.pow(2, 10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period);
}
return newT;
@@ -348,12 +361,12 @@ ccs.TweenFunction.elasticEaseOut = function (time, easingParam) {
}
var newT = 0;
- if (time == 0 || time == 1) {
+ if (time === 0 || time === 1) {
newT = time;
}
else {
var s = period / 4;
- newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.M_PI_X_2 / period) + 1;
+ newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period) + 1;
}
return newT;
@@ -366,7 +379,7 @@ ccs.TweenFunction.elasticEaseInOut = function (time, easingParam) {
}
var newT = 0;
- if (time == 0 || time == 1) {
+ if (time === 0 || time === 1) {
newT = time;
}
else {
@@ -379,10 +392,9 @@ ccs.TweenFunction.elasticEaseInOut = function (time, easingParam) {
time = time - 1;
if (time < 0) {
- newT = -0.5 * Math.pow(2, 10 * time) * Math.sin((time - s) * ccs.M_PI_X_2 / period);
- }
- else {
- newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.M_PI_X_2 / period) * 0.5 + 1;
+ 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;
@@ -442,8 +454,7 @@ ccs.TweenFunction.bounceEaseInOut = function (time) {
if (time < 0.5) {
time = time * 2;
newT = (1 - ccs.bounceTime(1 - time)) * 0.5;
- }
- else {
+ } else {
newT = ccs.bounceTime(time * 2 - 1) * 0.5 + 0.5;
}
@@ -458,4 +469,33 @@ ccs.TweenFunction.customEase = function (time, easingParam) {
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
index b960b05754..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
@@ -36,13 +37,13 @@ var CC_SAFE_RELEASE = function (obj) {
};
ccs.isSpriteContainPoint = function (sprite, point, outPoint) {
- var p = cc.p(0, 0);
+ 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);
};
ccs.SPRITE_CONTAIN_POINT = ccs.isSpriteContainPoint;
ccs.SPRITE_CONTAIN_POINT_WITH_RETURN = ccs.isSpriteContainPoint;
diff --git a/extensions/cocostudio/components/CCComAttribute.js b/extensions/cocostudio/components/CCComAttribute.js
index 0b91d17cbe..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,26 +24,36 @@
****************************************************************************/
/**
- * Base class for ccs.ComAttribute
+ * The attribute component for Cocostudio.
* @class
* @extends ccs.Component
*/
ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
_jsonDict: null,
_filePath: "",
+
+ /**
+ * Construction of ccs.ComAttribute
+ */
ctor: function () {
cc.Component.prototype.ctor.call(this);
this._jsonDict = {};
this._filePath = "";
this._name = "CCComAttribute";
+ ccs.ComAttribute.prototype.init.call(this);
},
+
+ /**
+ * Initializes a ccs.ComAttribute
+ * @returns {boolean}
+ */
init: function () {
this._jsonDict = {};
return true;
},
/**
- * Set int attribute
+ * Sets int attribute
* @param {String} key
* @param {number} value
*/
@@ -55,7 +66,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Set double attribute
+ * Sets double attribute
* @param {String} key
* @param {number} value
*/
@@ -68,7 +79,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Set float attribute
+ * Sets float attribute
* @param {String} key
* @param {number} value
*/
@@ -81,7 +92,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Set boolean attribute
+ * Sets boolean attribute
* @param {String} key
* @param {Boolean} value
*/
@@ -94,7 +105,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Set string attribute
+ * Sets string attribute
* @param {String} key
* @param {Boolean} value
*/
@@ -107,7 +118,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Set object attribute
+ * Sets object attribute
* @param {String} key
* @param {Object} value
*/
@@ -120,7 +131,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Get int value from attribute
+ * Returns int value from attribute
* @param {String} key
* @returns {Number}
*/
@@ -130,7 +141,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Get double value from attribute
+ * Returns double value from attribute
* @param {String} key
* @returns {Number}
*/
@@ -140,7 +151,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Get float value from attribute
+ * Returns float value from attribute
* @param {String} key
* @returns {Number}
*/
@@ -150,7 +161,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Get boolean value from attribute
+ * Returns boolean value from attribute
* @param {String} key
* @returns {Boolean}
*/
@@ -160,7 +171,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Get string value from attribute
+ * Returns string value from attribute
* @param {String} key
* @returns {String}
*/
@@ -170,7 +181,7 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- * Get object value from attribute
+ * Returns object value from attribute
* @param {String} key
* @returns {Object}
*/
@@ -179,25 +190,21 @@ ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
},
/**
- *
- * @param path
+ * Parses json file.
+ * @param filename
*/
- parse:function(path){
- this._jsonDict = cc.loader.getRes(path);
+ parse:function(filename){
+ this._jsonDict = cc.loader.getRes(filename);
}
});
/**
* allocates and initializes a ComAttribute.
- * @constructs
+ * @deprecated since v3.0, please use new construction instead.
* @return {ccs.ComAttribute}
* @example
* // example
* var com = ccs.ComAttribute.create();
*/
ccs.ComAttribute.create = function () {
- var com = new ccs.ComAttribute();
- if (com && com.init()) {
- return com;
- }
- return null;
+ return new ccs.ComAttribute();
};
\ No newline at end of file
diff --git a/extensions/cocostudio/components/CCComAudio.js b/extensions/cocostudio/components/CCComAudio.js
index a3868a7c78..0b15af0b9a 100644
--- a/extensions/cocostudio/components/CCComAudio.js
+++ b/extensions/cocostudio/components/CCComAudio.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,29 +24,43 @@
****************************************************************************/
/**
- * Base class for ccs.ComAudio
+ * 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;
},
- onEnter: function () {
- },
-
+ /**
+ * 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();
},
@@ -60,8 +75,8 @@ ccs.ComAudio = ccs.Component.extend(/** @lends ccs.ComAudio# */{
/**
* Play background music
- * @param {String} pszFilePath
- * @param {Boolean} loop
+ * @param {String} [pszFilePath]
+ * @param {Boolean} [loop]
*/
playBackgroundMusic: function (pszFilePath, loop) {
if(pszFilePath){
@@ -150,16 +165,15 @@ ccs.ComAudio = ccs.Component.extend(/** @lends ccs.ComAudio# */{
/**
* Play sound effect.
- * @param {String} pszFilePath
- * @param {Boolean} loop
+ * @param {String} [pszFilePath]
+ * @param {Boolean} [loop]
* @returns {Boolean}
*/
playEffect: function (pszFilePath, loop) {
- if (pszFilePath) {
+ if (pszFilePath)
return cc.audioEngine.playEffect(pszFilePath, loop);
- } else {
+ else
return cc.audioEngine.playEffect(this._filePath, this._loop);
- }
},
/**
@@ -234,7 +248,7 @@ ccs.ComAudio = ccs.Component.extend(/** @lends ccs.ComAudio# */{
},
/**
- * Set loop
+ * Sets audio component whether plays loop
* @param {Boolean} loop
*/
setLoop: function (loop) {
@@ -242,7 +256,7 @@ ccs.ComAudio = ccs.Component.extend(/** @lends ccs.ComAudio# */{
},
/**
- * File path Getter
+ * Returns the file path of audio component.
* @returns {string}
*/
getFile: function () {
@@ -250,25 +264,22 @@ ccs.ComAudio = ccs.Component.extend(/** @lends ccs.ComAudio# */{
},
/**
- * Whether is loop
+ * Returns audio component whether plays loop
* @returns {boolean}
*/
isLoop: function () {
return this._loop;
}
});
+
/**
* allocates and initializes a ComAudio.
- * @constructs
+ * @deprecated since v3.0, please use new construction instead.
* @return {ccs.ComAudio}
* @example
* // example
* var com = ccs.ComAudio.create();
*/
ccs.ComAudio.create = function () {
- var com = new ccs.ComAudio();
- if (com && com.init()) {
- return com;
- }
- return null;
+ return new ccs.ComAudio();
};
\ No newline at end of file
diff --git a/extensions/cocostudio/components/CCComController.js b/extensions/cocostudio/components/CCComController.js
index 1f2c7ead72..cdd85eeb94 100644
--- a/extensions/cocostudio/components/CCComController.js
+++ b/extensions/cocostudio/components/CCComController.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,32 +24,31 @@
****************************************************************************/
/**
- * Base class for ccs.ComController
+ * 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";
- },
- init: function () {
- return true;
+ ccs.ComController.prototype.init.call(this);
},
+ /**
+ * The callback calls when controller component enter stage.
+ * @override
+ */
onEnter: function () {
-
- },
-
- onExit: function () {
-
- },
-
- update: function (dt) {
+ if (this._owner !== null)
+ this._owner.scheduleUpdate();
},
/**
- * Enabled getter
+ * Returns controller component whether is enabled
* @returns {Boolean}
*/
isEnabled: function () {
@@ -56,25 +56,21 @@ ccs.ComController = ccs.Component.extend(/** @lends ccs.ComController# */{
},
/**
- * Enabled setter
+ * Sets controller component whether is enabled
* @param {Boolean} bool
*/
setEnabled: function (bool) {
- this._enabled = b;
+ this._enabled = bool;
}
});
/**
- * allocates and initializes a ComController.
- * @constructs
+ * 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 () {
- var com = new ccs.ComController();
- if (com && com.init()) {
- return com;
- }
- return null;
+ return new ccs.ComController();
};
\ No newline at end of file
diff --git a/extensions/cocostudio/components/CCComRender.js b/extensions/cocostudio/components/CCComRender.js
index 5626d03ba8..960e096a11 100644
--- a/extensions/cocostudio/components/CCComRender.js
+++ b/extensions/cocostudio/components/CCComRender.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,24 +24,36 @@
****************************************************************************/
/**
- * Base class for ccs.ComRender
+ * 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) {
+ 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);
@@ -49,7 +62,7 @@ ccs.ComRender = ccs.Component.extend(/** @lends ccs.ComRender# */{
},
/**
- * Node getter
+ * Returns a render node
* @returns {cc.Node}
*/
getNode: function () {
@@ -57,25 +70,22 @@ ccs.ComRender = ccs.Component.extend(/** @lends ccs.ComRender# */{
},
/**
- * Node setter
+ * Sets a render node to component.
* @param {cc.Node} node
*/
setNode: function (node) {
this._render = node;
}
});
+
/**
* allocates and initializes a ComRender.
- * @constructs
+ * @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) {
- var com = new ccs.ComRender(node, comName);
- if (com && com.init()) {
- return com;
- }
- return null;
+ return new ccs.ComRender(node, comName);
};
diff --git a/extensions/cocostudio/components/CCComponent.js b/extensions/cocostudio/components/CCComponent.js
index e444b2da0e..5084a9744a 100644
--- a/extensions/cocostudio/components/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
@@ -32,57 +33,103 @@ cc.Component = cc.Class.extend(/** @lends cc.Component# */{
_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/extensions/cocostudio/components/CCComponentContainer.js b/extensions/cocostudio/components/CCComponentContainer.js
index 470561f3ed..c82103e7ee 100644
--- a/extensions/cocostudio/components/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
@@ -23,7 +24,7 @@
****************************************************************************/
/**
- * The container of cc.Component
+ * The component container for Cocostudio, it has some components.
* @class
* @extends cc.Class
*/
@@ -31,18 +32,35 @@ 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){
if(!name)
throw "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){
if(!component)
throw "cc.ComponentContainer.add(): component should be non-null";
@@ -67,8 +85,8 @@ cc.ComponentContainer = cc.Class.extend(/** @lends cc.ComponentContainer# */{
},
/**
- *
- * @param {String|cc.Component} name
+ * Removes component from container by name or component object.
+ * @param {String|cc.Component} name component name or component object.
* @returns {boolean}
*/
remove:function(name){
@@ -76,16 +94,16 @@ cc.ComponentContainer = cc.Class.extend(/** @lends cc.ComponentContainer# */{
throw "cc.ComponentContainer.remove(): name should be non-null";
if(!this._components)
return false;
- if(name instanceof cc.Component){
+ if(name instanceof cc.Component)
return this._removeByComponent(name);
- }else{
+ else {
name = name.trim();
return this._removeByComponent(this._components[name]);
}
},
_removeByComponent:function(component){
- if(component)
+ if(!component)
return false;
component.onExit();
component.setOwner(null);
@@ -93,10 +111,12 @@ cc.ComponentContainer = cc.Class.extend(/** @lends cc.ComponentContainer# */{
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];
@@ -112,24 +132,27 @@ cc.ComponentContainer = cc.Class.extend(/** @lends cc.ComponentContainer# */{
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..751ee53918
--- /dev/null
+++ b/extensions/cocostudio/loader/load.js
@@ -0,0 +1,223 @@
+/****************************************************************************
+ 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){
+ var 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;
+};
+
+//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);
+ }
+};
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..6bcebf2734
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/action-1.x.js
@@ -0,0 +1,238 @@
+/****************************************************************************
+ 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 cache = {};
+
+ var Parser = baseParser.extend({
+
+ getNodeJson: function(json){
+ return json["action"];
+ },
+
+ parseNode: function(json, resourcePath, file){
+ if(!json)
+ return null;
+ if(cache[file])
+ return cache[file].clone();
+
+ 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)
+ );
+ }
+ });
+
+ cache[file] = action;
+ cache[file].retain();
+ return action.clone();
+ }
+
+ });
+
+ 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", "*", 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..3329106e25
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/action-2.x.js
@@ -0,0 +1,285 @@
+/****************************************************************************
+ 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 cache = {};
+
+ var Parser = baseParser.extend({
+
+ getNodeJson: function(json){
+ return json["Content"]["Content"]["Animation"];
+ },
+
+ parseNode: function(json, resourcePath, file){
+ if(!json)
+ return null;
+ if(cache[file])
+ return cache[file].clone();
+
+ 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);
+ });
+
+ cache[file] = action;
+ cache[file].retain();
+ return action.clone();
+ },
+
+ 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"];
+ 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: "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"] || 255;
+ color["G"] = color["G"] || 255;
+ color["B"] = color["B"] || 255;
+ 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 = new ccs.TextureFrame();
+ var texture = options["TextureFile"];
+ if(texture != null) {
+ var path = texture["Path"];
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ 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;
+ }
+ }
+ ];
+
+ var loadEasingDataWithFlatBuffers = function(frame, options){
+ var type = options["Type"];
+ frame.setTweenType(type);
+ var points = options["Points"];
+ if(points){
+ points = points.map(function(p){
+ return cc.p(p["X"], p["Y"]);
+ });
+ frame.setEasingParams(points);
+ }
+ };
+
+ 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);
+
+})(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..caa681d4fc
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/compatible.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.
+ ****************************************************************************/
+
+
+/*
+ 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();
+ }
+ };
+})();
\ No newline at end of file
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..04569cb17f
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/scene-1.x.js
@@ -0,0 +1,262 @@
+/****************************************************************************
+ 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..c9c3efbab5
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/timelineParser-1.x.js
@@ -0,0 +1,292 @@
+/****************************************************************************
+ 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", "*", 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..e5644ccada
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/timelineParser-2.x.js
@@ -0,0 +1,1321 @@
+/****************************************************************************
+ 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){
+ return json["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);
+
+ setContentSize(node, json["Size"]);
+
+ if (json["Alpha"] != null)
+ node.setOpacity(json["Alpha"]);
+
+ node.setTag(json["Tag"] || 0);
+
+ var actionTag = json["ActionTag"] || 0;
+ var extensionData = new ccs.ObjectExtensionData();
+ var customProperty = json["UserData"];
+ if(customProperty !== undefined)
+ extensionData.setCustomProperty(customProperty);
+ extensionData.setActionTag(actionTag);
+ node.setUserObject(extensionData);
+
+ node.setCascadeColorEnabled(true);
+ node.setCascadeOpacityEnabled(true);
+ };
+
+ 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);
+
+ 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);
+ 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.ObjectExtensionData();
+ var customProperty = json["UserData"];
+ if(customProperty !== undefined)
+ extensionData.setCustomProperty(customProperty);
+ extensionData.setActionTag(actionTag);
+ widget.setUserObject(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));
+
+ var layoutComponent = ccui.LayoutComponent.bindLayoutComponent(widget);
+ if(!layoutComponent)
+ return;
+
+ var positionXPercentEnabled = json["PositionPercentXEnable"] || false;
+ var positionYPercentEnabled = json["PositionPercentYEnable"] || false;
+ var positionXPercent = 0,
+ positionYPercent = 0,
+ PrePosition = json["PrePosition"];
+ if (PrePosition != null) {
+ positionXPercent = PrePosition["X"] || 0;
+ positionYPercent = PrePosition["Y"] || 0;
+ }
+ var sizeXPercentEnable = json["PercentWidthEnable"] || false;
+ var sizeYPercentEnable = json["PercentHeightEnable"] || 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.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"];
+ 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(/([^\/]+)\.ttf/);
+ 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);
+
+ this.widgetAttributes(widget, json, widget.isIgnoreContentAdaptWithSize());
+
+ 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(/([^\/]+)\.ttf/);
+ 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"];
+ 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);
+
+ return widget;
+ };
+
+ /**
+ * TextBMFont
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.TextBMFont}
+ */
+ parser.initTextBMFont = function(json, resourcePath){
+
+ var widget = new ccui.TextBMFont();
+ this.widgetAttributes(widget, json);
+
+ var text = json["LabelText"];
+ widget.setString(text);
+
+ 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);
+ });
+ 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(/([^\/]+)\.ttf/);
+ 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 loop = json["Loop"] || false;
+ var volume = json["Volume"] || 0;
+ cc.audioEngine.setMusicVolume(volume);
+ //var name = json["Name"];
+ var resPath = "";
+ if(cc.loader.resPath)
+ resPath = (cc.loader.resPath + "/").replace(/\/\/$/, "/");
+
+ loadTexture(json["FileData"], resourcePath, function(path, type){
+ cc.loader.load(path, function(){
+ cc.audioEngine.playMusic(resPath + path, loop);
+ });
+ });
+
+ };
+
+ /**
+ * 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"];
+
+ parser.generalAttributes(node, json);
+
+ 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);
+
+ });
+ 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.log("%s need to be preloaded", resourcePath + plist);
+ }
+ }
+ if(type !== 0)
+ cb(path, type);
+ 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: "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}
+ ];
+
+ 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);
+
+
+})(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..c14763e875
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/uiParser-1.x.js
@@ -0,0 +1,698 @@
+/****************************************************************************
+ 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({
+
+ 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);
+ },
+
+ deferred: function(json, resourcePath, node, file){
+ if(node){
+ ccs.actionManager.initWithDictionary(file, json["animation"], node);
+ node.setContentSize(cc.size(json["designWidth"], json["designHeight"]));
+ }
+ }
+
+ });
+ var parser = new Parser();
+
+
+ parser.generalAttributes = function(widget, options){
+ var ignoreSizeExsit = options["ignoreSize"];
+ if(ignoreSizeExsit != null)
+ widget.ignoreContentAdaptWithSize(ignoreSizeExsit);
+
+ if (options["sizeType"])
+ {
+ widget.setSizeType(options["sizeType"]);
+ }
+
+ if (options["positionType"])
+ {
+ widget.setPositionType(options["positionType"]);
+ }
+
+ widget.setSizePercent(cc.p(options["sizePercentX"], options["sizePercentY"]));
+ widget.setPositionPercent(cc.p(options["positionPercentX"], options["positionPercentY"]));
+
+ /* 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"];
+ h = options["height"];
+ }
+ widget.setContentSize(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(x, y);
+
+ var sx = options["scaleX"]!=null ? options["scaleX"] : 1;
+ widget.setScaleX(sx);
+
+ var sy = options["scaleY"]!=null ? options["scaleY"] : 1;
+ widget.setScaleY(sy);
+
+ var rt = options["rotation"] || 0;
+ widget.setRotation(rt);
+
+ var vb = options["visible"] || false;
+ if(vb != null)
+ widget.setVisible(vb);
+ widget.setLocalZOrder(options["ZOrder"]);
+
+ var layout = options["layoutParameter"];
+ if(layout != null){
+ var layoutParameterDic = options["layoutParameter"];
+ var paramType = layoutParameterDic["type"];
+ var parameter = null;
+
+ switch(paramType){
+ case 0:
+ break;
+ case 1:
+ parameter = new ccui.LinearLayoutParameter();
+ var gravity = layoutParameterDic["gravity"];
+ parameter.setGravity(gravity);
+ break;
+ case 2:
+ parameter = new ccui.RelativeLayoutParameter();
+ var rParameter = parameter;
+ var relativeName = layoutParameterDic["relativeName"];
+ rParameter.setRelativeName(relativeName);
+ var relativeToName = layoutParameterDic["relativeToName"];
+ rParameter.setRelativeToWidgetName(relativeToName);
+ var align = layoutParameterDic["align"];
+ rParameter.setAlign(align);
+ break;
+ default:
+ break;
+ }
+ if(parameter != null){
+ var mgl = layoutParameterDic["marginLeft"]||0;
+ var mgt = layoutParameterDic["marginTop"]||0;
+ var mgr = layoutParameterDic["marginRight"]||0;
+ var mgb = layoutParameterDic["marginDown"]||0;
+ parameter.setMargin(mgl, mgt, mgr, mgb);
+ widget.setLayoutParameter(parameter);
+ }
+ }
+ };
+
+ parser.colorAttributes = function(widget, options){
+ var op = options["opacity"];
+ 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"]);
+ };
+
+ parser.anchorPointAttributes = function(widget, options){
+ var isAnchorPointXExists = options["anchorPointX"];
+ var anchorPointXInFile;
+ if (isAnchorPointXExists != null)
+ anchorPointXInFile = options["anchorPointX"];
+ else
+ anchorPointXInFile = widget.getAnchorPoint().x;
+
+ var isAnchorPointYExists = options["anchorPointY"];
+ var anchorPointYInFile;
+ if (isAnchorPointYExists != null)
+ anchorPointYInFile = options["anchorPointY"];
+ else
+ anchorPointYInFile = widget.getAnchorPoint().y;
+
+ if (isAnchorPointXExists != null || isAnchorPointYExists != null)
+ widget.setAnchorPoint(cc.p(anchorPointXInFile, anchorPointYInFile));
+ };
+
+ parser.parseChild = function(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)
+ widget.addPage(child);
+ else {
+ if(widget instanceof ccui.ListView){
+ widget.pushBackCustomItem(child);
+ } else {
+ if(!(widget instanceof ccui.Layout)) {
+ 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));
+ }
+ var AnchorPointIn = widget.getAnchorPointInPoints();
+ child.setPosition(cc.p(child.getPositionX() + AnchorPointIn.x, child.getPositionY() + AnchorPointIn.y));
+ }
+ widget.addChild(child);
+ }
+ }
+ }
+ }
+ };
+
+ 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"];
+ h = options["height"];
+ }
+ widget.setSize(cc.size(w, h));
+
+ widget.setClippingEnabled(options["clipAble"]);
+
+ var backGroundScale9Enable = options["backGroundScale9Enable"];
+ widget.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"];
+ widget.setBackGroundColorVector(cc.p(bgcv1, bgcv2));
+
+ var co = options["bgColorOpacity"];
+
+ var colorType = options["colorType"];
+ 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"], imageFileNameDic["path"], function(path, type){
+ widget.setBackGroundImage(path, type);
+ });
+ }
+
+ if (backGroundScale9Enable){
+ var cx = options["capInsetsX"];
+ var cy = options["capInsetsY"];
+ var cw = options["capInsetsWidth"];
+ var ch = 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"], normalDic["path"], function(path, type){
+ button.loadTextureNormal(path, type);
+ });
+ var pressedDic = options["pressedData"];
+ getPath(resourcePath, pressedDic["resourceType"], pressedDic["path"], function(path, type){
+ button.loadTexturePressed(path, type);
+ });
+ var disabledDic = options["disabledData"];
+ getPath(resourcePath, disabledDic["resourceType"], disabledDic["path"], function(path, type){
+ button.loadTextureDisabled(path, type);
+ });
+ 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 != null && sh != null)
+ button.setSize(cc.size(sw, sh));
+ }
+ var text = options["text"];
+ if (text != null)
+ 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"], 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"], 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"], 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"], 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"];
+ var sh = options["scale9Height"];
+ if (sw && sh)
+ {
+ var swf = options["scale9Width"];
+ var shf = options["scale9Height"];
+ widget.setSize(cc.size(swf, shf));
+ }
+
+ var cx = options["capInsetsX"];
+ var cy = options["capInsetsY"];
+ var cw = options["capInsetsWidth"];
+ var ch = 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"];
+ 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"];
+ 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"];
+ 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"];
+ var ah = options["areaHeight"];
+ if (aw != null && ah != null){
+ var size = cc.size(options["areaWidth"], options["areaHeight"]);
+ widget.setTextAreaSize(size);
+ }
+ var ha = options["hAlignment"];
+ if (ha != null){
+ widget.setTextHorizontalAlignment(options["hAlignment"]);
+ }
+ var va = options["vAlignment"];
+ if (va != null){
+ widget.setTextVerticalAlignment(options["vAlignment"]);
+ }
+ };
+ /**
+ * ListView parser (UIListView)
+ */
+ parser.ListViewAttributes = function(widget, options, resoutcePath){
+ parser.ScrollViewAttributes(widget, options,resoutcePath);
+ var direction = options["direction"];
+ widget.setDirection(direction);
+ var gravity = options["gravity"];
+ widget.setGravity(gravity);
+ var itemMargin = options["itemMargin"];
+ widget.setItemsMargin(itemMargin);
+ };
+ /**
+ * LoadingBar parser (UILoadingBar)
+ */
+ parser.LoadingBarAttributes = function(widget, options, resourcePath){
+ var imageFileNameDic = options["textureData"];
+ getPath(resourcePath, imageFileNameDic["resourceType"], imageFileNameDic["path"], function(path, type){
+ widget.loadTexture(path, type);
+ });
+
+ var scale9Enable = options["scale9Enable"];
+ widget.setScale9Enabled(scale9Enable);
+
+ if (scale9Enable){
+ var cx = options["capInsetsX"];
+ var cy = options["capInsetsY"];
+ var cw = options["capInsetsWidth"];
+ var ch = options["capInsetsHeight"];
+
+ widget.setCapInsets(cc.rect(cx, cy, cw, ch));
+
+ var width = options["width"];
+ var height = options["height"];
+ widget.setSize(cc.size(width, height));
+ }
+
+ widget.setDirection(options["direction"]);
+ widget.setPercent(options["percent"]);
+ };
+ /**
+ * 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"];
+ 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"], 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"], disabledDic["path"], function(path, type){
+ slider.loadSlidBallTextureDisabled(path, type);
+ });
+
+ var progressBarDic = options["progressBarData"];
+ getPath(resourcePath, progressBarDic["resourceType"], 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["fontSize1"];
+ 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"];
+ var tsh = options["touchSizeHeight"];
+ if(tsw!=null && tsh!=null)
+ widget.setTouchSize(tsw, tsh);
+
+ var dw = options["width"];
+ var dh = options["height"];
+ 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"];
+ var ah = options["areaHeight"];
+ if(aw && ah){
+ var size = cc.size(aw, ah);
+ widget.setTextAreaSize(size);
+ }
+ var ha = options["hAlignment"];
+ if(ha)
+ widget.setTextHorizontalAlignment(ha);
+ var va = options["vAlignment"];
+ if(va)
+ widget.setTextVerticalAlignment(va);
+ };
+
+ var register = [
+ {name: "Panel", object: ccui.Layout, handle: parser.LayoutAttributes},
+ {name: "Button", object: ccui.Button, handle: parser.ButtonAttributes},
+ {name: "CheckBox", object: ccui.CheckBox, handle: parser.CheckBoxAttributes},
+ {name: "ImageView", object: ccui.ImageView, handle: parser.ImageViewAttributes},
+ {name: "LabelAtlas", object: ccui.TextAtlas, handle: parser.TextAtlasAttributes},
+ {name: "LabelBMFont", object: ccui.TextBMFont, handle: parser.TextBMFontAttributes},
+ {name: "Label", object: ccui.Text, handle: parser.TextAttributes},
+ {name: "ListView", object: ccui.ListView, handle: parser.ListViewAttributes},
+ {name: "LoadingBar", object: ccui.LoadingBar, handle: parser.LoadingBarAttributes},
+ {name: "PageView", object: ccui.PageView, handle: parser.PageViewAttributes},
+ {name: "ScrollView", object: ccui.ScrollView, handle: parser.ScrollViewAttributes},
+ {name: "Slider", object: ccui.Slider, handle: parser.SliderAttributes},
+ {name: "TextField", object: ccui.TextField, handle: parser.TextFieldAttributes}
+ ];
+
+ register.forEach(function(item){
+ parser.registerParser(item.name, function(options, resourcePath){
+ var widget = new item.object;
+ var uiOptions = options["options"];
+ parser.generalAttributes(widget, uiOptions);
+ item.handle(widget, uiOptions, resourcePath);
+ parser.colorAttributes(widget, uiOptions);
+ parser.anchorPointAttributes(widget, uiOptions);
+ parser.parseChild.call(this, widget, options, resourcePath);
+ return widget;
+ });
+ });
+
+ load.registerParser("ccui", "*", parser);
+
+})(ccs._load, ccs._parser);
\ No newline at end of file
diff --git a/extensions/cocostudio/reader/GUIReader.js b/extensions/cocostudio/reader/GUIReader.js
deleted file mode 100644
index 37e4847d48..0000000000
--- a/extensions/cocostudio/reader/GUIReader.js
+++ /dev/null
@@ -1,1594 +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.
- ****************************************************************************/
-/**
- * @namespace Base object for ccs.uiReader
- */
-ccs.uiReader = /** @lends ccs.uiReader# */{
- _filePath: "",
- _olderVersion: false,
- _fileDesignSizes: {},
-
- /**
- * get version
- * @param {String} str
- * @returns {Number}
- */
- getVersionInteger: function (str) {
- if(!str)
- return 0;
- var strVersion = str;
- var versionLength = strVersion.length;
- if (versionLength < 7) {
- return 0;
- }
- var pos = strVersion.indexOf(".");
- var t = strVersion.substr(0, pos);
- strVersion = strVersion.substr(pos + 1, versionLength - 1);
-
- pos = strVersion.indexOf(".");
- var h = strVersion.substr(0, pos);
- strVersion = strVersion.substr(pos + 1, versionLength - 1);
-
- pos = strVersion.indexOf(".");
- var te = strVersion.substr(0, pos);
- strVersion = strVersion.substr(pos + 1, versionLength - 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;
- },
-
- /**
- * store file designSize
- * @param {String} fileName
- * @param {cc.Size} size
- */
- storeFileDesignSize: function (fileName, size) {
- this._fileDesignSizes[fileName] = size;
- },
-
- /**
- *
- * @param {String} fileName
- * @returns {cc.Size}
- */
- getFileDesignSize: function (fileName) {
- return this._fileDesignSizes[fileName];
- },
-
- /**
- * create uiWidget from a josn file that exported by cocostudio UI editor
- * @param {String} fileName
- * @returns {ccui.Widget}
- */
- widgetFromJsonFile: function (fileName) {
- var jsonDict = cc.loader.getRes(fileName);
- if(!jsonDict) throw "Please load the resource first : " + fileName;
-
- var tempFilePath = cc.path.dirname(fileName);
- this._filePath = tempFilePath == "" ? tempFilePath : tempFilePath + "/";
-
- var fileVersion = jsonDict["version"];
- var pReader, widget;
- var versionInteger = this.getVersionInteger(fileVersion);
- if (fileVersion) {
- if (versionInteger < 250) {
- pReader = new ccs.WidgetPropertiesReader0250();
- widget = pReader.createWidget(jsonDict, this._filePath, fileName);
- } else {
- pReader = new ccs.WidgetPropertiesReader0300();
- widget = pReader.createWidget(jsonDict, this._filePath, fileName);
- }
- } else {
- pReader = new ccs.WidgetPropertiesReader0250();
- widget = pReader.createWidget(jsonDict, this._filePath, fileName);
- }
-
- if (!fileVersion || versionInteger < 250) {
- this._olderVersion = true;
- }
- jsonDict = null;
- return widget;
- },
-
- /**
- * Clear data: Release all actions.
- */
- clear: function () {
- this._filePath = "";
- this._olderVersion = false;
- this._fileDesignSizes = {};
- }
-};
-
-
-ccs.WidgetPropertiesReader = ccs.Class.extend({
- _filePath: "",
- createWidget: function (jsonDict, fullPath, fileName) {
- },
- widgetFromJsonDictionary: function (data) {
- }
-});
-ccs.WidgetPropertiesReader0250 = ccs.WidgetPropertiesReader.extend({
- createWidget: function (jsonDict, fullPath, fileName) {
- this._filePath = fullPath == "" ? fullPath : cc.path.join(fullPath, "/");
- var textures = jsonDict["textures"];
- for (var i = 0; i < textures.length; i++) {
- var file = textures[i];
- var tp = fullPath;
- tp += file;
- cc.spriteFrameCache.addSpriteFrames(tp);
- }
- var fileDesignWidth = jsonDict["designWidth"];
- var fileDesignHeight = jsonDict["designHeight"];
- if (fileDesignWidth <= 0 || fileDesignHeight <= 0) {
- cc.log("Read design size error!");
- var winSize = cc.director.getWinSize();
- ccs.uiReader.storeFileDesignSize(fileName, winSize);
- }
- else {
- ccs.uiReader.storeFileDesignSize(fileName, cc.size(fileDesignWidth, 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;
- ccs.actionManager.initWithDictionary(fileName, actions, rootWidget);
-
- widgetTree = null;
- actions = null;
- return widget;
- },
- widgetFromJsonDictionary: function (data) {
- var widget = null;
- var classname = data["classname"];
- var uiOptions = data["options"];
- if (classname == "Button") {
- widget = ccui.Button.create();
- this.setPropsForButtonFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "CheckBox") {
- widget = ccui.CheckBox.create();
- this.setPropsForCheckBoxFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Label") {
- widget = ccui.Text.create();
- this.setPropsForLabelFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LabelAtlas") {
- widget = ccui.TextAtlas.create();
- this.setPropsForLabelAtlasFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LoadingBar") {
- widget = ccui.LoadingBar.create();
- this.setPropsForLoadingBarFromJsonDictionary(widget, uiOptions);
- } else if (classname == "ScrollView") {
- widget = ccui.ScrollView.create();
- this.setPropsForScrollViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextArea") {
- widget = ccui.Text.create();
- this.setPropsForLabelFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextButton") {
- widget = ccui.Button.create();
- this.setPropsForButtonFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextField") {
- widget = ccui.TextField.create();
- this.setPropsForTextFieldFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "ImageView") {
- widget = ccui.ImageView.create();
- this.setPropsForImageViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Panel") {
- widget = ccui.Layout.create();
- this.setPropsForLayoutFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Slider") {
- widget = ccui.Slider.create();
- this.setPropsForSliderFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LabelBMFont") {
- widget = ccui.TextBMFont.create();
- this.setPropsForLabelBMFontFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "DragPanel") {
- widget = ccui.ScrollView.create();
- this.setPropsForScrollViewFromJsonDictionary(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;
- },
-
-
- setPropsForWidgetFromJsonDictionary: function (widget, options) {
- if (options["ignoreSize"] !== undefined) {
- 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(x, y);
- if (options["scaleX"] !== undefined) {
- widget.setScaleX(options["scaleX"]);
- }
- if (options["scaleY"] !== undefined) {
- widget.setScaleY(options["scaleY"]);
- }
- if (options["rotation"] !== undefined) {
- widget.setRotation(options["rotation"]);
- }
- if (options["visible"] !== undefined) {
- widget.setVisible(options["visible"]);
- }
-
- var z = options["ZOrder"];
- widget.setLocalZOrder(z);
- },
-
- setColorPropsForWidgetFromJsonDictionary: function (widget, options) {
- if (options["opacity"] !== undefined) {
- widget.setOpacity(options["opacity"]);
- }
- var colorR = options["colorR"] !== undefined ? options["colorR"] : 255;
- var colorG = options["colorG"] !== undefined ? options["colorG"] : 255;
- var colorB = options["colorB"] !== undefined ? options["colorB"] : 255;
- widget.setColor(cc.color(colorR, colorG, colorB));
- var apx = options["anchorPointX"] !== undefined ? options["anchorPointX"] : ((widget.getWidgetType() == ccui.Widget.TYPE_WIDGET) ? 0.5 : 0);
- var apy = options["anchorPointY"] !== undefined ? options["anchorPointY"] : ((widget.getWidgetType() == ccui.Widget.TYPE_WIDGET) ? 0.5 : 0);
- widget.setAnchorPoint(apx, apy);
- var flipX = options["flipX"];
- var flipY = options["flipY"];
- widget.setFlippedX(flipX);
- widget.setFlippedY(flipY);
- },
-
- setPropsForButtonFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var button = widget;
- var scale9Enable = options["scale9Enable"];
- button.setScale9Enabled(scale9Enable);
-
- var normalFileName = options["normal"];
- var pressedFileName = options["pressed"];
- var disabledFileName = options["disabled"];
-
- var normalFileName_tp = normalFileName ? this._filePath + normalFileName : null;
- var pressedFileName_tp = pressedFileName ? this._filePath + pressedFileName : null;
- var disabledFileName_tp = disabledFileName ? this._filePath + 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, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- button.loadTextures(normalFileName_tp, pressedFileName_tp, disabledFileName_tp);
- }
- //button.setCapInsets(cc.rect(cx, cy, cw, ch));
- if (options["scale9Width"] !== undefined && options["scale9Height"] !== undefined) {
- var swf = options["scale9Width"];
- var shf = options["scale9Height"];
- button.setSize(cc.size(swf, shf));
- }
- }
- else {
- if (useMergedTexture) {
- button.loadTextures(normalFileName, pressedFileName, disabledFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- button.loadTextures(normalFileName_tp, pressedFileName_tp, disabledFileName_tp);
- }
- }
- if (options["text"] !== undefined) {
- var text = options["text"] || "";
- if (text)
- button.setTitleText(text);
- }
- if (options["fontSize"] !== undefined) {
- button.setTitleFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- button.setTitleFontName(options["fontName"]);
- }
- var cr = options["textColorR"] !== undefined ? options["textColorR"] : 255;
- var cg = options["textColorG"] !== undefined ? options["textColorG"] : 255;
- var cb = options["textColorB"] !== undefined ? options["textColorB"] : 255;
- var tc = cc.color(cr, cg, cb);
- button.setTitleColor(tc);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForCheckBoxFromJsonDictionary: function (widget, options) {
- 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 locFilePath = this._filePath;
-
- var backGroundFileName_tp = backGroundFileName ? locFilePath + backGroundFileName : null;
- var backGroundSelectedFileName_tp = backGroundSelectedFileName ? locFilePath + backGroundSelectedFileName : null;
- var frontCrossFileName_tp = frontCrossFileName ? locFilePath + frontCrossFileName : null;
- var backGroundDisabledFileName_tp = backGroundDisabledFileName ? locFilePath + backGroundDisabledFileName : null;
- var frontCrossDisabledFileName_tp = frontCrossDisabledFileName ? locFilePath + frontCrossDisabledFileName : null;
- var useMergedTexture = options["useMergedTexture"];
-
- if (useMergedTexture) {
- checkBox.loadTextures(backGroundFileName, backGroundSelectedFileName, frontCrossFileName, backGroundDisabledFileName, frontCrossDisabledFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- checkBox.loadTextures(backGroundFileName_tp, backGroundSelectedFileName_tp, frontCrossFileName_tp, backGroundDisabledFileName_tp, frontCrossDisabledFileName_tp);
- }
-
- checkBox.setSelectedState(options["selectedState"] || false);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForImageViewFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
-
- var imageView = widget;
- var imageFileName = options["fileName"];
- var scale9Enable = options["scale9Enable"] || false;
- 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, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- imageView.loadTexture(imageFileName_tp);
- }
-
- if (options["scale9Width"] !== undefined && options["scale9Height"] !== undefined) {
- 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, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- imageView.loadTexture(imageFileName_tp);
- }
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var label = widget;
- var touchScaleChangeAble = options["touchScaleEnable"];
- label.setTouchScaleChangeEnabled(touchScaleChangeAble);
- var text = options["text"];
- label.setText(text);
- if (options["fontSize"] !== undefined) {
- label.setFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- label.setFontName(options["fontName"]);
- }
- if (options["areaWidth"] !== undefined && options["areaHeight"] !== undefined) {
- var size = cc.size(options["areaWidth"], options["areaHeight"]);
- label.setTextAreaSize(size);
- }
- if (options["hAlignment"]) {
- label.setTextHorizontalAlignment(options["hAlignment"]);
- }
- if (options["vAlignment"]) {
- label.setTextVerticalAlignment(options["vAlignment"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelAtlasFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var labelAtlas = widget;
- var sv = (options["stringValue"] !== undefined);
- var cmf = (options["charMapFile"] !== undefined);
- var iw = (options["itemWidth"] !== undefined);
- var ih = (options["itemHeight"] !== undefined);
- var scm = (options["startCharMap"] !== undefined);
- if (sv && cmf && iw && ih && scm && options["charMapFile"]) {
- var cmft = options["charMapFile"];
- var cmf_tp = this._filePath + cmft;
-
- labelAtlas.setProperty(options["stringValue"], cmf_tp, options["itemWidth"], options["itemHeight"], options["startCharMap"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLayoutFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var containerWidget = widget;
- if (!(containerWidget instanceof ccui.ScrollView) && !(containerWidget instanceof ccui.ListView)) {
- containerWidget.setClippingEnabled(options["clipAble"]);
- }
- 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.color(scr, scg, scb), cc.color(ecr, ecg, ecb));
- panel.setBackGroundColor(cc.color(cr, cg, cb));
- panel.setBackGroundColorOpacity(co);
-
- var imageFileName = options["backGroundImage"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- var useMergedTexture = options["useMergedTexture"];
- if (useMergedTexture) {
- panel.setBackGroundImage(imageFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- panel.setBackGroundImage(imageFileName_tp);
- }
- 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.setPropsForLayoutFromJsonDictionary(widget, options);
- var scrollView = widget;
- var innerWidth = options["innerWidth"];
- var innerHeight = options["innerHeight"];
- scrollView.setInnerContainerSize(cc.size(innerWidth, innerHeight));
- var direction = options["direction"];
- scrollView.setDirection(direction);
- scrollView.setBounceEnabled(options["bounceEnable"]);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForContainerWidgetFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var containerWidget = widget;
- if (containerWidget instanceof ccui.ScrollView ||
- containerWidget instanceof ccui.ListView) {
- containerWidget.setClippingEnabled(options["clipAble"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForSliderFromJsonDictionary: function (widget, options) {
-
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var slider = widget;
-
- var barTextureScale9Enable = options["barTextureScale9Enable"] || false;
- slider.setScale9Enabled(barTextureScale9Enable);
- var barLength = options["length"];
- var useMergedTexture = options["useMergedTexture"];
- var bt = (options["barFileName"] !== undefined);
- if (bt) {
- if (barTextureScale9Enable) {
- var imageFileName = options["barFileName"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- if (useMergedTexture) {
- slider.loadBarTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- slider.loadBarTexture(imageFileName_tp);
- }
- slider.setSize(cc.size(barLength, slider.getContentSize().height));
- }
- else {
- var imageFileName = options["barFileName"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- if (useMergedTexture) {
- slider.loadBarTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- slider.loadBarTexture(imageFileName_tp);
- }
- }
- }
-
- var normalFileName = options["ballNormal"];
- var pressedFileName = options["ballPressed"];
- var disabledFileName = options["ballDisabled"];
-
- var normalFileName_tp = normalFileName ? this._filePath + normalFileName : null;
- var pressedFileName_tp = pressedFileName ? this._filePath + pressedFileName : null;
- var disabledFileName_tp = disabledFileName ? this._filePath + disabledFileName : null;
- if (useMergedTexture) {
- slider.loadSlidBallTextures(normalFileName, pressedFileName, disabledFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- slider.loadSlidBallTextures(normalFileName_tp, pressedFileName_tp, disabledFileName_tp);
- }
- slider.setPercent(options["percent"]);
-
- var imageFileName = options["progressBarFileName"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- if (useMergedTexture) {
- slider.loadProgressBarTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- slider.loadProgressBarTexture(imageFileName_tp);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextAreaFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var textArea = widget;
- textArea.setText(options["text"]);
- if (options["fontSize"] !== undefined) {
- textArea.setFontSize(options["fontSize"]);
- }
- var cr = options["colorR"]
- var cg = options["colorG"];
- var cb = options["colorB"];
- textArea.setColor(cc.color(cr, cg, cb));
- textArea.setFontName(options["fontName"]);
- if (options["areaWidth"] !== undefined && options["areaHeight"] !== undefined) {
- var size = cc.size(options["areaWidth"], options["areaHeight"]);
- textArea.setTextAreaSize(size);
- }
- if (options["hAlignment"]) {
- textArea.setTextHorizontalAlignment(options["hAlignment"]);
- }
- if (options["vAlignment"]) {
- textArea.setTextVerticalAlignment(options["vAlignment"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextButtonFromJsonDictionary: function (widget, options) {
- this.setPropsForButtonFromJsonDictionary(widget, options);
-
- var textButton = widget;
- textButton.setTitleText(options["text"] || "");
- var cri = options["textColorR"] !== undefined ? options["textColorR"] : 255;
- var cgi = options["textColorG"] !== undefined ? options["textColorG"] : 255;
- var cbi = options["textColorB"] !== undefined ? options["textColorB"] : 255;
- textButton.setTitleColor(cc.color(cri, cgi, cbi));
- if (options["fontSize"] !== undefined) {
- textButton.setTitleFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- textButton.setTitleFontName(options["fontName"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextFieldFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var textField = widget;
- if (options["placeHolder"] !== undefined) {
- textField.setPlaceHolder(options["placeHolder"]);
- }
- textField.setText(options["text"]);
- if (options["fontSize"] !== undefined) {
- textField.setFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- textField.setFontName(options["fontName"]);
- }
- if (options["touchSizeWidth"] !== undefined && options["touchSizeHeight"] !== undefined) {
- 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.setMaxLengthEnabled(maxLengthEnable);
-
- if (maxLengthEnable) {
- var maxLength = options["maxLength"];
- textField.setMaxLength(maxLength);
- }
- var passwordEnable = options["passwordEnable"];
- textField.setPasswordEnabled(passwordEnable);
- if (passwordEnable) {
- textField.setPasswordStyleText(options["passwordStyleText"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLoadingBarFromJsonDictionary: function (widget, options) {
-
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var loadingBar = widget;
- var useMergedTexture = options["useMergedTexture"];
- var imageFileName = options["texture"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- if (useMergedTexture) {
- loadingBar.loadTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- }
- else {
- loadingBar.loadTexture(imageFileName_tp);
- }
- loadingBar.setDirection(options["direction"]);
- loadingBar.setPercent(options["percent"]);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForListViewFromJsonDictionary: function (widget, options) {
- this.setPropsForLayoutFromJsonDictionary(widget, options);
- },
-
- setPropsForPageViewFromJsonDictionary: function (widget, options) {
- this.setPropsForLayoutFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelBMFontFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var labelBMFont = widget;
- var cmft = options["fileName"];
- var cmf_tp = this._filePath + cmft;
- labelBMFont.setFntFile(cmf_tp);
- var text = options["text"];
- labelBMFont.setText(text);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
-});
-
-ccs.WidgetPropertiesReader0300 = ccs.WidgetPropertiesReader.extend({
- createWidget: function (jsonDict, fullPath, fileName) {
- this._filePath = fullPath == "" ? fullPath : cc.path.join(fullPath, "/");
- var textures = jsonDict["textures"];
- for (var i = 0; i < textures.length; i++) {
- var file = textures[i];
- var tp = fullPath;
- tp += file;
- cc.spriteFrameCache.addSpriteFrames(tp);
- }
- var fileDesignWidth = jsonDict["designWidth"];
- var fileDesignHeight = jsonDict["designHeight"];
- if (fileDesignWidth <= 0 || fileDesignHeight <= 0) {
- cc.log("Read design size error!");
- var winSize = cc.director.getWinSize();
- ccs.uiReader.storeFileDesignSize(fileName, winSize);
- }
- else {
- ccs.uiReader.storeFileDesignSize(fileName, cc.size(fileDesignWidth, 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;
- ccs.actionManager.initWithDictionary(fileName, actions, rootWidget);
-
- widgetTree = null;
- actions = null;
- return widget;
- },
- widgetFromJsonDictionary: function (data) {
- var widget = null;
- var classname = data["classname"];
- var uiOptions = data["options"];
- if (classname == "Button") {
- widget = ccui.Button.create();
- this.setPropsForButtonFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "CheckBox") {
- widget = ccui.CheckBox.create();
- this.setPropsForCheckBoxFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Label") {
- widget = ccui.Text.create();
- this.setPropsForLabelFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LabelAtlas") {
- widget = ccui.TextAtlas.create();
- this.setPropsForLabelAtlasFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LoadingBar") {
- widget = ccui.LoadingBar.create();
- this.setPropsForLoadingBarFromJsonDictionary(widget, uiOptions);
- } else if (classname == "ScrollView") {
- widget = ccui.ScrollView.create();
- this.setPropsForScrollViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextArea") {
- widget = ccui.Text.create();
- this.setPropsForLabelFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextButton") {
- widget = ccui.Button.create();
- this.setPropsForButtonFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextField") {
- widget = ccui.TextField.create();
- this.setPropsForTextFieldFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "ImageView") {
- widget = ccui.ImageView.create();
- this.setPropsForImageViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Panel") {
- widget = ccui.Layout.create();
- this.setPropsForLayoutFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Slider") {
- widget = ccui.Slider.create();
- this.setPropsForSliderFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LabelBMFont") {
- widget = ccui.TextBMFont.create();
- this.setPropsForLabelBMFontFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "DragPanel") {
- widget = ccui.ScrollView.create();
- this.setPropsForScrollViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "ListView") {
- widget = ccui.ListView.create();
- this.setPropsForListViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "PageView") {
- widget = ccui.PageView.create();
- this.setPropsForPageViewFromJsonDictionary(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) {
- if (widget instanceof ccui.PageView && child instanceof ccui.Layout) {
- widget.addPage(child);
- } else if (widget instanceof ccui.ListView) {
- widget.pushBackCustomItem(child);
- } else {
- widget.addChild(child);
- }
- }
- subData = null;
- }
-
- uiOptions = null;
- return widget;
- },
-
-
- setPropsForWidgetFromJsonDictionary: function (widget, options) {
- var name = options["name"];
- var widgetName = name ? name : "default";
- widget.setName(widgetName);
-
- if (options["ignoreSize"] !== undefined) {
- widget.ignoreContentAdaptWithSize(options["ignoreSize"]);
- }
- widget.setSizeType(options["sizeType"]);
- widget.setPositionType(options["positionType"]);
-
- widget.setSizePercent(cc.p(options["sizePercentX"], options["sizePercentY"]));
- widget.setPositionPercent(cc.p(options["positionPercentX"], options["positionPercentY"]));
-
- 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 x = options["x"];
- var y = options["y"];
- widget.setPosition(x, y);
- if (options["scaleX"] !== undefined) {
- widget.setScaleX(options["scaleX"]);
- }
- if (options["scaleY"] !== undefined) {
- widget.setScaleY(options["scaleY"]);
- }
- if (options["rotation"] !== undefined) {
- widget.setRotation(options["rotation"]);
- }
- if (options["visible"] !== undefined) {
- widget.setVisible(options["visible"]);
- }
-
- widget.setLocalZOrder(options["ZOrder"]);
- var layoutParameterDic = options["layoutParameter"];
- if (layoutParameterDic) {
- var paramType = layoutParameterDic["type"];
- var parameter;
- switch (paramType) {
- case 0:
- break;
- case 1:
- parameter = ccui.LinearLayoutParameter.create();
- var gravity = layoutParameterDic["gravity"];
- parameter.setGravity(gravity);
- break;
- case 2:
- parameter = ccui.RelativeLayoutParameter.create();
- var relativeName = layoutParameterDic["relativeName"];
- parameter.setRelativeName(relativeName);
- var relativeToName = layoutParameterDic["relativeToName"];
- parameter.setRelativeToWidgetName(relativeToName);
- parameter.setAlign(layoutParameterDic["align"]);
- break;
- default:
- break;
- }
- var mgl = layoutParameterDic["marginLeft"];
- var mgt = layoutParameterDic["marginTop"];
- var mgr = layoutParameterDic["marginRight"];
- var mgb = layoutParameterDic["marginDown"];
- parameter.setMargin(new ccui.Margin(mgl, mgt, mgr, mgb));
- widget.setLayoutParameter(parameter);
- }
- },
-
- setColorPropsForWidgetFromJsonDictionary: function (widget, options) {
- if (options["opacity"] !== undefined) {
- widget.setOpacity(options["opacity"]);
- }
- var colorR = options["colorR"] !== undefined ? options["colorR"] : 255;
- var colorG = options["colorG"] !== undefined ? options["colorG"] : 255;
- var colorB = options["colorB"] !== undefined ? options["colorB"] : 255;
- widget.setColor(cc.color(colorR, colorG, colorB));
- var apx = options["anchorPointX"] !== undefined ? options["anchorPointX"] : ((widget.getWidgetType() == ccui.Widget.TYPE_WIDGET) ? 0.5 : 0);
- var apy = options["anchorPointY"] !== undefined ? options["anchorPointY"] : ((widget.getWidgetType() == ccui.Widget.TYPE_WIDGET) ? 0.5 : 0);
- widget.setAnchorPoint(apx, apy);
- var flipX = options["flipX"];
- var flipY = options["flipY"];
- widget.setFlippedX(flipX);
- widget.setFlippedY(flipY);
- },
-
- setPropsForButtonFromJsonDictionary: function (widget, options) {
-
-
- 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 normalFileName = normalDic["path"];
- var normalFileName_tp = normalFileName ? this._filePath + normalFileName : null;
- button.loadTextureNormal(normalFileName_tp);
- break;
- case 1:
- var normalFileName = normalDic["path"];
- button.loadTextureNormal(normalFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- normalDic = null;
- var pressedDic = options["pressedData"];
- var pressedType = pressedDic["resourceType"];
- switch (pressedType) {
- case 0:
- var pressedFileName = pressedDic["path"];
- var pressedFileName_tp = pressedFileName ? this._filePath + pressedFileName : null;
- button.loadTexturePressed(pressedFileName_tp);
- break;
- case 1:
- var pressedFileName = pressedDic["path"];
- button.loadTexturePressed(pressedFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- pressedDic = null;
- var disabledDic = options["disabledData"];
- var disabledType = disabledDic["resourceType"];
- switch (disabledType) {
- case 0:
- var disabledFileName = disabledDic["path"];
- var disabledFileName_tp = disabledFileName ? this._filePath + disabledFileName : null;
- button.loadTextureDisabled(disabledFileName_tp);
- break;
- case 1:
- var disabledFileName = disabledDic["path"];
- button.loadTextureDisabled(disabledFileName, ccui.Widget.PLIST_TEXTURE);
- 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));
- if (options["scale9Width"] !== undefined && options["scale9Height"] !== undefined) {
- var swf = options["scale9Width"];
- var shf = options["scale9Height"];
- button.setSize(cc.size(swf, shf));
- }
- }
- if (options["text"] !== undefined) {
- var text = options["text"] || "";
- if (text)
- button.setTitleText(text);
- }
- if (options["fontSize"] !== undefined) {
- button.setTitleFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- button.setTitleFontName(options["fontName"]);
- }
- var cr = options["textColorR"] !== undefined ? options["textColorR"] : 255;
- var cg = options["textColorG"] !== undefined ? options["textColorG"] : 255;
- var cb = options["textColorB"] !== undefined ? options["textColorB"] : 255;
- var tc = cc.color(cr, cg, cb);
- button.setTitleColor(tc);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForCheckBoxFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var checkBox = widget;
- var backGroundDic = options["backGroundBoxData"];
- var backGroundType = backGroundDic["resourceType"];
- switch (backGroundType) {
- case 0:
- var backGroundFileName = backGroundDic["path"];
- var backGroundFileName_tp = backGroundFileName ? this._filePath + backGroundFileName : null;
- checkBox.loadTextureBackGround(backGroundFileName_tp);
- break;
- case 1:
- var backGroundFileName = backGroundDic["path"];
- checkBox.loadTextureBackGround(backGroundFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- backGroundDic = null;
- var backGroundSelectedDic = options["backGroundBoxSelectedData"];
- var backGroundSelectedType = backGroundSelectedDic["resourceType"];
- switch (backGroundSelectedType) {
- case 0:
- var backGroundSelectedFileName = backGroundSelectedDic["path"];
- var backGroundSelectedFileName_tp = backGroundSelectedFileName ? this._filePath + backGroundSelectedFileName : null;
- checkBox.loadTextureBackGroundSelected(backGroundSelectedFileName_tp);
- break;
- case 1:
- var backGroundSelectedFileName = backGroundSelectedDic["path"];
- checkBox.loadTextureBackGroundSelected(backGroundSelectedFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- backGroundSelectedDic = null;
-
- var frontCrossDic = options["frontCrossData"];
- var frontCrossType = frontCrossDic["resourceType"];
- switch (frontCrossType) {
- case 0:
- var frontCrossFileName = frontCrossDic["path"];
- var frontCrossFileName_tp = frontCrossFileName ? this._filePath + frontCrossFileName : null;
- checkBox.loadTextureFrontCross(frontCrossFileName_tp);
- break;
- case 1:
- var frontCrossFileName = frontCrossDic["path"];
- checkBox.loadTextureFrontCross(frontCrossFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- frontCrossDic = null;
-
- var backGroundDisabledDic = options["backGroundBoxDisabledData"];
- var backGroundDisabledType = backGroundDisabledDic["resourceType"];
- switch (backGroundDisabledType) {
- case 0:
- var backGroundDisabledFileName = backGroundDisabledDic["path"];
- var backGroundDisabledFileName_tp = backGroundDisabledFileName ? this._filePath + backGroundDisabledFileName : null;
- checkBox.loadTextureBackGroundDisabled(backGroundDisabledFileName_tp);
- break;
- case 1:
- var backGroundDisabledFileName = backGroundDisabledDic["path"];
- checkBox.loadTextureBackGroundDisabled(backGroundDisabledFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- backGroundDisabledDic = null;
-
- var frontCrossDisabledDic = options["frontCrossDisabledData"];
- var frontCrossDisabledType = frontCrossDisabledDic["resourceType"];
- switch (frontCrossDisabledType) {
- case 0:
- var frontCrossDisabledFileName = options["path"];
- var frontCrossDisabledFileName_tp = frontCrossDisabledFileName ? this._filePath + frontCrossDisabledFileName : null;
- checkBox.loadTextureFrontCrossDisabled(frontCrossDisabledFileName_tp);
- break;
- case 1:
- var frontCrossDisabledFileName = options["path"];
- checkBox.loadTextureFrontCrossDisabled(frontCrossDisabledFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- frontCrossDisabledDic = null;
-
- var selectedState = options["selectedState"] || false;
- widget.setSelectedState(selectedState);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForImageViewFromJsonDictionary: function (widget, options) {
- 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, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
-
- var scale9Enable = options["scale9Enable"] || false;
- imageView.setScale9Enabled(scale9Enable);
-
- if (scale9Enable) {
- if (options["scale9Width"] !== undefined && options["scale9Height"] !== undefined) {
- 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.setTouchScaleChangeEnabled(touchScaleChangeAble);
- var text = options["text"];
- label.setText(text);
- if (options["fontSize"] !== undefined) {
- label.setFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- label.setFontName(options["fontName"]);
- }
- if (options["areaWidth"] !== undefined && options["areaHeight"] !== undefined) {
- var size = cc.size(options["areaWidth"], options["areaHeight"]);
- label.setTextAreaSize(size);
- }
- if (options["hAlignment"]) {
- label.setTextHorizontalAlignment(options["hAlignment"]);
- }
- if (options["vAlignment"]) {
- label.setTextVerticalAlignment(options["vAlignment"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelAtlasFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var labelAtlas = widget;
- var sv = (options["stringValue"] !== undefined);
- var cmf = (options["charMapFile"] !== undefined);
- var iw = (options["itemWidth"] !== undefined);
- var ih = (options["itemHeight"] !== undefined);
- var scm = (options["startCharMap"] !== undefined);
- if (sv && cmf && iw && ih && scm) {
-
- var cmftDic = options["charMapFileData"];
- var cmfType = cmftDic["resourceType"];
- switch (cmfType) {
- case 0:
- var cmfPath = cmftDic["path"];
- var cmf_tp = this._filePath + 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);
- },
-
- setPropsForLayoutFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var panel = widget;
- if (!(panel instanceof ccui.ScrollView) && !(panel instanceof ccui.ListView)) {
- panel.setClippingEnabled(options["clipAble"]);
- }
- 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.color(scr, scg, scb), cc.color(ecr, ecg, ecb));
- panel.setBackGroundColor(cc.color(cr, cg, cb));
- panel.setBackGroundColorOpacity(co);
-
-
- var imageFileNameDic = options["backGroundImageData"] || {};
- var imageFileNameType = imageFileNameDic["resourceType"];
- switch (imageFileNameType) {
- case 0:
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- panel.setBackGroundImage(imageFileName_tp);
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- panel.setBackGroundImage(imageFileName, ccui.Widget.PLIST_TEXTURE);
- 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));
- }
- panel.setLayoutType(options["layoutType"]);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
-
- setPropsForScrollViewFromJsonDictionary: function (widget, options) {
- this.setPropsForLayoutFromJsonDictionary(widget, options);
- var scrollView = widget;
- var innerWidth = options["innerWidth"];
- var innerHeight = options["innerHeight"];
- scrollView.setInnerContainerSize(cc.size(innerWidth, innerHeight));
- var direction = options["direction"];
- scrollView.setDirection(direction);
- scrollView.setBounceEnabled(options["bounceEnable"]);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForSliderFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var slider = widget;
-
- var barTextureScale9Enable = options["barTextureScale9Enable"] || false;
- slider.setScale9Enabled(barTextureScale9Enable);
- var barLength = options["length"];
- var bt = (options["barFileName"] !== undefined);
- if (bt) {
- if (barTextureScale9Enable) {
- var imageFileNameDic = options["barFileNameData"];
- var imageFileType = imageFileNameDic["resourceType"];
- switch (imageFileType) {
- case 0:
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- slider.loadBarTexture(imageFileName_tp);
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- slider.loadBarTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- 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 imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- slider.loadBarTexture(imageFileName_tp);
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- slider.loadBarTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
- }
- }
-
- var normalDic = options["ballNormalData"];
- var normalType = normalDic["resourceType"];
- switch (normalType) {
- case 0:
- var normalFileName = normalDic["path"];
- var normalFileName_tp = normalFileName ? this._filePath + normalFileName : null;
- slider.loadSlidBallTextureNormal(normalFileName_tp);
- break;
- case 1:
- var normalFileName = normalDic["path"];
- slider.loadSlidBallTextureNormal(normalFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- normalDic = null;
-
- var pressedDic = options["ballPressedData"];
- var pressedType = pressedDic["resourceType"];
- switch (pressedType) {
- case 0:
- var pressedFileName = pressedDic["path"];
- var pressedFileName_tp = pressedFileName ? this._filePath + pressedFileName : null;
- slider.loadSlidBallTexturePressed(pressedFileName_tp);
- break;
- case 1:
- var pressedFileName = pressedDic["path"];
- slider.loadSlidBallTexturePressed(pressedFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- pressedDic = null;
-
- var disabledDic = options["ballDisabledData"];
- var disabledType = disabledDic["resourceType"];
- switch (disabledType) {
- case 0:
- var disabledFileName = disabledDic["path"];
- var disabledFileName_tp = disabledFileName ? this._filePath + disabledFileName : null;
- slider.loadSlidBallTextureDisabled(disabledFileName_tp);
- break;
- case 1:
- var disabledFileName = disabledDic["path"];
- slider.loadSlidBallTextureDisabled(disabledFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- disabledDic = null;
-
- var progressBarDic = options["progressBarData"];
- var progressBarType = progressBarDic["resourceType"];
- switch (progressBarType) {
- case 0:
- var imageFileName = progressBarDic["path"];
- var imageFileName_tp = imageFileName ? this._filePath + imageFileName : null;
- slider.loadProgressBarTexture(imageFileName_tp);
- break;
- case 1:
- var imageFileName = progressBarDic["path"];
- slider.loadProgressBarTexture(imageFileName, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
-
- slider.setPercent(options["percent"]);
- },
-
- setPropsForTextAreaFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var textArea = widget;
- textArea.setText(options["text"]);
- if (options["fontSize"] !== undefined) {
- textArea.setFontSize(options["fontSize"]);
- }
- var cr = options["colorR"]
- var cg = options["colorG"];
- var cb = options["colorB"];
- textArea.setColor(cc.color(cr, cg, cb));
- textArea.setFontName(options["fontName"]);
- if (options["areaWidth"] !== undefined && options["areaHeight"] !== undefined) {
- var size = cc.size(options["areaWidth"], options["areaHeight"]);
- textArea.setTextAreaSize(size);
- }
- if (options["hAlignment"]) {
- textArea.setTextHorizontalAlignment(options["hAlignment"]);
- }
- if (options["vAlignment"]) {
- textArea.setTextVerticalAlignment(options["vAlignment"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextButtonFromJsonDictionary: function (widget, options) {
- this.setPropsForButtonFromJsonDictionary(widget, options);
-
- var textButton = widget;
- textButton.setTitleText(options["text"] || "");
- var cri = options["textColorR"] !== undefined ? options["textColorR"] : 255;
- var cgi = options["textColorG"] !== undefined ? options["textColorG"] : 255;
- var cbi = options["textColorB"] !== undefined ? options["textColorB"] : 255;
- textButton.setTitleColor(cc.color(cri, cgi, cbi));
- if (options["fontSize"] !== undefined) {
- textButton.setTitleFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- textButton.setTitleFontName(options["fontName"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextFieldFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var textField = widget;
- if (options["placeHolder"] !== undefined) {
- textField.setPlaceHolder(options["placeHolder"]);
- }
- textField.setText(options["text"]);
- if (options["fontSize"] !== undefined) {
- textField.setFontSize(options["fontSize"]);
- }
- if (options["fontName"] !== undefined) {
- textField.setFontName(options["fontName"]);
- }
- if (options["touchSizeWidth"] !== undefined && options["touchSizeHeight"] !== undefined) {
- 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.setMaxLengthEnabled(maxLengthEnable);
-
- if (maxLengthEnable) {
- var maxLength = options["maxLength"];
- textField.setMaxLength(maxLength);
- }
- var passwordEnable = options["passwordEnable"];
- textField.setPasswordEnabled(passwordEnable);
- if (passwordEnable) {
- textField.setPasswordStyleText(options["passwordStyleText"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLoadingBarFromJsonDictionary: function (widget, options) {
- 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, ccui.Widget.PLIST_TEXTURE);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
-
- 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.setPropsForLayoutFromJsonDictionary(widget, options);
- var innerWidth = options["innerWidth"] || 0;
- var innerHeight = options["innerHeight"] || 0;
- widget.setInnerContainerSize(cc.size(innerWidth, innerHeight));
- widget.setDirection(options["direction"] || 0);
- widget.setGravity(options["gravity"] || 0);
- widget.setItemsMargin(options["itemMargin"] || 0);
- },
-
- setPropsForPageViewFromJsonDictionary: function (widget, options) {
- this.setPropsForLayoutFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelBMFontFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
-
- var labelBMFont = widget;
-
- var cmftDic = options["fileNameData"];
- var cmfType = cmftDic["resourceType"];
- switch (cmfType) {
- case 0:
- var cmfPath = cmftDic["path"];
- var cmf_tp = this._filePath + 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);
- }
-});
diff --git a/extensions/cocostudio/reader/SceneReader.js b/extensions/cocostudio/reader/SceneReader.js
deleted file mode 100644
index 2d73b83801..0000000000
--- a/extensions/cocostudio/reader/SceneReader.js
+++ /dev/null
@@ -1,342 +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.
- ****************************************************************************/
-
-/**
- * @namespace Base singleton object for ccs.sceneReader
- */
-ccs.sceneReader = /** @lends ccs.sceneReader# */{
- _baseBath:"",
- _listener:null,
- _selector:null,
- _node: null,
-
- /**
- * create node with json file that exported by CocoStudio scene editor
- * @param pszFileName
- * @returns {cc.Node}
- */
- createNodeWithSceneFile: function (pszFileName) {
- this._baseBath = cc.path.dirname(pszFileName);
- var jsonDict = cc.loader.getRes(pszFileName);
-
- if (!jsonDict) throw "Please load the resource first : " + pszFileName;
-
- this._node = this.createObject(jsonDict, null);
- ccs.triggerManager.parse(jsonDict["Triggers"]||[]);
- return this._node;
- },
-
- /**
- * create object from data
- * @param {Object} inputFiles
- * @param {cc.Node} parenet
- * @returns {cc.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 = "", plistFile = "";
- var resType = 0;
- if (fileData != null) {
- if(fileData["resourceType"] !== undefined){
- resType = fileData["resourceType"]
- }else{
- resType =-1;
- }
-
- path = cc.path.join(this._baseBath, fileData["path"]);
- plistFile = fileData["plistFile"];
- }
-
- var pathExtname = cc.path.extname(path);
-
- if (className == "CCSprite") {
- var sprite = null;
-
- if (resType == 0) {
- if (pathExtname != ".png") continue;
- sprite = cc.Sprite.create(path);
- }
- else if (resType == 1) {
- if (pathExtname != ".plist") continue;
-
- plistFile = cc.path.join(this._baseBath, plistFile);
- var pngFile = cc.path.changeExtname(plistFile, ".png");
- cc.spriteFrameCache.addSpriteFrames(plistFile, pngFile);
- sprite = cc.Sprite.create("#" + fileData["path"]);
- }
- else {
- continue;
- }
-
- var render = ccs.ComRender.create(sprite, "CCSprite");
- if (comName != null) {
- render.setName(comName);
- }
-
- gb.addComponent(render);
- this._callSelector(sprite, subDict);
- }
- else if (className == "CCTMXTiledMap") {
- var tmx = null;
- if (resType == 0) {
- if (pathExtname != ".tmx") continue;
- tmx = cc.TMXTiledMap.create(path);
- }
- else {
- continue;
- }
-
- var render = ccs.ComRender.create(tmx, "CCTMXTiledMap");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
- this._callSelector(tmx, subDict);
- }
- else if (className == "CCParticleSystemQuad") {
- if (pathExtname != ".plist") continue;
-
- var particle = null;
- if (resType == 0) {
- particle = cc.ParticleSystem.create(path);
- }
- else {
- cc.log("unknown resourcetype on CCParticleSystemQuad!");
- continue;
- }
-
- particle.setPosition(0, 0);
- var render = ccs.ComRender.create(particle, "CCParticleSystemQuad");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
- this._callSelector(particle, subDict);
- }
- else if (className == "CCArmature") {
- if (resType != 0) {
- continue;
- }
- 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);
-
- var armature = ccs.Armature.create(name);
- var render = ccs.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;
- this._callSelector(armature, subDict);
- }
- else if (className == "CCComAudio") {
- var audio = null;
- if (resType == 0) {
- audio = ccs.ComAudio.create();
- }
- else {
- continue;
- }
- audio.preloadEffect(path);
- if (comName) {
- audio.setName(comName);
- }
- gb.addComponent(audio);
- this._callSelector(audio, subDict);
- }
- else if (className == "CCComAttribute") {
- var attribute = null;
- if (resType == 0) {
- attribute = ccs.ComAttribute.create();
- if (path != "") attribute.parse(path);
- }
- else {
- cc.log("unknown resourcetype on CCComAttribute!");
- continue;
- }
- if (comName) {
- attribute.setName(comName);
- }
- gb.addComponent(attribute);
- this._callSelector(attribute, subDict);
- }
- else if (className == "CCBackgroundAudio") {
- if(!pathExtname) continue;
- if(resType!=0) continue;
-
- var audio = ccs.ComAudio.create();
- audio.preloadBackgroundMusic(path);
- audio.setFile(path);
- var bLoop = Boolean(subDict["loop"] || 0);
- audio.setLoop(bLoop);
- if (comName) {
- audio.setName(comName);
- }
- gb.addComponent(audio);
- audio.playBackgroundMusic(path, bLoop);
- this._callSelector(audio, subDict);
- }
- else if (className == "GUIComponent") {
- var widget = ccs.uiReader.widgetFromJsonFile(path);
- var render = ccs.ComRender.create(widget, "GUIComponent");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
- this._callSelector(audio, subDict);
- }
- 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;
- },
-
-
- 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;
- },
-
- getNodeByTag: function (tag) {
- if (this._node == null) {
- return null;
- }
- if (this._node.getTag() == tag) {
- return this._node;
- }
- return this.nodeByTag(this._node, tag);
- },
-
- /**
- * set property
- * @param {cc.Node} node
- * @param {Object} dict
- */
- setPropertyFromJsonDict: function (node, dict) {
- var x = (typeof dict["x"] === 'undefined')?0:dict["x"];
- var y = (typeof dict["y"] === 'undefined')?0:dict["y"];
- node.setPosition(x, y);
-
- var bVisible = Boolean((typeof dict["visible"] === 'undefined')?1:dict["visible"]);
- node.setVisible(bVisible);
-
- var nTag = (typeof dict["objecttag"] === 'undefined')?-1:dict["objecttag"];
- node.setTag(nTag);
-
- var nZorder = (typeof dict["zorder"] === 'undefined')?0:dict["zorder"];
- node.setLocalZOrder(nZorder);
-
- var fScaleX = (typeof dict["scalex"] === 'undefined')?1:dict["scalex"];
- var fScaleY = (typeof dict["scaley"] === 'undefined')?1:dict["scaley"];
- node.setScaleX(fScaleX);
- node.setScaleY(fScaleY);
-
- var fRotationZ = (typeof dict["rotation"] === 'undefined')?0:dict["rotation"];
- node.setRotation(fRotationZ);
- },
- setTarget : function(selector,listener){
- this._listener = listener;
- this._selector = selector;
- },
- _callSelector:function(obj,subDict){
- if(this._selector){
- this._selector.call(this._listener,obj,subDict);
- }
- },
-
- version: function () {
- return "1.2.0.0";
- },
-
- /**
- * Clear data
- */
- clear: function () {
- ccs.triggerManager.removeAll();
- cc.audioEngine.end();
- }
-};
\ No newline at end of file
diff --git a/extensions/cocostudio/timeline/ActionTimeline.js b/extensions/cocostudio/timeline/ActionTimeline.js
new file mode 100644
index 0000000000..d458bb958b
--- /dev/null
+++ b/extensions/cocostudio/timeline/ActionTimeline.js
@@ -0,0 +1,509 @@
+/****************************************************************************
+ 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.ObjectExtensionData = ccs.Class.extend({
+
+ _customProperty: null,
+ _timelineData: null,
+
+ ctor: function(){
+ this._timelineData = new ccs.ActionTimelineData(0);
+ return true;
+ },
+
+ setActionTag: function(actionTag){
+ this._timelineData.setActionTag(actionTag);
+ },
+
+ getActionTag: function(){
+ return this._timelineData.getActionTag();
+ }
+});
+
+ccs.ObjectExtensionData.create = function(){
+ return new ccs.ObjectExtensionData();
+};
+
+/**
+ * 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,
+
+ 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
+ * Returns the flag which indicates whether the widget is flipped horizontally or not.
+ * Return the flag which indicates whether the widget is flipped vertically or not. 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.
+ * The skeleton of Spine.
+ *
+ * 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);
+ *
+ *
+ * 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);
+ * Your browser does not support HTML5 canvas!
' +
- '
';
- var p = d.getElementById(c.tag).parentNode;
- p.style.background = 'none';
- p.style.border = 'none';
- p.insertBefore(s);
-
- d.body.style.background = '#ffffff';
- return;
- }
-
- var fn;
- window.addEventListener('DOMContentLoaded', fn = function() {
- this.removeEventListener('DOMContentLoaded', fn, 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 + '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 @@
-
-
-
-
-
+ * 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).
+ *
+ * @param {String} fromAnimation
+ * @param {String} toAnimation
+ * @param {Number} duration
+ */
+ setMix: function (fromAnimation, toAnimation, duration) {
+ this._state.data.setMixByName(fromAnimation, toAnimation, duration);
+ },
+
+ /**
+ * Sets event listener of sp.SkeletonAnimation.
+ * @param {Object} target
+ * @param {Function} callback
+ */
+ setAnimationListener: function (target, callback) {
+ this._target = target;
+ this._callback = callback;
+ },
+
+ /**
+ * Set the current animation. Any queued animations are cleared.
+ * @param {Number} trackIndex
+ * @param {String} name
+ * @param {Boolean} loop
+ * @returns {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.setAnimation(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 {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.addAnimation(trackIndex, animation, loop, delay);
+ },
+
+ /**
+ * Returns track entry by trackIndex.
+ * @param trackIndex
+ * @returns {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._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._startListener = listener;
+ },
+
+ /**
+ * Set the end event listener.
+ * @param {function} listener
+ */
+ setEndListener: function(listener) {
+ this._endListener = listener;
+ },
+
+ setCompleteListener: function(listener) {
+ this._completeListener = listener;
+ },
+
+ setEventListener: function(listener){
+ this._eventListener = listener;
+ },
+
+ setTrackStartListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).startListener = listener;
+ },
+
+ setTrackEndListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).endListener = listener;
+ },
+
+ setTrackCompleteListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).completeListener = listener;
+ },
+
+ setTrackEventListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).eventListener = listener;
+ },
+
+ onTrackEntryEvent: function(traceIndex, type, event, loopCount){
+ var entry = this._state.getCurrent(traceIndex);
+ if(!entry.rendererObject)
+ return;
+ var listeners = entry.rendererObject;
+ switch (type){
+ case sp.ANIMATION_EVENT_TYPE.START:
+ if(listeners.startListener)
+ listeners.startListener(traceIndex);
+ break;
+ case sp.ANIMATION_EVENT_TYPE.END:
+ if(listeners.endListener)
+ listeners.endListener(traceIndex);
+ break;
+ case sp.ANIMATION_EVENT_TYPE.COMPLETE:
+ if(listeners.completeListener)
+ listeners.completeListener(traceIndex, loopCount);
+ break;
+ case sp.ANIMATION_EVENT_TYPE.EVENT:
+ if(listeners.eventListener)
+ listeners.eventListener(traceIndex, event);
+ break;
+ }
+ },
+
+ onAnimationStateEvent: function(trackIndex, type, event, loopCount) {
+ switch(type){
+ case sp.ANIMATION_EVENT_TYPE.START:
+ if(this._startListener)
+ this._startListener(trackIndex);
+ break;
+ case sp.ANIMATION_EVENT_TYPE.END:
+ if(this._endListener)
+ this._endListener(trackIndex);
+ break;
+ case sp.ANIMATION_EVENT_TYPE.COMPLETE:
+ if(this._completeListener)
+ this._completeListener(trackIndex, loopCount);
+ break;
+ case sp.ANIMATION_EVENT_TYPE.EVENT:
+ if(this._eventListener)
+ this._eventListener(trackIndex, event);
+ break;
+ }
+ },
+
+ getState: function(){
+ return this._state;
+ },
+
+ _onAnimationStateStart: function (trackIndex) {
+ this._animationStateCallback(trackIndex, sp.ANIMATION_EVENT_TYPE.START, null, 0);
+ },
+ _onAnimationStateEnd: function (trackIndex) {
+ this._animationStateCallback(trackIndex, sp.ANIMATION_EVENT_TYPE.END, null, 0);
+ },
+ _onAnimationStateComplete: function (trackIndex, count) {
+ this._animationStateCallback(trackIndex, sp.ANIMATION_EVENT_TYPE.COMPLETE, null, count);
+ },
+ _onAnimationStateEvent: function (trackIndex, event) {
+ this._animationStateCallback(trackIndex, sp.ANIMATION_EVENT_TYPE.EVENT, event, 0);
+ },
+ _animationStateCallback: function (trackIndex, type, event, loopCount) {
+ this.onAnimationStateEvent(trackIndex, type, event, loopCount);
+ if (this._target && this._callback) {
+ this._callback.call(this._target, this, trackIndex, type, event, loopCount)
+ }
+ }
+});
+
+/**
+ * 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.create = function (skeletonDataFile, atlasFile/* or atlas*/, scale) {
+ return new sp.SkeletonAnimation(skeletonDataFile, atlasFile, scale);
+};
\ No newline at end of file
diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js
new file mode 100644
index 0000000000..1b4f873cd1
--- /dev/null
+++ b/extensions/spine/CCSkeletonCanvasRenderCmd.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(){
+ sp.Skeleton.CanvasRenderCmd = function(renderableObject){
+ cc.Node.CanvasRenderCmd.call(this, 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.type != sp.ATTACHMENT_TYPE.REGION)
+ 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.m00 + bone.worldX;
+ var y = bone.data.length * bone.m10 + bone.worldY;
+ drawingUtil.drawLine(
+ {x: bone.worldX, y: bone.worldY},
+ {x: x, y: 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({x: bone.worldX, y: bone.worldY});
+ if (i === 0)
+ drawingUtil.setDrawColor(0, 255, 0, 255);
+ }
+ }
+ };
+
+ proto._updateRegionAttachmentSlot = function(attachment, slot, points) {
+ if(!points)
+ return;
+
+ var vertices = {}, VERTEX = sp.VERTEX_INDEX, bone = slot.bone;
+ attachment.computeVertices(bone.skeleton.x, bone.skeleton.y, bone, vertices);
+ points.length = 0;
+ points.push(cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1]));
+ points.push(cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4]));
+ points.push(cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3]));
+ points.push(cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2]));
+ };
+
+ 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.rendererObject.name;
+ sprite = this._createSprite(slot, attachment);
+ slot.currentSprite = sprite;
+ slot.currentSpriteName = spriteName;
+ slotNode.addChild(sprite);
+ } else if(attachment instanceof spine.MeshAttachment){
+ //todo for mesh
+ }
+ }
+ };
+
+ proto._createSprite = function(slot, attachment){
+ var rendererObject = attachment.rendererObject;
+ var texture = rendererObject.page._texture;
+ var rect = new cc.Rect(rendererObject.x, rendererObject.y, rendererObject.width, rendererObject.height);
+ var sprite = new cc.Sprite();
+ sprite.initWithTexture(rendererObject.page._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);
+
+ slot.sprites = slot.sprites || {};
+ slot.sprites[rendererObject.name] = sprite;
+
+ return sprite;
+ };
+
+ proto._updateChild = function(){
+ var locSkeleton = this._node._skeleton, slots = locSkeleton.slots;
+ var i, n, selSprite;
+
+ 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;
+ }
+ var type = attachment.type;
+ if (type === spine.AttachmentType.region){
+ if(attachment.rendererObject){
+ if(!slot.currentSpriteName || slot.currentSpriteName !== attachment.name){
+ var spriteName = attachment.rendererObject.name;
+ if(slot.currentSprite !== undefined)
+ slot.currentSprite.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;
+ slotNode.setPosition(bone.worldX + attachment.x * bone.m00 + attachment.y * bone.m01,
+ bone.worldY + attachment.x * bone.m10 + attachment.y * bone.m11);
+ slotNode.setScale(bone.worldScaleX, bone.worldScaleY);
+
+ //set the color and opacity
+ selSprite = slot.currentSprite;
+ selSprite._flippedX = bone.worldFlipX;
+ selSprite._flippedY = bone.worldFlipY;
+ if(selSprite._flippedY || selSprite._flippedX){
+ slotNode.setRotation(bone.worldRotation);
+ selSprite.setRotation(attachment.rotation);
+ }else{
+ slotNode.setRotation(-bone.worldRotation);
+ selSprite.setRotation(-attachment.rotation);
+ }
+
+ //hack for sprite
+ selSprite._renderCmd._displayedOpacity = 0 | (locSkeleton.a * slot.a * 255);
+ var r = 0 | (locSkeleton.r * slot.r * 255), g = 0 | (locSkeleton.g * slot.g * 255), b = 0 | (locSkeleton.b * slot.b * 255);
+ selSprite.setColor(cc.color(r,g,b));
+ selSprite._renderCmd._updateColor();
+ } else if (type === spine.AttachmentType.skinnedmesh) {
+ //todo for mesh
+ } else {
+ slotNode.setVisible(false);
+ continue;
+ }
+ slotNode.setVisible(true);
+ }
+ };
+})();
\ No newline at end of file
diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js
new file mode 100644
index 0000000000..ca0f14b613
--- /dev/null
+++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js
@@ -0,0 +1,246 @@
+/****************************************************************************
+ 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(){
+ sp.Skeleton.WebGLRenderCmd = function (renderableObject) {
+ cc.Node.WebGLRenderCmd.call(this, renderableObject);
+ this._needDraw = true;
+ this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
+ this._tmpQuad = new cc.V3F_C4B_T2F_Quad();
+ };
+
+ var proto = sp.Skeleton.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = sp.Skeleton.WebGLRenderCmd;
+
+ proto.rendering = function (ctx) {
+ var node = this._node, tmpQuad = this._tmpQuad;
+ this._shaderProgram.use();
+ this._shaderProgram._setUniformForMVPMatrixWithMat4(this._stackMatrix);
+// cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
+ var color = node.getColor(), locSkeleton = node._skeleton;
+ locSkeleton.r = color.r / 255;
+ locSkeleton.g = color.g / 255;
+ locSkeleton.b = color.b / 255;
+ locSkeleton.a = node.getOpacity() / 255;
+ if (node._premultipliedAlpha) {
+ locSkeleton.r *= locSkeleton.a;
+ locSkeleton.g *= locSkeleton.a;
+ locSkeleton.b *= locSkeleton.a;
+ }
+
+ var additive, textureAtlas, attachment, slot, i, n;
+ var locBlendFunc = node._blendFunc;
+
+ //for (i = 0, n = locSkeleton.slots.length; i < n; i++) {
+ for (i = 0, n = locSkeleton.drawOrder.length; i < n; i++) {
+ slot = locSkeleton.drawOrder[i];
+ if (!slot.attachment)
+ continue;
+ attachment = slot.attachment;
+
+ switch(slot.attachment.type) {
+ case sp.ATTACHMENT_TYPE.REGION:
+ this._updateRegionAttachmentQuad(attachment, slot, tmpQuad, node._premultipliedAlpha);
+ break;
+ case sp.ATTACHMENT_TYPE.MESH:
+ this._updateMeshAttachmentQuad(attachment, slot, tmpQuad, node._premultipliedAlpha);
+ break;
+ case sp.ATTACHMENT_TYPE.SKINNED_MESH:
+ break;
+ default:
+ continue;
+ }
+
+ var regionTextureAtlas = node.getTextureAtlas(attachment);
+
+ if (slot.data.additiveBlending != additive) {
+ if (textureAtlas) {
+ textureAtlas.drawQuads();
+ textureAtlas.removeAllQuads();
+ }
+ additive = !additive;
+ cc.glBlendFunc(locBlendFunc.src, additive ? cc.ONE : locBlendFunc.dst);
+ } else if (regionTextureAtlas != textureAtlas && textureAtlas) {
+ textureAtlas.drawQuads();
+ textureAtlas.removeAllQuads();
+ }
+ textureAtlas = regionTextureAtlas;
+
+ var quadCount = textureAtlas.getTotalQuads();
+ if (textureAtlas.getCapacity() == quadCount) {
+ textureAtlas.drawQuads();
+ textureAtlas.removeAllQuads();
+ if (!textureAtlas.resizeCapacity(textureAtlas.getCapacity() * 2))
+ return;
+ }
+
+ textureAtlas.updateQuad(tmpQuad, quadCount);
+ }
+
+ if (textureAtlas) {
+ textureAtlas.drawQuads();
+ textureAtlas.removeAllQuads();
+ }
+
+ if (node._debugBones || node._debugSlots) {
+ cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
+ //cc.kmGLPushMatrixWitMat4(this._stackMatrix);
+ cc.current_stack.stack.push(cc.current_stack.top);
+ cc.current_stack.top = this._stackMatrix;
+ var drawingUtil = cc._drawingUtil;
+
+ if (node._debugSlots) {
+ // Slots.
+ drawingUtil.setDrawColor(0, 0, 255, 255);
+ drawingUtil.setLineWidth(1);
+
+ for (i = 0, n = locSkeleton.slots.length; i < n; i++) {
+ slot = locSkeleton.drawOrder[i];
+ if (!slot.attachment || slot.attachment.type != sp.ATTACHMENT_TYPE.REGION)
+ continue;
+ attachment = slot.attachment;
+ this._updateRegionAttachmentQuad(attachment, slot, tmpQuad);
+
+ var points = [];
+ points.push(cc.p(tmpQuad.bl.vertices.x, tmpQuad.bl.vertices.y));
+ points.push(cc.p(tmpQuad.br.vertices.x, tmpQuad.br.vertices.y));
+ points.push(cc.p(tmpQuad.tr.vertices.x, tmpQuad.tr.vertices.y));
+ points.push(cc.p(tmpQuad.tl.vertices.x, tmpQuad.tl.vertices.y));
+
+ 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.m00 + bone.worldX;
+ var y = bone.data.length * bone.m10 + 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();
+ }
+ };
+
+ proto._createChildFormSkeletonData = function(){};
+
+ proto._updateChild = function(){};
+
+ proto._updateRegionAttachmentQuad = function(self, slot, quad, premultipliedAlpha) {
+ var vertices = {};
+ self.computeVertices(slot.bone.skeleton.x, slot.bone.skeleton.y, slot.bone, vertices);
+ var r = slot.bone.skeleton.r * slot.r * 255;
+ var g = slot.bone.skeleton.g * slot.g * 255;
+ var b = slot.bone.skeleton.b * slot.b * 255;
+ var normalizedAlpha = slot.bone.skeleton.a * slot.a;
+
+ if (premultipliedAlpha) {
+ r *= normalizedAlpha;
+ g *= normalizedAlpha;
+ b *= normalizedAlpha;
+ }
+ var a = normalizedAlpha * 255;
+
+ quad.bl.colors.r = quad.tl.colors.r = quad.tr.colors.r = quad.br.colors.r = r;
+ quad.bl.colors.g = quad.tl.colors.g = quad.tr.colors.g = quad.br.colors.g = g;
+ quad.bl.colors.b = quad.tl.colors.b = quad.tr.colors.b = quad.br.colors.b = b;
+ quad.bl.colors.a = quad.tl.colors.a = quad.tr.colors.a = quad.br.colors.a = a;
+
+ var VERTEX = sp.VERTEX_INDEX;
+ quad.bl.vertices.x = vertices[VERTEX.X1];
+ quad.bl.vertices.y = vertices[VERTEX.Y1];
+ quad.tl.vertices.x = vertices[VERTEX.X2];
+ quad.tl.vertices.y = vertices[VERTEX.Y2];
+ quad.tr.vertices.x = vertices[VERTEX.X3];
+ quad.tr.vertices.y = vertices[VERTEX.Y3];
+ quad.br.vertices.x = vertices[VERTEX.X4];
+ quad.br.vertices.y = vertices[VERTEX.Y4];
+
+ quad.bl.texCoords.u = self.uvs[VERTEX.X1];
+ quad.bl.texCoords.v = self.uvs[VERTEX.Y1];
+ quad.tl.texCoords.u = self.uvs[VERTEX.X2];
+ quad.tl.texCoords.v = self.uvs[VERTEX.Y2];
+ quad.tr.texCoords.u = self.uvs[VERTEX.X3];
+ quad.tr.texCoords.v = self.uvs[VERTEX.Y3];
+ quad.br.texCoords.u = self.uvs[VERTEX.X4];
+ quad.br.texCoords.v = self.uvs[VERTEX.Y4];
+ };
+
+ proto._updateMeshAttachmentQuad = function(self, slot, quad, premultipliedAlpha) {
+ var vertices = {};
+ self.computeWorldVertices(slot.bone.x, slot.bone.y, slot, vertices);
+ var r = slot.bone.skeleton.r * slot.r * 255;
+ var g = slot.bone.skeleton.g * slot.g * 255;
+ var b = slot.bone.skeleton.b * slot.b * 255;
+ var normalizedAlpha = slot.bone.skeleton.a * slot.a;
+ if (premultipliedAlpha) {
+ r *= normalizedAlpha;
+ g *= normalizedAlpha;
+ b *= normalizedAlpha;
+ }
+ var a = normalizedAlpha * 255;
+
+ quad.bl.colors.r = quad.tl.colors.r = quad.tr.colors.r = quad.br.colors.r = r;
+ quad.bl.colors.g = quad.tl.colors.g = quad.tr.colors.g = quad.br.colors.g = g;
+ quad.bl.colors.b = quad.tl.colors.b = quad.tr.colors.b = quad.br.colors.b = b;
+ quad.bl.colors.a = quad.tl.colors.a = quad.tr.colors.a = quad.br.colors.a = a;
+
+ var VERTEX = sp.VERTEX_INDEX;
+ quad.bl.vertices.x = vertices[VERTEX.X1];
+ quad.bl.vertices.y = vertices[VERTEX.Y1];
+ quad.tl.vertices.x = vertices[VERTEX.X2];
+ quad.tl.vertices.y = vertices[VERTEX.Y2];
+ quad.tr.vertices.x = vertices[VERTEX.X3];
+ quad.tr.vertices.y = vertices[VERTEX.Y3];
+ quad.br.vertices.x = vertices[VERTEX.X4];
+ quad.br.vertices.y = vertices[VERTEX.Y4];
+
+ quad.bl.texCoords.u = self.uvs[VERTEX.X1];
+ quad.bl.texCoords.v = self.uvs[VERTEX.Y1];
+ quad.tl.texCoords.u = self.uvs[VERTEX.X2];
+ quad.tl.texCoords.v = self.uvs[VERTEX.Y2];
+ quad.tr.texCoords.u = self.uvs[VERTEX.X3];
+ quad.tr.texCoords.v = self.uvs[VERTEX.Y3];
+ quad.br.texCoords.u = self.uvs[VERTEX.X4];
+ quad.br.texCoords.v = self.uvs[VERTEX.Y4];
+ };
+})();
\ No newline at end of file
diff --git a/extensions/spine/Spine.js b/extensions/spine/Spine.js
new file mode 100644
index 0000000000..7a25bab80e
--- /dev/null
+++ b/extensions/spine/Spine.js
@@ -0,0 +1,2628 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ *
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), you
+ * may not (a) modify, translate, adapt or otherwise create derivative works,
+ * improvements of the Software or develop new applications using the Software
+ * or (b) remove, delete, alter or obscure any trademarks or any copyright,
+ * trademark, patent or other intellectual property or proprietary rights
+ * notices on or in the Software, including any copy thereof. Redistributions
+ * in binary or source form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+var spine = {
+ radDeg: 180 / Math.PI,
+ degRad: Math.PI / 180,
+ temp: [],
+ Float32Array: (typeof(Float32Array) === 'undefined') ? Array : Float32Array,
+ Uint16Array: (typeof(Uint16Array) === 'undefined') ? Array : Uint16Array
+};
+
+spine.BoneData = function (name, parent) {
+ this.name = name;
+ this.parent = parent;
+};
+spine.BoneData.prototype = {
+ length: 0,
+ x: 0, y: 0,
+ rotation: 0,
+ scaleX: 1, scaleY: 1,
+ inheritScale: true,
+ inheritRotation: true,
+ flipX: false, flipY: false
+};
+
+spine.SlotData = function (name, boneData) {
+ this.name = name;
+ this.boneData = boneData;
+};
+spine.SlotData.prototype = {
+ r: 1, g: 1, b: 1, a: 1,
+ attachmentName: null,
+ additiveBlending: false
+};
+
+spine.IkConstraintData = function (name) {
+ this.name = name;
+ this.bones = [];
+};
+spine.IkConstraintData.prototype = {
+ target: null,
+ bendDirection: 1,
+ mix: 1
+};
+
+spine.Bone = function (boneData, skeleton, parent) {
+ this.data = boneData;
+ this.skeleton = skeleton;
+ this.parent = parent;
+ this.setToSetupPose();
+};
+spine.Bone.yDown = false;
+spine.Bone.prototype = {
+ x: 0, y: 0,
+ rotation: 0, rotationIK: 0,
+ scaleX: 1, scaleY: 1,
+ flipX: false, flipY: false,
+ m00: 0, m01: 0, worldX: 0, // a b x
+ m10: 0, m11: 0, worldY: 0, // c d y
+ worldRotation: 0,
+ worldScaleX: 1, worldScaleY: 1,
+ worldFlipX: false, worldFlipY: false,
+ updateWorldTransform: function () {
+ var parent = this.parent;
+ if (parent) {
+ this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX;
+ this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY;
+ if (this.data.inheritScale) {
+ this.worldScaleX = parent.worldScaleX * this.scaleX;
+ this.worldScaleY = parent.worldScaleY * this.scaleY;
+ } else {
+ this.worldScaleX = this.scaleX;
+ this.worldScaleY = this.scaleY;
+ }
+ this.worldRotation = this.data.inheritRotation ? (parent.worldRotation + this.rotationIK) : this.rotationIK;
+ this.worldFlipX = parent.worldFlipX != this.flipX;
+ this.worldFlipY = parent.worldFlipY != this.flipY;
+ } else {
+ var skeletonFlipX = this.skeleton.flipX, skeletonFlipY = this.skeleton.flipY;
+ this.worldX = skeletonFlipX ? -this.x : this.x;
+ this.worldY = (skeletonFlipY != spine.Bone.yDown) ? -this.y : this.y;
+ this.worldScaleX = this.scaleX;
+ this.worldScaleY = this.scaleY;
+ this.worldRotation = this.rotationIK;
+ this.worldFlipX = skeletonFlipX != this.flipX;
+ this.worldFlipY = skeletonFlipY != this.flipY;
+ }
+ var radians = this.worldRotation * spine.degRad;
+ var cos = Math.cos(radians);
+ var sin = Math.sin(radians);
+ if (this.worldFlipX) {
+ this.m00 = -cos * this.worldScaleX;
+ this.m01 = sin * this.worldScaleY;
+ } else {
+ this.m00 = cos * this.worldScaleX;
+ this.m01 = -sin * this.worldScaleY;
+ }
+ if (this.worldFlipY != spine.Bone.yDown) {
+ this.m10 = -sin * this.worldScaleX;
+ this.m11 = -cos * this.worldScaleY;
+ } else {
+ this.m10 = sin * this.worldScaleX;
+ this.m11 = cos * this.worldScaleY;
+ }
+ },
+ setToSetupPose: function () {
+ var data = this.data;
+ this.x = data.x;
+ this.y = data.y;
+ this.rotation = data.rotation;
+ this.rotationIK = this.rotation;
+ this.scaleX = data.scaleX;
+ this.scaleY = data.scaleY;
+ this.flipX = data.flipX;
+ this.flipY = data.flipY;
+ },
+ worldToLocal: function (world) {
+ var dx = world[0] - this.worldX, dy = world[1] - this.worldY;
+ var m00 = this.m00, m10 = this.m10, m01 = this.m01, m11 = this.m11;
+ if (this.worldFlipX != (this.worldFlipY != spine.Bone.yDown)) {
+ m00 = -m00;
+ m11 = -m11;
+ }
+ var invDet = 1 / (m00 * m11 - m01 * m10);
+ world[0] = dx * m00 * invDet - dy * m01 * invDet;
+ world[1] = dy * m11 * invDet - dx * m10 * invDet;
+ },
+ localToWorld: function (local) {
+ var localX = local[0], localY = local[1];
+ local[0] = localX * this.m00 + localY * this.m01 + this.worldX;
+ local[1] = localX * this.m10 + localY * this.m11 + this.worldY;
+ }
+};
+
+spine.Slot = function (slotData, bone) {
+ this.data = slotData;
+ this.bone = bone;
+ this.setToSetupPose();
+};
+spine.Slot.prototype = {
+ r: 1, g: 1, b: 1, a: 1,
+ _attachmentTime: 0,
+ attachment: null,
+ attachmentVertices: [],
+ setAttachment: function (attachment) {
+ this.attachment = attachment;
+ this._attachmentTime = this.bone.skeleton.time;
+ this.attachmentVertices.length = 0;
+ },
+ setAttachmentTime: function (time) {
+ this._attachmentTime = this.bone.skeleton.time - time;
+ },
+ getAttachmentTime: function () {
+ return this.bone.skeleton.time - this._attachmentTime;
+ },
+ setToSetupPose: function () {
+ var data = this.data;
+ this.r = data.r;
+ this.g = data.g;
+ this.b = data.b;
+ this.a = data.a;
+
+ var slotDatas = this.bone.skeleton.data.slots;
+ for (var i = 0, n = slotDatas.length; i < n; i++) {
+ if (slotDatas[i] == data) {
+ this.setAttachment(!data.attachmentName ? null : this.bone.skeleton.getAttachmentBySlotIndex(i, data.attachmentName));
+ break;
+ }
+ }
+ }
+};
+
+spine.IkConstraint = function (data, skeleton) {
+ this.data = data;
+ this.mix = data.mix;
+ this.bendDirection = data.bendDirection;
+
+ this.bones = [];
+ for (var i = 0, n = data.bones.length; i < n; i++)
+ this.bones.push(skeleton.findBone(data.bones[i].name));
+ this.target = skeleton.findBone(data.target.name);
+};
+spine.IkConstraint.prototype = {
+ apply: function () {
+ var target = this.target;
+ var bones = this.bones;
+ switch (bones.length) {
+ case 1:
+ spine.IkConstraint.apply1(bones[0], target.worldX, target.worldY, this.mix);
+ break;
+ case 2:
+ spine.IkConstraint.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix);
+ break;
+ }
+ }
+};
+/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
+ * coordinate system. */
+spine.IkConstraint.apply1 = function (bone, targetX, targetY, alpha) {
+ var parentRotation = (!bone.data.inheritRotation || !bone.parent) ? 0 : bone.parent.worldRotation;
+ var rotation = bone.rotation;
+ var rotationIK = Math.atan2(targetY - bone.worldY, targetX - bone.worldX) * spine.radDeg;
+ if (bone.worldFlipX != (bone.worldFlipY != spine.Bone.yDown)) rotationIK = -rotationIK;
+ rotationIK -= parentRotation;
+ bone.rotationIK = rotation + (rotationIK - rotation) * alpha;
+};
+/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
+ * target is specified in the world coordinate system.
+ * @param child Any descendant bone of the parent. */
+spine.IkConstraint.apply2 = function (parent, child, targetX, targetY, bendDirection, alpha) {
+ var childRotation = child.rotation, parentRotation = parent.rotation;
+ if (!alpha) {
+ child.rotationIK = childRotation;
+ parent.rotationIK = parentRotation;
+ return;
+ }
+ var positionX, positionY, tempPosition = spine.temp;
+ var parentParent = parent.parent;
+ if (parentParent) {
+ tempPosition[0] = targetX;
+ tempPosition[1] = targetY;
+ parentParent.worldToLocal(tempPosition);
+ targetX = (tempPosition[0] - parent.x) * parentParent.worldScaleX;
+ targetY = (tempPosition[1] - parent.y) * parentParent.worldScaleY;
+ } else {
+ targetX -= parent.x;
+ targetY -= parent.y;
+ }
+ if (child.parent == parent) {
+ positionX = child.x;
+ positionY = child.y;
+ } else {
+ tempPosition[0] = child.x;
+ tempPosition[1] = child.y;
+ child.parent.localToWorld(tempPosition);
+ parent.worldToLocal(tempPosition);
+ positionX = tempPosition[0];
+ positionY = tempPosition[1];
+ }
+ var childX = positionX * parent.worldScaleX, childY = positionY * parent.worldScaleY;
+ var offset = Math.atan2(childY, childX);
+ var len1 = Math.sqrt(childX * childX + childY * childY), len2 = child.data.length * child.worldScaleX;
+ // Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/
+ var cosDenom = 2 * len1 * len2;
+ if (cosDenom < 0.0001) {
+ child.rotationIK = childRotation + (Math.atan2(targetY, targetX) * spine.radDeg - parentRotation - childRotation) * alpha;
+ return;
+ }
+ var cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom;
+ if (cos < -1)
+ cos = -1;
+ else if (cos > 1)
+ cos = 1;
+ var childAngle = Math.acos(cos) * bendDirection;
+ var adjacent = len1 + len2 * cos, opposite = len2 * Math.sin(childAngle);
+ var parentAngle = Math.atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
+ var rotation = (parentAngle - offset) * spine.radDeg - parentRotation;
+ if (rotation > 180)
+ rotation -= 360;
+ else if (rotation < -180) //
+ rotation += 360;
+ parent.rotationIK = parentRotation + rotation * alpha;
+ rotation = (childAngle + offset) * spine.radDeg - childRotation;
+ if (rotation > 180)
+ rotation -= 360;
+ else if (rotation < -180) //
+ rotation += 360;
+ child.rotationIK = childRotation + (rotation + parent.worldRotation - child.parent.worldRotation) * alpha;
+};
+
+spine.Skin = function (name) {
+ this.name = name;
+ this.attachments = {};
+};
+spine.Skin.prototype = {
+ addAttachment: function (slotIndex, name, attachment) {
+ this.attachments[slotIndex + ":" + name] = attachment;
+ },
+ getAttachment: function (slotIndex, name) {
+ return this.attachments[slotIndex + ":" + name];
+ },
+ _attachAll: function (skeleton, oldSkin) {
+ for (var key in oldSkin.attachments) {
+ var colon = key.indexOf(":");
+ var slotIndex = parseInt(key.substring(0, colon));
+ var name = key.substring(colon + 1);
+ var slot = skeleton.slots[slotIndex];
+ if (slot.attachment && slot.attachment.name == name) {
+ var attachment = this.getAttachment(slotIndex, name);
+ if (attachment) slot.setAttachment(attachment);
+ }
+ }
+ }
+};
+
+spine.Animation = function (name, timelines, duration) {
+ this.name = name;
+ this.timelines = timelines;
+ this.duration = duration;
+};
+spine.Animation.prototype = {
+ apply: function (skeleton, lastTime, time, loop, events) {
+ if (loop && this.duration != 0) {
+ time %= this.duration;
+ lastTime %= this.duration;
+ }
+ var timelines = this.timelines;
+ for (var i = 0, n = timelines.length; i < n; i++)
+ timelines[i].apply(skeleton, lastTime, time, events, 1);
+ },
+ mix: function (skeleton, lastTime, time, loop, events, alpha) {
+ if (loop && this.duration != 0) {
+ time %= this.duration;
+ 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);
+ }
+};
+spine.Animation.binarySearch = function (values, target, step) {
+ var low = 0;
+ var high = Math.floor(values.length / step) - 2;
+ if (!high) return step;
+ var current = high >>> 1;
+ while (true) {
+ if (values[(current + 1) * step] <= target)
+ low = current + 1;
+ else
+ high = current;
+ if (low == high) return (low + 1) * step;
+ current = (low + high) >>> 1;
+ }
+};
+spine.Animation.binarySearch1 = function (values, target) {
+ var low = 0;
+ var high = values.length - 2;
+ if (!high) return 1;
+ var current = high >>> 1;
+ while (true) {
+ if (values[current + 1] <= target)
+ low = current + 1;
+ else
+ high = current;
+ if (low == high) return low + 1;
+ current = (low + high) >>> 1;
+ }
+};
+spine.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;
+};
+
+spine.Curves = function (frameCount) {
+ this.curves = []; // type, x, y, ...
+ //this.curves.length = (frameCount - 1) * 19/*BEZIER_SIZE*/;
+};
+spine.Curves.prototype = {
+ setLinear: function (frameIndex) {
+ this.curves[frameIndex * 19/*BEZIER_SIZE*/] = 0/*LINEAR*/;
+ },
+ setStepped: function (frameIndex) {
+ this.curves[frameIndex * 19/*BEZIER_SIZE*/] = 1/*STEPPED*/;
+ },
+ /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
+ * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
+ * the difference between the keyframe's values. */
+ setCurve: function (frameIndex, cx1, cy1, cx2, cy2) {
+ var subdiv1 = 1 / 10/*BEZIER_SEGMENTS*/, subdiv2 = subdiv1 * subdiv1, subdiv3 = subdiv2 * subdiv1;
+ var pre1 = 3 * subdiv1, pre2 = 3 * subdiv2, pre4 = 6 * subdiv2, pre5 = 6 * subdiv3;
+ var tmp1x = -cx1 * 2 + cx2, tmp1y = -cy1 * 2 + cy2, tmp2x = (cx1 - cx2) * 3 + 1, tmp2y = (cy1 - cy2) * 3 + 1;
+ var dfx = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv3, dfy = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv3;
+ var ddfx = tmp1x * pre4 + tmp2x * pre5, ddfy = tmp1y * pre4 + tmp2y * pre5;
+ var dddfx = tmp2x * pre5, dddfy = tmp2y * pre5;
+
+ var i = frameIndex * 19/*BEZIER_SIZE*/;
+ var curves = this.curves;
+ curves[i++] = 2/*BEZIER*/;
+
+ var x = dfx, y = dfy;
+ for (var n = i + 19/*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;
+ }
+ },
+ getCurvePercent: function (frameIndex, percent) {
+ percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent);
+ var curves = this.curves;
+ var i = frameIndex * 19/*BEZIER_SIZE*/;
+ var type = curves[i];
+ if (type === 0/*LINEAR*/) return percent;
+ if (type == 1/*STEPPED*/) return 0;
+ i++;
+ var x = 0;
+ for (var start = i, n = i + 19/*BEZIER_SIZE*/ - 1; i < n; i += 2) {
+ x = curves[i];
+ if (x >= percent) {
+ var prevX, prevY;
+ 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); // Last point is 1,1.
+ }
+};
+
+spine.RotateTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, angle, ...
+ this.frames.length = frameCount * 2;
+};
+spine.RotateTimeline.prototype = {
+ boneIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 2;
+ },
+ setFrame: function (frameIndex, time, angle) {
+ frameIndex *= 2;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = angle;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var bone = skeleton.bones[this.boneIndex];
+
+ if (time >= frames[frames.length - 2]) { // Time is after last frame.
+ var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation;
+ while (amount > 180)
+ amount -= 360;
+ while (amount < -180)
+ amount += 360;
+ bone.rotation += amount * alpha;
+ return;
+ }
+
+ // Interpolate between the previous frame and the current frame.
+ var frameIndex = spine.Animation.binarySearch(frames, time, 2);
+ var prevFrameValue = frames[frameIndex - 1];
+ var frameTime = frames[frameIndex];
+ var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*PREV_FRAME_TIME*/] - frameTime);
+ percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent);
+
+ var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - prevFrameValue;
+ while (amount > 180)
+ amount -= 360;
+ while (amount < -180)
+ amount += 360;
+ amount = bone.data.rotation + (prevFrameValue + amount * percent) - bone.rotation;
+ while (amount > 180)
+ amount -= 360;
+ while (amount < -180)
+ amount += 360;
+ bone.rotation += amount * alpha;
+ }
+};
+
+spine.TranslateTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, x, y, ...
+ this.frames.length = frameCount * 3;
+};
+spine.TranslateTimeline.prototype = {
+ boneIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 3;
+ },
+ setFrame: function (frameIndex, time, x, y) {
+ frameIndex *= 3;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = x;
+ this.frames[frameIndex + 2] = y;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var bone = skeleton.bones[this.boneIndex];
+
+ if (time >= frames[frames.length - 3]) { // Time is after last frame.
+ bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha;
+ bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha;
+ return;
+ }
+
+ // Interpolate between the previous frame and the current frame.
+ var frameIndex = spine.Animation.binarySearch(frames, time, 3);
+ var prevFrameX = frames[frameIndex - 2];
+ var prevFrameY = frames[frameIndex - 1];
+ var frameTime = frames[frameIndex];
+ var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime);
+ percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
+
+ bone.x += (bone.data.x + prevFrameX + (frames[frameIndex + 1/*FRAME_X*/] - prevFrameX) * percent - bone.x) * alpha;
+ bone.y += (bone.data.y + prevFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - prevFrameY) * percent - bone.y) * alpha;
+ }
+};
+
+spine.ScaleTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, x, y, ...
+ this.frames.length = frameCount * 3;
+};
+spine.ScaleTimeline.prototype = {
+ boneIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 3;
+ },
+ setFrame: function (frameIndex, time, x, y) {
+ frameIndex *= 3;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = x;
+ this.frames[frameIndex + 2] = y;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var bone = skeleton.bones[this.boneIndex];
+
+ if (time >= frames[frames.length - 3]) { // Time is after last frame.
+ bone.scaleX += (bone.data.scaleX * frames[frames.length - 2] - bone.scaleX) * alpha;
+ bone.scaleY += (bone.data.scaleY * frames[frames.length - 1] - bone.scaleY) * alpha;
+ return;
+ }
+
+ // Interpolate between the previous frame and the current frame.
+ var frameIndex = spine.Animation.binarySearch(frames, time, 3);
+ var prevFrameX = frames[frameIndex - 2];
+ var prevFrameY = frames[frameIndex - 1];
+ var frameTime = frames[frameIndex];
+ var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime);
+ percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
+
+ bone.scaleX += (bone.data.scaleX * (prevFrameX + (frames[frameIndex + 1/*FRAME_X*/] - prevFrameX) * percent) - bone.scaleX) * alpha;
+ bone.scaleY += (bone.data.scaleY * (prevFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - prevFrameY) * percent) - bone.scaleY) * alpha;
+ }
+};
+
+spine.ColorTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, r, g, b, a, ...
+ this.frames.length = frameCount * 5;
+};
+spine.ColorTimeline.prototype = {
+ slotIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 5;
+ },
+ setFrame: function (frameIndex, time, r, g, b, a) {
+ frameIndex *= 5;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = r;
+ this.frames[frameIndex + 2] = g;
+ this.frames[frameIndex + 3] = b;
+ this.frames[frameIndex + 4] = a;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var r, g, b, a;
+ if (time >= frames[frames.length - 5]) {
+ // Time is after last frame.
+ var i = frames.length - 1;
+ r = frames[i - 3];
+ g = frames[i - 2];
+ b = frames[i - 1];
+ a = frames[i];
+ } else {
+ // Interpolate between the previous frame and the current frame.
+ var frameIndex = spine.Animation.binarySearch(frames, time, 5);
+ var prevFrameR = frames[frameIndex - 4];
+ var prevFrameG = frames[frameIndex - 3];
+ var prevFrameB = frames[frameIndex - 2];
+ var prevFrameA = frames[frameIndex - 1];
+ var frameTime = frames[frameIndex];
+ var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*PREV_FRAME_TIME*/] - frameTime);
+ percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent);
+
+ r = prevFrameR + (frames[frameIndex + 1/*FRAME_R*/] - prevFrameR) * percent;
+ g = prevFrameG + (frames[frameIndex + 2/*FRAME_G*/] - prevFrameG) * percent;
+ b = prevFrameB + (frames[frameIndex + 3/*FRAME_B*/] - prevFrameB) * percent;
+ a = prevFrameA + (frames[frameIndex + 4/*FRAME_A*/] - prevFrameA) * percent;
+ }
+ var slot = skeleton.slots[this.slotIndex];
+ if (alpha < 1) {
+ slot.r += (r - slot.r) * alpha;
+ slot.g += (g - slot.g) * alpha;
+ slot.b += (b - slot.b) * alpha;
+ slot.a += (a - slot.a) * alpha;
+ } else {
+ slot.r = r;
+ slot.g = g;
+ slot.b = b;
+ slot.a = a;
+ }
+ }
+};
+
+spine.AttachmentTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, ...
+ this.frames.length = frameCount;
+ this.attachmentNames = [];
+ this.attachmentNames.length = frameCount;
+};
+spine.AttachmentTimeline.prototype = {
+ slotIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length;
+ },
+ setFrame: function (frameIndex, time, attachmentName) {
+ this.frames[frameIndex] = time;
+ this.attachmentNames[frameIndex] = attachmentName;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) {
+ if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0);
+ return;
+ } else if (lastTime > time) //
+ lastTime = -1;
+
+ var frameIndex = time >= frames[frames.length - 1] ? frames.length - 1 : spine.Animation.binarySearch1(frames, time) - 1;
+ if (frames[frameIndex] < lastTime) return;
+
+ var attachmentName = this.attachmentNames[frameIndex];
+ skeleton.slots[this.slotIndex].setAttachment(
+ !attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName));
+ }
+};
+
+spine.EventTimeline = function (frameCount) {
+ this.frames = []; // time, ...
+ this.frames.length = frameCount;
+ this.events = [];
+ this.events.length = frameCount;
+};
+spine.EventTimeline.prototype = {
+ getFrameCount: function () {
+ return this.frames.length;
+ },
+ setFrame: function (frameIndex, time, event) {
+ this.frames[frameIndex] = time;
+ this.events[frameIndex] = event;
+ },
+ /** Fires events for frames > lastTime and <= time. */
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ if (!firedEvents) return;
+
+ var frames = this.frames;
+ var frameCount = frames.length;
+
+ if (lastTime > time) { // Fire events after last time for looped animations.
+ this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha);
+ lastTime = -1;
+ } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame.
+ return;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var frameIndex;
+ if (lastTime < frames[0])
+ frameIndex = 0;
+ else {
+ frameIndex = spine.Animation.binarySearch1(frames, lastTime);
+ var frame = frames[frameIndex];
+ while (frameIndex > 0) { // Fire multiple events with the same frame.
+ if (frames[frameIndex - 1] != frame) break;
+ frameIndex--;
+ }
+ }
+ var events = this.events;
+ for (; frameIndex < frameCount && time >= frames[frameIndex]; frameIndex++)
+ firedEvents.push(events[frameIndex]);
+ }
+};
+
+spine.DrawOrderTimeline = function (frameCount) {
+ this.frames = []; // time, ...
+ this.frames.length = frameCount;
+ this.drawOrders = [];
+ this.drawOrders.length = frameCount;
+};
+spine.DrawOrderTimeline.prototype = {
+ getFrameCount: function () {
+ return this.frames.length;
+ },
+ setFrame: function (frameIndex, time, drawOrder) {
+ this.frames[frameIndex] = time;
+ this.drawOrders[frameIndex] = drawOrder;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var frameIndex;
+ if (time >= frames[frames.length - 1]) // Time is after last frame.
+ frameIndex = frames.length - 1;
+ else
+ frameIndex = spine.Animation.binarySearch1(frames, time) - 1;
+
+ var drawOrder = skeleton.drawOrder;
+ var slots = skeleton.slots;
+ var drawOrderToSetupIndex = this.drawOrders[frameIndex];
+ if (!drawOrderToSetupIndex) {
+ for (var i = 0, n = slots.length; i < n; i++)
+ drawOrder[i] = slots[i];
+ } else {
+ for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
+ drawOrder[i] = skeleton.slots[drawOrderToSetupIndex[i]];
+ }
+
+ }
+};
+
+spine.FfdTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = [];
+ this.frames.length = frameCount;
+ this.frameVertices = [];
+ this.frameVertices.length = frameCount;
+};
+spine.FfdTimeline.prototype = {
+ slotIndex: 0,
+ attachment: 0,
+ getFrameCount: function () {
+ return this.frames.length;
+ },
+ setFrame: function (frameIndex, time, vertices) {
+ this.frames[frameIndex] = time;
+ this.frameVertices[frameIndex] = vertices;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var slot = skeleton.slots[this.slotIndex];
+ if (slot.attachment != this.attachment) return;
+
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var frameVertices = this.frameVertices;
+ var vertexCount = frameVertices[0].length;
+
+ var vertices = slot.attachmentVertices;
+ if (vertices.length != vertexCount) alpha = 1;
+ vertices.length = vertexCount;
+
+ if (time >= frames[frames.length - 1]) { // Time is after last frame.
+ var lastVertices = frameVertices[frames.length - 1];
+ if (alpha < 1) {
+ for (var i = 0; i < vertexCount; i++)
+ vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
+ } else {
+ for (var i = 0; i < vertexCount; i++)
+ vertices[i] = lastVertices[i];
+ }
+ return;
+ }
+
+ // Interpolate between the previous frame and the current frame.
+ var frameIndex = spine.Animation.binarySearch1(frames, time);
+ var frameTime = frames[frameIndex];
+ var percent = 1 - (time - frameTime) / (frames[frameIndex - 1] - frameTime);
+ percent = this.curves.getCurvePercent(frameIndex - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
+
+ var prevVertices = frameVertices[frameIndex - 1];
+ var nextVertices = frameVertices[frameIndex];
+
+ if (alpha < 1) {
+ for (var i = 0; i < vertexCount; i++) {
+ var prev = prevVertices[i];
+ vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
+ }
+ } else {
+ for (var i = 0; i < vertexCount; i++) {
+ var prev = prevVertices[i];
+ vertices[i] = prev + (nextVertices[i] - prev) * percent;
+ }
+ }
+ }
+};
+
+spine.IkConstraintTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, mix, bendDirection, ...
+ this.frames.length = frameCount * 3;
+};
+spine.IkConstraintTimeline.prototype = {
+ ikConstraintIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 3;
+ },
+ setFrame: function (frameIndex, time, mix, bendDirection) {
+ frameIndex *= 3;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = mix;
+ this.frames[frameIndex + 2] = bendDirection;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) return; // Time is before first frame.
+
+ var ikConstraint = skeleton.ikConstraints[this.ikConstraintIndex];
+
+ if (time >= frames[frames.length - 3]) { // Time is after last frame.
+ ikConstraint.mix += (frames[frames.length - 2] - ikConstraint.mix) * alpha;
+ ikConstraint.bendDirection = frames[frames.length - 1];
+ return;
+ }
+
+ // Interpolate between the previous frame and the current frame.
+ var frameIndex = spine.Animation.binarySearch(frames, time, 3);
+ var prevFrameMix = frames[frameIndex + -2/*PREV_FRAME_MIX*/];
+ var frameTime = frames[frameIndex];
+ var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime);
+ percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
+
+ var mix = prevFrameMix + (frames[frameIndex + 1/*FRAME_MIX*/] - prevFrameMix) * percent;
+ ikConstraint.mix += (mix - ikConstraint.mix) * alpha;
+ ikConstraint.bendDirection = frames[frameIndex + -1/*PREV_FRAME_BEND_DIRECTION*/];
+ }
+};
+
+spine.FlipXTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, flip, ...
+ this.frames.length = frameCount * 2;
+};
+spine.FlipXTimeline.prototype = {
+ boneIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 2;
+ },
+ setFrame: function (frameIndex, time, flip) {
+ frameIndex *= 2;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = flip ? 1 : 0;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) {
+ if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0);
+ return;
+ } else if (lastTime > time) //
+ lastTime = -1;
+ var frameIndex = (time >= frames[frames.length - 2] ? frames.length : spine.Animation.binarySearch(frames, time, 2)) - 2;
+ if (frames[frameIndex] < lastTime) return;
+ skeleton.bones[this.boneIndex].flipX = frames[frameIndex + 1] != 0;
+ }
+};
+
+spine.FlipYTimeline = function (frameCount) {
+ this.curves = new spine.Curves(frameCount);
+ this.frames = []; // time, flip, ...
+ this.frames.length = frameCount * 2;
+};
+spine.FlipYTimeline.prototype = {
+ boneIndex: 0,
+ getFrameCount: function () {
+ return this.frames.length / 2;
+ },
+ setFrame: function (frameIndex, time, flip) {
+ frameIndex *= 2;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + 1] = flip ? 1 : 0;
+ },
+ apply: function (skeleton, lastTime, time, firedEvents, alpha) {
+ var frames = this.frames;
+ if (time < frames[0]) {
+ if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0);
+ return;
+ } else if (lastTime > time) //
+ lastTime = -1;
+ var frameIndex = (time >= frames[frames.length - 2] ? frames.length : spine.Animation.binarySearch(frames, time, 2)) - 2;
+ if (frames[frameIndex] < lastTime) return;
+ skeleton.bones[this.boneIndex].flipY = frames[frameIndex + 1] != 0;
+ }
+};
+
+spine.SkeletonData = function () {
+ this.bones = [];
+ this.slots = [];
+ this.skins = [];
+ this.events = [];
+ this.animations = [];
+ this.ikConstraints = [];
+};
+spine.SkeletonData.prototype = {
+ name: null,
+ defaultSkin: null,
+ width: 0, height: 0,
+ version: null, hash: null,
+ /** @return May be null. */
+ findBone: function (boneName) {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ if (bones[i].name == boneName) return bones[i];
+ return null;
+ },
+ /** @return -1 if the bone was not found. */
+ findBoneIndex: function (boneName) {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ if (bones[i].name == boneName) return i;
+ return -1;
+ },
+ /** @return May be null. */
+ findSlot: function (slotName) {
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ if (slots[i].name == slotName) return slot[i];
+ }
+ return null;
+ },
+ /** @return -1 if the bone was not found. */
+ findSlotIndex: function (slotName) {
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++)
+ if (slots[i].name == slotName) return i;
+ return -1;
+ },
+ /** @return May be null. */
+ findSkin: function (skinName) {
+ var skins = this.skins;
+ for (var i = 0, n = skins.length; i < n; i++)
+ if (skins[i].name == skinName) return skins[i];
+ return null;
+ },
+ /** @return May be null. */
+ findEvent: function (eventName) {
+ var events = this.events;
+ for (var i = 0, n = events.length; i < n; i++)
+ if (events[i].name == eventName) return events[i];
+ return null;
+ },
+ /** @return May be null. */
+ findAnimation: function (animationName) {
+ var animations = this.animations;
+ for (var i = 0, n = animations.length; i < n; i++)
+ if (animations[i].name == animationName) return animations[i];
+ return null;
+ },
+ /** @return May be null. */
+ findIkConstraint: function (ikConstraintName) {
+ var ikConstraints = this.ikConstraints;
+ for (var i = 0, n = ikConstraints.length; i < n; i++)
+ if (ikConstraints[i].name == ikConstraintName) return ikConstraints[i];
+ return null;
+ }
+};
+
+spine.Skeleton = function (skeletonData) {
+ this.data = skeletonData;
+
+ this.bones = [];
+ for (var i = 0, n = skeletonData.bones.length; i < n; i++) {
+ var boneData = skeletonData.bones[i];
+ var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)];
+ this.bones.push(new spine.Bone(boneData, this, parent));
+ }
+
+ this.slots = [];
+ this.drawOrder = [];
+ for (var i = 0, n = skeletonData.slots.length; i < n; i++) {
+ var slotData = skeletonData.slots[i];
+ var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)];
+ var slot = new spine.Slot(slotData, bone);
+ this.slots.push(slot);
+ this.drawOrder.push(slot);
+ }
+
+ this.ikConstraints = [];
+ for (var i = 0, n = skeletonData.ikConstraints.length; i < n; i++)
+ this.ikConstraints.push(new spine.IkConstraint(skeletonData.ikConstraints[i], this));
+
+ this.boneCache = [];
+ this.updateCache();
+};
+spine.Skeleton.prototype = {
+ x: 0, y: 0,
+ skin: null,
+ r: 1, g: 1, b: 1, a: 1,
+ time: 0,
+ flipX: false, flipY: false,
+ /** Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or removed. */
+ updateCache: function () {
+ var ikConstraints = this.ikConstraints;
+ var ikConstraintsCount = ikConstraints.length;
+
+ var arrayCount = ikConstraintsCount + 1;
+ var boneCache = this.boneCache;
+ if (boneCache.length > arrayCount) boneCache.length = arrayCount;
+ for (var i = 0, n = boneCache.length; i < n; i++)
+ boneCache[i].length = 0;
+ while (boneCache.length < arrayCount)
+ boneCache[boneCache.length] = [];
+
+ var nonIkBones = boneCache[0];
+ var bones = this.bones;
+
+ outer:
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ var current = bone;
+ do {
+ for (var ii = 0; ii < ikConstraintsCount; ii++) {
+ var ikConstraint = ikConstraints[ii];
+ var parent = ikConstraint.bones[0];
+ var child= ikConstraint.bones[ikConstraint.bones.length - 1];
+ while (true) {
+ if (current == child) {
+ boneCache[ii].push(bone);
+ boneCache[ii + 1].push(bone);
+ continue outer;
+ }
+ if (child == parent) break;
+ child = child.parent;
+ }
+ }
+ current = current.parent;
+ } while (current);
+ nonIkBones[nonIkBones.length] = bone;
+ }
+ },
+ /** Updates the world transform for each bone. */
+ updateWorldTransform: function () {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ bone.rotationIK = bone.rotation;
+ }
+ var i = 0, last = this.boneCache.length - 1;
+ while (true) {
+ var cacheBones = this.boneCache[i];
+ for (var ii = 0, nn = cacheBones.length; ii < nn; ii++)
+ cacheBones[ii].updateWorldTransform();
+ if (i == last) break;
+ this.ikConstraints[i].apply();
+ i++;
+ }
+ },
+ /** Sets the bones and slots to their setup pose values. */
+ setToSetupPose: function () {
+ this.setBonesToSetupPose();
+ this.setSlotsToSetupPose();
+ },
+ setBonesToSetupPose: function () {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ bones[i].setToSetupPose();
+
+ var ikConstraints = this.ikConstraints;
+ for (var i = 0, n = ikConstraints.length; i < n; i++) {
+ var ikConstraint = ikConstraints[i];
+ ikConstraint.bendDirection = ikConstraint.data.bendDirection;
+ ikConstraint.mix = ikConstraint.data.mix;
+ }
+ },
+ setSlotsToSetupPose: function () {
+ var slots = this.slots;
+ var drawOrder = this.drawOrder;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ drawOrder[i] = slots[i];
+ slots[i].setToSetupPose(i);
+ }
+ },
+ /** @return May return null. */
+ getRootBone: function () {
+ return this.bones.length ? this.bones[0] : null;
+ },
+ /** @return May be null. */
+ findBone: function (boneName) {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ if (bones[i].data.name == boneName) return bones[i];
+ return null;
+ },
+ /** @return -1 if the bone was not found. */
+ findBoneIndex: function (boneName) {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ if (bones[i].data.name == boneName) return i;
+ return -1;
+ },
+ /** @return May be null. */
+ findSlot: function (slotName) {
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++)
+ if (slots[i].data.name == slotName) return slots[i];
+ return null;
+ },
+ /** @return -1 if the bone was not found. */
+ findSlotIndex: function (slotName) {
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++)
+ if (slots[i].data.name == slotName) return i;
+ return -1;
+ },
+ setSkinByName: function (skinName) {
+ var skin = this.data.findSkin(skinName);
+ if (!skin) throw "Skin not found: " + skinName;
+ this.setSkin(skin);
+ },
+ /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}.
+ * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was
+ * no old skin, each slot's setup mode attachment is attached from the new skin.
+ * @param newSkin May be null. */
+ setSkin: function (newSkin) {
+ if (newSkin) {
+ if (this.skin)
+ 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 = slot.data.attachmentName;
+ if (name) {
+ var attachment = newSkin.getAttachment(i, name);
+ if (attachment) slot.setAttachment(attachment);
+ }
+ }
+ }
+ }
+ this.skin = newSkin;
+ },
+ /** @return May be null. */
+ getAttachmentBySlotName: function (slotName, attachmentName) {
+ return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName);
+ },
+ /** @return May be null. */
+ getAttachmentBySlotIndex: function (slotIndex, attachmentName) {
+ if (this.skin) {
+ var attachment = this.skin.getAttachment(slotIndex, attachmentName);
+ if (attachment) return attachment;
+ }
+ if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
+ return null;
+ },
+ /** @param attachmentName May be null. */
+ setAttachment: function (slotName, attachmentName) {
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ var slot = slots[i];
+ if (slot.data.name == slotName) {
+ var attachment = null;
+ if (attachmentName) {
+ attachment = this.getAttachmentBySlotIndex(i, attachmentName);
+ if (!attachment) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName;
+ }
+ slot.setAttachment(attachment);
+ return;
+ }
+ }
+ throw "Slot not found: " + slotName;
+ },
+ /** @return May be null. */
+ findIkConstraint: function (ikConstraintName) {
+ var ikConstraints = this.ikConstraints;
+ for (var i = 0, n = ikConstraints.length; i < n; i++)
+ if (ikConstraints[i].data.name == ikConstraintName) return ikConstraints[i];
+ return null;
+ },
+ update: function (delta) {
+ this.time += delta;
+ }
+};
+
+spine.EventData = function (name) {
+ this.name = name;
+};
+spine.EventData.prototype = {
+ intValue: 0,
+ floatValue: 0,
+ stringValue: null
+};
+
+spine.Event = function (data) {
+ this.data = data;
+};
+spine.Event.prototype = {
+ intValue: 0,
+ floatValue: 0,
+ stringValue: null
+};
+
+spine.AttachmentType = {
+ region: 0,
+ boundingbox: 1,
+ mesh: 2,
+ skinnedmesh: 3
+};
+
+spine.RegionAttachment = function (name) {
+ this.name = name;
+ this.offset = [];
+ this.offset.length = 8;
+ this.uvs = [];
+ this.uvs.length = 8;
+};
+spine.RegionAttachment.prototype = {
+ type: spine.AttachmentType.region,
+ x: 0, y: 0,
+ rotation: 0,
+ scaleX: 1, scaleY: 1,
+ width: 0, height: 0,
+ r: 1, g: 1, b: 1, a: 1,
+ path: null,
+ rendererObject: null,
+ regionOffsetX: 0, regionOffsetY: 0,
+ regionWidth: 0, regionHeight: 0,
+ regionOriginalWidth: 0, regionOriginalHeight: 0,
+ setUVs: function (u, v, u2, v2, rotate) {
+ var uvs = this.uvs;
+ if (rotate) {
+ uvs[2/*X2*/] = u;
+ uvs[3/*Y2*/] = v2;
+ uvs[4/*X3*/] = u;
+ uvs[5/*Y3*/] = v;
+ uvs[6/*X4*/] = u2;
+ uvs[7/*Y4*/] = v;
+ uvs[0/*X1*/] = u2;
+ uvs[1/*Y1*/] = v2;
+ } else {
+ uvs[0/*X1*/] = u;
+ uvs[1/*Y1*/] = v2;
+ uvs[2/*X2*/] = u;
+ uvs[3/*Y2*/] = v;
+ uvs[4/*X3*/] = u2;
+ uvs[5/*Y3*/] = v;
+ uvs[6/*X4*/] = u2;
+ uvs[7/*Y4*/] = v2;
+ }
+ },
+ updateOffset: function () {
+ var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX;
+ var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY;
+ var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX;
+ var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY;
+ var localX2 = localX + this.regionWidth * regionScaleX;
+ var localY2 = localY + this.regionHeight * regionScaleY;
+ var radians = this.rotation * spine.degRad;
+ var cos = Math.cos(radians);
+ var sin = Math.sin(radians);
+ var localXCos = localX * cos + this.x;
+ var localXSin = localX * sin;
+ var localYCos = localY * cos + this.y;
+ var localYSin = localY * sin;
+ var localX2Cos = localX2 * cos + this.x;
+ var localX2Sin = localX2 * sin;
+ var localY2Cos = localY2 * cos + this.y;
+ var localY2Sin = localY2 * sin;
+ var offset = this.offset;
+ offset[0/*X1*/] = localXCos - localYSin;
+ offset[1/*Y1*/] = localYCos + localXSin;
+ offset[2/*X2*/] = localXCos - localY2Sin;
+ offset[3/*Y2*/] = localY2Cos + localXSin;
+ offset[4/*X3*/] = localX2Cos - localY2Sin;
+ offset[5/*Y3*/] = localY2Cos + localX2Sin;
+ offset[6/*X4*/] = localX2Cos - localYSin;
+ offset[7/*Y4*/] = localYCos + localX2Sin;
+ },
+ computeVertices: function (x, y, bone, vertices) {
+ x += bone.worldX;
+ y += bone.worldY;
+ var m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
+ var offset = this.offset;
+ vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x;
+ vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y;
+ vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x;
+ vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y;
+ vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x;
+ vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y;
+ vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x;
+ vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y;
+ }
+};
+
+spine.MeshAttachment = function (name) {
+ this.name = name;
+};
+spine.MeshAttachment.prototype = {
+ type: spine.AttachmentType.mesh,
+ vertices: null,
+ uvs: null,
+ regionUVs: null,
+ triangles: null,
+ hullLength: 0,
+ r: 1, g: 1, b: 1, a: 1,
+ path: null,
+ rendererObject: null,
+ regionU: 0, regionV: 0, regionU2: 0, regionV2: 0, regionRotate: false,
+ regionOffsetX: 0, regionOffsetY: 0,
+ regionWidth: 0, regionHeight: 0,
+ regionOriginalWidth: 0, regionOriginalHeight: 0,
+ edges: null,
+ width: 0, height: 0,
+ updateUVs: function () {
+ var width = this.regionU2 - this.regionU, height = this.regionV2 - this.regionV;
+ var n = this.regionUVs.length;
+ if (!this.uvs || this.uvs.length != n) {
+ this.uvs = new spine.Float32Array(n);
+ }
+ if (this.regionRotate) {
+ for (var i = 0; i < n; i += 2) {
+ this.uvs[i] = this.regionU + this.regionUVs[i + 1] * width;
+ this.uvs[i + 1] = this.regionV + height - this.regionUVs[i] * height;
+ }
+ } else {
+ for (var i = 0; i < n; i += 2) {
+ this.uvs[i] = this.regionU + this.regionUVs[i] * width;
+ this.uvs[i + 1] = this.regionV + this.regionUVs[i + 1] * height;
+ }
+ }
+ },
+ computeWorldVertices: function (x, y, slot, worldVertices) {
+ var bone = slot.bone;
+ x += bone.worldX;
+ y += bone.worldY;
+ var m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
+ var vertices = this.vertices;
+ var verticesCount = vertices.length;
+ if (slot.attachmentVertices.length == verticesCount) vertices = slot.attachmentVertices;
+ for (var i = 0; i < verticesCount; i += 2) {
+ var vx = vertices[i];
+ var vy = vertices[i + 1];
+ worldVertices[i] = vx * m00 + vy * m01 + x;
+ worldVertices[i + 1] = vx * m10 + vy * m11 + y;
+ }
+ }
+};
+
+spine.SkinnedMeshAttachment = function (name) {
+ this.name = name;
+};
+spine.SkinnedMeshAttachment.prototype = {
+ type: spine.AttachmentType.skinnedmesh,
+ bones: null,
+ weights: null,
+ uvs: null,
+ regionUVs: null,
+ triangles: null,
+ hullLength: 0,
+ r: 1, g: 1, b: 1, a: 1,
+ path: null,
+ rendererObject: null,
+ regionU: 0, regionV: 0, regionU2: 0, regionV2: 0, regionRotate: false,
+ regionOffsetX: 0, regionOffsetY: 0,
+ regionWidth: 0, regionHeight: 0,
+ regionOriginalWidth: 0, regionOriginalHeight: 0,
+ edges: null,
+ width: 0, height: 0,
+ updateUVs: function (u, v, u2, v2, rotate) {
+ var width = this.regionU2 - this.regionU, height = this.regionV2 - this.regionV;
+ var n = this.regionUVs.length;
+ if (!this.uvs || this.uvs.length != n) {
+ this.uvs = new spine.Float32Array(n);
+ }
+ if (this.regionRotate) {
+ for (var i = 0; i < n; i += 2) {
+ this.uvs[i] = this.regionU + this.regionUVs[i + 1] * width;
+ this.uvs[i + 1] = this.regionV + height - this.regionUVs[i] * height;
+ }
+ } else {
+ for (var i = 0; i < n; i += 2) {
+ this.uvs[i] = this.regionU + this.regionUVs[i] * width;
+ this.uvs[i + 1] = this.regionV + this.regionUVs[i + 1] * height;
+ }
+ }
+ },
+ computeWorldVertices: function (x, y, slot, worldVertices) {
+ var skeletonBones = slot.bone.skeleton.bones;
+ var weights = this.weights;
+ var bones = this.bones;
+
+ var w = 0, v = 0, b = 0, f = 0, n = bones.length, nn;
+ var wx, wy, bone, vx, vy, weight;
+ if (!slot.attachmentVertices.length) {
+ for (; v < n; w += 2) {
+ wx = 0;
+ wy = 0;
+ nn = bones[v++] + v;
+ for (; v < nn; v++, b += 3) {
+ bone = skeletonBones[bones[v]];
+ vx = weights[b];
+ vy = weights[b + 1];
+ weight = weights[b + 2];
+ wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight;
+ wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight;
+ }
+ worldVertices[w] = wx + x;
+ worldVertices[w + 1] = wy + y;
+ }
+ } else {
+ var ffd = slot.attachmentVertices;
+ for (; v < n; w += 2) {
+ wx = 0;
+ wy = 0;
+ nn = bones[v++] + v;
+ for (; v < nn; v++, b += 3, f += 2) {
+ bone = skeletonBones[bones[v]];
+ vx = weights[b] + ffd[f];
+ vy = weights[b + 1] + ffd[f + 1];
+ weight = weights[b + 2];
+ wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight;
+ wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight;
+ }
+ worldVertices[w] = wx + x;
+ worldVertices[w + 1] = wy + y;
+ }
+ }
+ }
+};
+
+spine.BoundingBoxAttachment = function (name) {
+ this.name = name;
+ this.vertices = [];
+};
+spine.BoundingBoxAttachment.prototype = {
+ type: spine.AttachmentType.boundingbox,
+ computeWorldVertices: function (x, y, bone, worldVertices) {
+ x += bone.worldX;
+ y += bone.worldY;
+ var m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
+ var vertices = this.vertices;
+ for (var i = 0, n = vertices.length; i < n; i += 2) {
+ var px = vertices[i];
+ var py = vertices[i + 1];
+ worldVertices[i] = px * m00 + py * m01 + x;
+ worldVertices[i + 1] = px * m10 + py * m11 + y;
+ }
+ }
+};
+
+spine.AnimationStateData = function (skeletonData) {
+ this.skeletonData = skeletonData;
+ this.animationToMixTime = {};
+};
+spine.AnimationStateData.prototype = {
+ defaultMix: 0,
+ setMixByName: function (fromName, toName, duration) {
+ var from = this.skeletonData.findAnimation(fromName);
+ if (!from) throw "Animation not found: " + fromName;
+ var to = this.skeletonData.findAnimation(toName);
+ if (!to) throw "Animation not found: " + toName;
+ this.setMix(from, to, duration);
+ },
+ setMix: function (from, to, duration) {
+ this.animationToMixTime[from.name + ":" + to.name] = duration;
+ },
+ getMix: function (from, to) {
+ var key = from.name + ":" + to.name;
+ return this.animationToMixTime.hasOwnProperty(key) ? this.animationToMixTime[key] : this.defaultMix;
+ }
+};
+
+spine.TrackEntry = function () {};
+spine.TrackEntry.prototype = {
+ next: null, previous: null,
+ animation: null,
+ loop: false,
+ delay: 0, time: 0, lastTime: -1, endTime: 0,
+ timeScale: 1,
+ mixTime: 0, mixDuration: 0, mix: 1,
+ onStart: null, onEnd: null, onComplete: null, onEvent: null
+};
+
+spine.AnimationState = function (stateData) {
+ this.data = stateData;
+ this.tracks = [];
+ this.events = [];
+};
+spine.AnimationState.prototype = {
+ onStart: null,
+ onEnd: null,
+ onComplete: null,
+ onEvent: null,
+ timeScale: 1,
+ update: function (delta) {
+ delta *= this.timeScale;
+ for (var i = 0; i < this.tracks.length; i++) {
+ var current = this.tracks[i];
+ if (!current) continue;
+
+ current.time += delta * current.timeScale;
+ if (current.previous) {
+ var previousDelta = delta * current.previous.timeScale;
+ current.previous.time += previousDelta;
+ current.mixTime += previousDelta;
+ }
+
+ var next = current.next;
+ if (next) {
+ next.time = current.lastTime - next.delay;
+ if (next.time >= 0) this.setCurrent(i, next);
+ } else {
+ // End non-looping animation when it reaches its end time and there is no next entry.
+ if (!current.loop && current.lastTime >= current.endTime) this.clearTrack(i);
+ }
+ }
+ },
+ apply: function (skeleton) {
+ for (var i = 0; i < this.tracks.length; i++) {
+ var current = this.tracks[i];
+ if (!current) continue;
+
+ this.events.length = 0;
+
+ var time = current.time;
+ var lastTime = current.lastTime;
+ var endTime = current.endTime;
+ var loop = current.loop;
+ if (!loop && time > endTime) time = endTime;
+
+ var previous = current.previous;
+ if (!previous) {
+ if (current.mix == 1)
+ current.animation.apply(skeleton, current.lastTime, time, loop, this.events);
+ else
+ current.animation.mix(skeleton, current.lastTime, time, loop, this.events, current.mix);
+ } else {
+ var previousTime = previous.time;
+ if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
+ previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
+
+ var alpha = current.mixTime / current.mixDuration * current.mix;
+ if (alpha >= 1) {
+ alpha = 1;
+ current.previous = null;
+ }
+ current.animation.mix(skeleton, current.lastTime, time, loop, this.events, alpha);
+ }
+
+ for (var ii = 0, nn = this.events.length; ii < nn; ii++) {
+ var event = this.events[ii];
+ if (current.onEvent) current.onEvent(i, event);
+ if (this.onEvent) this.onEvent(i, event);
+ }
+
+ // Check if completed the animation or a loop iteration.
+ if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
+ var count = Math.floor(time / endTime);
+ if (current.onComplete) current.onComplete(i, count);
+ if (this.onComplete) this.onComplete(i, count);
+ }
+
+ current.lastTime = current.time;
+ }
+ },
+ clearTracks: function () {
+ for (var i = 0, n = this.tracks.length; i < n; i++)
+ this.clearTrack(i);
+ this.tracks.length = 0;
+ },
+ clearTrack: function (trackIndex) {
+ if (trackIndex >= this.tracks.length) return;
+ var current = this.tracks[trackIndex];
+ if (!current) return;
+
+ if (current.onEnd) current.onEnd(trackIndex);
+ if (this.onEnd) this.onEnd(trackIndex);
+
+ this.tracks[trackIndex] = null;
+ },
+ _expandToIndex: function (index) {
+ if (index < this.tracks.length) return this.tracks[index];
+ while (index >= this.tracks.length)
+ this.tracks.push(null);
+ return null;
+ },
+ setCurrent: function (index, entry) {
+ var current = this._expandToIndex(index);
+ if (current) {
+ var previous = current.previous;
+ current.previous = null;
+
+ if (current.onEnd) current.onEnd(index);
+ if (this.onEnd) this.onEnd(index);
+
+ entry.mixDuration = this.data.getMix(current.animation, entry.animation);
+ if (entry.mixDuration > 0) {
+ entry.mixTime = 0;
+ // If a mix is in progress, mix from the closest animation.
+ if (previous && current.mixTime / current.mixDuration < 0.5)
+ entry.previous = previous;
+ else
+ entry.previous = current;
+ }
+ }
+
+ this.tracks[index] = entry;
+
+ if (entry.onStart) entry.onStart(index);
+ if (this.onStart) this.onStart(index);
+ },
+ setAnimationByName: function (trackIndex, animationName, loop) {
+ var animation = this.data.skeletonData.findAnimation(animationName);
+ if (!animation) throw "Animation not found: " + animationName;
+ return this.setAnimation(trackIndex, animation, loop);
+ },
+ /** Set the current animation. Any queued animations are cleared. */
+ setAnimation: function (trackIndex, animation, loop) {
+ var entry = new spine.TrackEntry();
+ entry.animation = animation;
+ entry.loop = loop;
+ entry.endTime = animation.duration;
+ this.setCurrent(trackIndex, entry);
+ return entry;
+ },
+ addAnimationByName: function (trackIndex, animationName, loop, delay) {
+ var animation = this.data.skeletonData.findAnimation(animationName);
+ if (!animation) throw "Animation not found: " + animationName;
+ return this.addAnimation(trackIndex, animation, loop, delay);
+ },
+ /** Adds an animation to be played delay seconds after the current or last queued animation.
+ * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
+ addAnimation: function (trackIndex, animation, loop, delay) {
+ var entry = new spine.TrackEntry();
+ entry.animation = animation;
+ entry.loop = loop;
+ entry.endTime = animation.duration;
+
+ var last = this._expandToIndex(trackIndex);
+ if (last) {
+ while (last.next)
+ last = last.next;
+ last.next = entry;
+ } else
+ this.tracks[trackIndex] = entry;
+
+ if (delay <= 0) {
+ if (last)
+ delay += last.endTime - this.data.getMix(last.animation, animation);
+ else
+ delay = 0;
+ }
+ entry.delay = delay;
+
+ return entry;
+ },
+ /** May be null. */
+ getCurrent: function (trackIndex) {
+ if (trackIndex >= this.tracks.length) return null;
+ return this.tracks[trackIndex];
+ }
+};
+
+spine.SkeletonJson = function (attachmentLoader) {
+ this.attachmentLoader = attachmentLoader;
+};
+spine.SkeletonJson.prototype = {
+ scale: 1,
+ readSkeletonData: function (root, name) {
+ var skeletonData = new spine.SkeletonData();
+ skeletonData.name = name;
+
+ // Skeleton.
+ var skeletonMap = root["skeleton"];
+ if (skeletonMap) {
+ skeletonData.hash = skeletonMap["hash"];
+ skeletonData.version = skeletonMap["spine"];
+ skeletonData.width = skeletonMap["width"] || 0;
+ skeletonData.height = skeletonMap["height"] || 0;
+ }
+
+ // Bones.
+ var bones = root["bones"];
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var boneMap = bones[i];
+ var parent = null;
+ if (boneMap["parent"]) {
+ parent = skeletonData.findBone(boneMap["parent"]);
+ if (!parent) throw "Parent bone not found: " + boneMap["parent"];
+ }
+ var boneData = new spine.BoneData(boneMap["name"], parent);
+ boneData.length = (boneMap["length"] || 0) * this.scale;
+ boneData.x = (boneMap["x"] || 0) * this.scale;
+ boneData.y = (boneMap["y"] || 0) * this.scale;
+ boneData.rotation = (boneMap["rotation"] || 0);
+ boneData.scaleX = boneMap.hasOwnProperty("scaleX") ? boneMap["scaleX"] : 1;
+ boneData.scaleY = boneMap.hasOwnProperty("scaleY") ? boneMap["scaleY"] : 1;
+ boneData.inheritScale = boneMap.hasOwnProperty("inheritScale") ? boneMap["inheritScale"] : true;
+ boneData.inheritRotation = boneMap.hasOwnProperty("inheritRotation") ? boneMap["inheritRotation"] : true;
+ skeletonData.bones.push(boneData);
+ }
+
+ // IK constraints.
+ var ik = root["ik"];
+ if (ik) {
+ for (var i = 0, n = ik.length; i < n; i++) {
+ var ikMap = ik[i];
+ var ikConstraintData = new spine.IkConstraintData(ikMap["name"]);
+
+ var bones = ikMap["bones"];
+ for (var ii = 0, nn = bones.length; ii < nn; ii++) {
+ var bone = skeletonData.findBone(bones[ii]);
+ if (!bone) throw "IK bone not found: " + bones[ii];
+ ikConstraintData.bones.push(bone);
+ }
+
+ ikConstraintData.target = skeletonData.findBone(ikMap["target"]);
+ if (!ikConstraintData.target) throw "Target bone not found: " + ikMap["target"];
+
+ ikConstraintData.bendDirection = (!ikMap.hasOwnProperty("bendPositive") || ikMap["bendPositive"]) ? 1 : -1;
+ ikConstraintData.mix = ikMap.hasOwnProperty("mix") ? ikMap["mix"] : 1;
+
+ skeletonData.ikConstraints.push(ikConstraintData);
+ }
+ }
+
+ // Slots.
+ var slots = root["slots"];
+ for (var i = 0, n = slots.length; i < n; i++) {
+ var slotMap = slots[i];
+ var boneData = skeletonData.findBone(slotMap["bone"]);
+ if (!boneData) throw "Slot bone not found: " + slotMap["bone"];
+ var slotData = new spine.SlotData(slotMap["name"], boneData);
+
+ var color = slotMap["color"];
+ if (color) {
+ slotData.r = this.toColor(color, 0);
+ slotData.g = this.toColor(color, 1);
+ slotData.b = this.toColor(color, 2);
+ slotData.a = this.toColor(color, 3);
+ }
+
+ slotData.attachmentName = slotMap["attachment"];
+ slotData.additiveBlending = slotMap["additive"] && slotMap["additive"] == "true";
+
+ skeletonData.slots.push(slotData);
+ }
+
+ // Skins.
+ var skins = root["skins"];
+ for (var skinName in skins) {
+ if (!skins.hasOwnProperty(skinName)) continue;
+ var skinMap = skins[skinName];
+ var skin = new spine.Skin(skinName);
+ for (var slotName in skinMap) {
+ if (!skinMap.hasOwnProperty(slotName)) continue;
+ var slotIndex = skeletonData.findSlotIndex(slotName);
+ var slotEntry = skinMap[slotName];
+ for (var attachmentName in slotEntry) {
+ if (!slotEntry.hasOwnProperty(attachmentName)) continue;
+ var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]);
+ if (attachment) skin.addAttachment(slotIndex, attachmentName, attachment);
+ }
+ }
+ skeletonData.skins.push(skin);
+ if (skin.name == "default") skeletonData.defaultSkin = skin;
+ }
+
+ // Events.
+ var events = root["events"];
+ for (var eventName in events) {
+ if (!events.hasOwnProperty(eventName)) continue;
+ var eventMap = events[eventName];
+ var eventData = new spine.EventData(eventName);
+ eventData.intValue = eventMap["int"] || 0;
+ eventData.floatValue = eventMap["float"] || 0;
+ eventData.stringValue = eventMap["string"] || null;
+ skeletonData.events.push(eventData);
+ }
+
+ // Animations.
+ var animations = root["animations"];
+ for (var animationName in animations) {
+ if (!animations.hasOwnProperty(animationName)) continue;
+ this.readAnimation(animationName, animations[animationName], skeletonData);
+ }
+
+ return skeletonData;
+ },
+ readAttachment: function (skin, name, map) {
+ name = map["name"] || name;
+
+ var type = spine.AttachmentType[map["type"] || "region"];
+ var path = map["path"] || name;
+
+ var scale = this.scale;
+ if (type == spine.AttachmentType.region) {
+ var region = this.attachmentLoader.newRegionAttachment(skin, name, path);
+ if (!region) return null;
+ region.path = path;
+ region.x = (map["x"] || 0) * scale;
+ region.y = (map["y"] || 0) * scale;
+ region.scaleX = map.hasOwnProperty("scaleX") ? map["scaleX"] : 1;
+ region.scaleY = map.hasOwnProperty("scaleY") ? map["scaleY"] : 1;
+ region.rotation = map["rotation"] || 0;
+ region.width = (map["width"] || 0) * scale;
+ region.height = (map["height"] || 0) * scale;
+
+ var color = map["color"];
+ if (color) {
+ region.r = this.toColor(color, 0);
+ region.g = this.toColor(color, 1);
+ region.b = this.toColor(color, 2);
+ region.a = this.toColor(color, 3);
+ }
+
+ region.updateOffset();
+ return region;
+ } else if (type == spine.AttachmentType.mesh) {
+ var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path);
+ if (!mesh) return null;
+ mesh.path = path;
+ mesh.vertices = this.getFloatArray(map, "vertices", scale);
+ mesh.triangles = this.getIntArray(map, "triangles");
+ mesh.regionUVs = this.getFloatArray(map, "uvs", 1);
+ mesh.updateUVs();
+
+ color = map["color"];
+ if (color) {
+ mesh.r = this.toColor(color, 0);
+ mesh.g = this.toColor(color, 1);
+ mesh.b = this.toColor(color, 2);
+ mesh.a = this.toColor(color, 3);
+ }
+
+ mesh.hullLength = (map["hull"] || 0) * 2;
+ if (map["edges"]) mesh.edges = this.getIntArray(map, "edges");
+ mesh.width = (map["width"] || 0) * scale;
+ mesh.height = (map["height"] || 0) * scale;
+ return mesh;
+ } else if (type == spine.AttachmentType.skinnedmesh) {
+ var mesh = this.attachmentLoader.newSkinnedMeshAttachment(skin, name, path);
+ if (!mesh) return null;
+ mesh.path = path;
+
+ var uvs = this.getFloatArray(map, "uvs", 1);
+ var vertices = this.getFloatArray(map, "vertices", 1);
+ var weights = [];
+ var bones = [];
+ for (var i = 0, n = vertices.length; i < n; ) {
+ var boneCount = vertices[i++] | 0;
+ bones[bones.length] = boneCount;
+ for (var nn = i + boneCount * 4; i < nn; ) {
+ bones[bones.length] = vertices[i];
+ weights[weights.length] = vertices[i + 1] * scale;
+ weights[weights.length] = vertices[i + 2] * scale;
+ weights[weights.length] = vertices[i + 3];
+ i += 4;
+ }
+ }
+ mesh.bones = bones;
+ mesh.weights = weights;
+ mesh.triangles = this.getIntArray(map, "triangles");
+ mesh.regionUVs = uvs;
+ mesh.updateUVs();
+
+ color = map["color"];
+ if (color) {
+ mesh.r = this.toColor(color, 0);
+ mesh.g = this.toColor(color, 1);
+ mesh.b = this.toColor(color, 2);
+ mesh.a = this.toColor(color, 3);
+ }
+
+ mesh.hullLength = (map["hull"] || 0) * 2;
+ if (map["edges"]) mesh.edges = this.getIntArray(map, "edges");
+ mesh.width = (map["width"] || 0) * scale;
+ mesh.height = (map["height"] || 0) * scale;
+ return mesh;
+ } else if (type == spine.AttachmentType.boundingbox) {
+ var attachment = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
+ var vertices = map["vertices"];
+ for (var i = 0, n = vertices.length; i < n; i++)
+ attachment.vertices.push(vertices[i] * scale);
+ return attachment;
+ }
+ throw "Unknown attachment type: " + type;
+ },
+ readAnimation: function (name, map, skeletonData) {
+ var timelines = [];
+ var duration = 0;
+
+ var slots = map["slots"];
+ for (var slotName in slots) {
+ if (!slots.hasOwnProperty(slotName)) continue;
+ var slotMap = slots[slotName];
+ var slotIndex = skeletonData.findSlotIndex(slotName);
+
+ for (var timelineName in slotMap) {
+ if (!slotMap.hasOwnProperty(timelineName)) continue;
+ var values = slotMap[timelineName];
+ if (timelineName == "color") {
+ var timeline = new spine.ColorTimeline(values.length);
+ timeline.slotIndex = slotIndex;
+
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ var color = valueMap["color"];
+ var r = this.toColor(color, 0);
+ var g = this.toColor(color, 1);
+ var b = this.toColor(color, 2);
+ var a = this.toColor(color, 3);
+ timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a);
+ this.readCurve(timeline, frameIndex, valueMap);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]);
+
+ } else if (timelineName == "attachment") {
+ var timeline = new spine.AttachmentTimeline(values.length);
+ timeline.slotIndex = slotIndex;
+
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]);
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+
+ } else
+ throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")";
+ }
+ }
+
+ var bones = map["bones"];
+ for (var boneName in bones) {
+ if (!bones.hasOwnProperty(boneName)) continue;
+ var boneIndex = skeletonData.findBoneIndex(boneName);
+ if (boneIndex == -1) throw "Bone not found: " + boneName;
+ var boneMap = bones[boneName];
+
+ for (var timelineName in boneMap) {
+ if (!boneMap.hasOwnProperty(timelineName)) continue;
+ var values = boneMap[timelineName];
+ if (timelineName == "rotate") {
+ var timeline = new spine.RotateTimeline(values.length);
+ timeline.boneIndex = boneIndex;
+
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]);
+ this.readCurve(timeline, frameIndex, valueMap);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]);
+
+ } else if (timelineName == "translate" || timelineName == "scale") {
+ var timeline;
+ var timelineScale = 1;
+ if (timelineName == "scale")
+ timeline = new spine.ScaleTimeline(values.length);
+ else {
+ timeline = new spine.TranslateTimeline(values.length);
+ timelineScale = this.scale;
+ }
+ timeline.boneIndex = boneIndex;
+
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ var x = (valueMap["x"] || 0) * timelineScale;
+ var y = (valueMap["y"] || 0) * timelineScale;
+ timeline.setFrame(frameIndex, valueMap["time"], x, y);
+ this.readCurve(timeline, frameIndex, valueMap);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]);
+
+ } else if (timelineName == "flipX" || timelineName == "flipY") {
+ var x = timelineName == "flipX";
+ var timeline = x ? new spine.FlipXTimeline(values.length) : new spine.FlipYTimeline(values.length);
+ timeline.boneIndex = boneIndex;
+
+ var field = x ? "x" : "y";
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ timeline.setFrame(frameIndex, valueMap["time"], valueMap[field] || false);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]);
+ } else
+ throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")";
+ }
+ }
+
+ var ikMap = map["ik"];
+ for (var ikConstraintName in ikMap) {
+ if (!ikMap.hasOwnProperty(ikConstraintName)) continue;
+ var ikConstraint = skeletonData.findIkConstraint(ikConstraintName);
+ var values = ikMap[ikConstraintName];
+ var timeline = new spine.IkConstraintTimeline(values.length);
+ timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(ikConstraint);
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ var mix = valueMap.hasOwnProperty("mix") ? valueMap["mix"] : 1;
+ var bendDirection = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1;
+ timeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection);
+ this.readCurve(timeline, frameIndex, valueMap);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.frameCount * 3 - 3]);
+ }
+
+ var ffd = map["ffd"];
+ for (var skinName in ffd) {
+ var skin = skeletonData.findSkin(skinName);
+ var slotMap = ffd[skinName];
+ for (slotName in slotMap) {
+ var slotIndex = skeletonData.findSlotIndex(slotName);
+ var meshMap = slotMap[slotName];
+ for (var meshName in meshMap) {
+ var values = meshMap[meshName];
+ var timeline = new spine.FfdTimeline(values.length);
+ var attachment = skin.getAttachment(slotIndex, meshName);
+ if (!attachment) throw "FFD attachment not found: " + meshName;
+ timeline.slotIndex = slotIndex;
+ timeline.attachment = attachment;
+
+ var isMesh = attachment.type == spine.AttachmentType.mesh;
+ var vertexCount;
+ if (isMesh)
+ vertexCount = attachment.vertices.length;
+ else
+ vertexCount = attachment.weights.length / 3 * 2;
+
+ var frameIndex = 0;
+ for (var i = 0, n = values.length; i < n; i++) {
+ var valueMap = values[i];
+ var vertices;
+ if (!valueMap["vertices"]) {
+ if (isMesh)
+ vertices = attachment.vertices;
+ else {
+ vertices = [];
+ vertices.length = vertexCount;
+ }
+ } else {
+ var verticesValue = valueMap["vertices"];
+ var vertices = [];
+ vertices.length = vertexCount;
+ var start = valueMap["offset"] || 0;
+ var nn = verticesValue.length;
+ if (this.scale == 1) {
+ for (var ii = 0; ii < nn; ii++)
+ vertices[ii + start] = verticesValue[ii];
+ } else {
+ for (var ii = 0; ii < nn; ii++)
+ vertices[ii + start] = verticesValue[ii] * this.scale;
+ }
+ if (isMesh) {
+ var meshVertices = attachment.vertices;
+ for (var ii = 0, nn = vertices.length; ii < nn; ii++)
+ vertices[ii] += meshVertices[ii];
+ }
+ }
+
+ timeline.setFrame(frameIndex, valueMap["time"], vertices);
+ this.readCurve(timeline, frameIndex, valueMap);
+ frameIndex++;
+ }
+ timelines[timelines.length] = timeline;
+ duration = Math.max(duration, timeline.frames[timeline.frameCount - 1]);
+ }
+ }
+ }
+
+ var drawOrderValues = map["drawOrder"];
+ if (!drawOrderValues) drawOrderValues = map["draworder"];
+ if (drawOrderValues) {
+ var timeline = new spine.DrawOrderTimeline(drawOrderValues.length);
+ var slotCount = skeletonData.slots.length;
+ var frameIndex = 0;
+ for (var i = 0, n = drawOrderValues.length; i < n; i++) {
+ var drawOrderMap = drawOrderValues[i];
+ var drawOrder = null;
+ if (drawOrderMap["offsets"]) {
+ drawOrder = [];
+ drawOrder.length = slotCount;
+ for (var ii = slotCount - 1; ii >= 0; ii--)
+ drawOrder[ii] = -1;
+ var offsets = drawOrderMap["offsets"];
+ var unchanged = [];
+ unchanged.length = slotCount - offsets.length;
+ var originalIndex = 0, unchangedIndex = 0;
+ for (var ii = 0, nn = offsets.length; ii < nn; ii++) {
+ var offsetMap = offsets[ii];
+ var slotIndex = skeletonData.findSlotIndex(offsetMap["slot"]);
+ if (slotIndex == -1) throw "Slot not found: " + offsetMap["slot"];
+ // Collect unchanged items.
+ while (originalIndex != slotIndex)
+ unchanged[unchangedIndex++] = originalIndex++;
+ // Set changed items.
+ drawOrder[originalIndex + offsetMap["offset"]] = originalIndex++;
+ }
+ // Collect remaining unchanged items.
+ while (originalIndex < slotCount)
+ unchanged[unchangedIndex++] = originalIndex++;
+ // Fill in unchanged items.
+ for (var ii = slotCount - 1; ii >= 0; ii--)
+ if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
+ }
+ timeline.setFrame(frameIndex++, drawOrderMap["time"], drawOrder);
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+ }
+
+ var events = map["events"];
+ if (events) {
+ var timeline = new spine.EventTimeline(events.length);
+ var frameIndex = 0;
+ for (var i = 0, n = events.length; i < n; i++) {
+ var eventMap = events[i];
+ var eventData = skeletonData.findEvent(eventMap["name"]);
+ if (!eventData) throw "Event not found: " + eventMap["name"];
+ var event = new spine.Event(eventData);
+ event.intValue = eventMap.hasOwnProperty("int") ? eventMap["int"] : eventData.intValue;
+ event.floatValue = eventMap.hasOwnProperty("float") ? eventMap["float"] : eventData.floatValue;
+ event.stringValue = eventMap.hasOwnProperty("string") ? eventMap["string"] : eventData.stringValue;
+ timeline.setFrame(frameIndex++, eventMap["time"], event);
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+ }
+
+ skeletonData.animations.push(new spine.Animation(name, timelines, duration));
+ },
+ readCurve: function (timeline, frameIndex, valueMap) {
+ var curve = valueMap["curve"];
+ if (!curve)
+ timeline.curves.setLinear(frameIndex);
+ else if (curve == "stepped")
+ timeline.curves.setStepped(frameIndex);
+ else if (curve instanceof Array)
+ timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]);
+ },
+ toColor: function (hexString, colorIndex) {
+ if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString;
+ return parseInt(hexString.substring(colorIndex * 2, (colorIndex * 2) + 2), 16) / 255;
+ },
+ getFloatArray: function (map, name, scale) {
+ var list = map[name];
+ var values = new spine.Float32Array(list.length);
+ var i = 0, n = list.length;
+ if (scale == 1) {
+ for (; i < n; i++)
+ values[i] = list[i];
+ } else {
+ for (; i < n; i++)
+ values[i] = list[i] * scale;
+ }
+ return values;
+ },
+ getIntArray: function (map, name) {
+ var list = map[name];
+ var values = new spine.Uint16Array(list.length);
+ for (var i = 0, n = list.length; i < n; i++)
+ values[i] = list[i] | 0;
+ return values;
+ }
+};
+
+spine.Atlas = function (atlasText, textureLoader) {
+ this.textureLoader = textureLoader;
+ this.pages = [];
+ this.regions = [];
+
+ var reader = new spine.AtlasReader(atlasText);
+ var tuple = [];
+ tuple.length = 4;
+ var page = null;
+ while (true) {
+ var line = reader.readLine();
+ if (line === null) break;
+ line = reader.trim(line);
+ if (!line.length)
+ page = null;
+ else if (!page) {
+ page = new spine.AtlasPage();
+ page.name = line;
+
+ if (reader.readTuple(tuple) == 2) { // size is only optional for an atlas packed with an old TexturePacker.
+ page.width = parseInt(tuple[0]);
+ page.height = parseInt(tuple[1]);
+ reader.readTuple(tuple);
+ }
+ page.format = spine.Atlas.Format[tuple[0]];
+
+ reader.readTuple(tuple);
+ page.minFilter = spine.Atlas.TextureFilter[tuple[0]];
+ page.magFilter = spine.Atlas.TextureFilter[tuple[1]];
+
+ var direction = reader.readValue();
+ page.uWrap = spine.Atlas.TextureWrap.clampToEdge;
+ page.vWrap = spine.Atlas.TextureWrap.clampToEdge;
+ if (direction == "x")
+ page.uWrap = spine.Atlas.TextureWrap.repeat;
+ else if (direction == "y")
+ page.vWrap = spine.Atlas.TextureWrap.repeat;
+ else if (direction == "xy")
+ page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat;
+
+ textureLoader.load(page, line, this);
+
+ this.pages.push(page);
+
+ } else {
+ var region = new spine.AtlasRegion();
+ region.name = line;
+ region.page = page;
+
+ region.rotate = reader.readValue() == "true";
+
+ reader.readTuple(tuple);
+ var x = parseInt(tuple[0]);
+ var y = parseInt(tuple[1]);
+
+ reader.readTuple(tuple);
+ var width = parseInt(tuple[0]);
+ var height = parseInt(tuple[1]);
+
+ region.u = x / page.width;
+ region.v = y / page.height;
+ if (region.rotate) {
+ region.u2 = (x + height) / page.width;
+ region.v2 = (y + width) / page.height;
+ } else {
+ region.u2 = (x + width) / page.width;
+ region.v2 = (y + height) / page.height;
+ }
+ region.x = x;
+ region.y = y;
+ region.width = Math.abs(width);
+ region.height = Math.abs(height);
+
+ if (reader.readTuple(tuple) == 4) { // split is optional
+ region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
+
+ if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits
+ region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
+
+ reader.readTuple(tuple);
+ }
+ }
+
+ region.originalWidth = parseInt(tuple[0]);
+ region.originalHeight = parseInt(tuple[1]);
+
+ reader.readTuple(tuple);
+ region.offsetX = parseInt(tuple[0]);
+ region.offsetY = parseInt(tuple[1]);
+
+ region.index = parseInt(reader.readValue());
+
+ this.regions.push(region);
+ }
+ }
+};
+spine.Atlas.prototype = {
+ findRegion: function (name) {
+ var regions = this.regions;
+ for (var i = 0, n = regions.length; i < n; i++)
+ if (regions[i].name == name) return regions[i];
+ return null;
+ },
+ dispose: function () {
+ var pages = this.pages;
+ for (var i = 0, n = pages.length; i < n; i++)
+ this.textureLoader.unload(pages[i].rendererObject);
+ },
+ updateUVs: function (page) {
+ var regions = this.regions;
+ for (var i = 0, n = regions.length; i < n; i++) {
+ var region = regions[i];
+ if (region.page != page) continue;
+ region.u = region.x / page.width;
+ region.v = region.y / page.height;
+ if (region.rotate) {
+ region.u2 = (region.x + region.height) / page.width;
+ region.v2 = (region.y + region.width) / page.height;
+ } else {
+ region.u2 = (region.x + region.width) / page.width;
+ region.v2 = (region.y + region.height) / page.height;
+ }
+ }
+ }
+};
+
+spine.Atlas.Format = {
+ alpha: 0,
+ intensity: 1,
+ luminanceAlpha: 2,
+ rgb565: 3,
+ rgba4444: 4,
+ rgb888: 5,
+ rgba8888: 6
+};
+
+spine.Atlas.TextureFilter = {
+ nearest: 0,
+ linear: 1,
+ mipMap: 2,
+ mipMapNearestNearest: 3,
+ mipMapLinearNearest: 4,
+ mipMapNearestLinear: 5,
+ mipMapLinearLinear: 6
+};
+
+spine.Atlas.TextureWrap = {
+ mirroredRepeat: 0,
+ clampToEdge: 1,
+ repeat: 2
+};
+
+spine.AtlasPage = function () {};
+spine.AtlasPage.prototype = {
+ name: null,
+ format: null,
+ minFilter: null,
+ magFilter: null,
+ uWrap: null,
+ vWrap: null,
+ rendererObject: null,
+ width: 0,
+ height: 0
+};
+
+spine.AtlasRegion = function () {};
+spine.AtlasRegion.prototype = {
+ page: null,
+ name: null,
+ x: 0, y: 0,
+ width: 0, height: 0,
+ u: 0, v: 0, u2: 0, v2: 0,
+ offsetX: 0, offsetY: 0,
+ originalWidth: 0, originalHeight: 0,
+ index: 0,
+ rotate: false,
+ splits: null,
+ pads: null
+};
+
+spine.AtlasReader = function (text) {
+ this.lines = text.split(/\r\n|\r|\n/);
+};
+spine.AtlasReader.prototype = {
+ index: 0,
+ trim: function (value) {
+ return value.replace(/^\s+|\s+$/g, "");
+ },
+ readLine: function () {
+ if (this.index >= this.lines.length) return null;
+ return this.lines[this.index++];
+ },
+ readValue: function () {
+ var line = this.readLine();
+ var colon = line.indexOf(":");
+ if (colon == -1) throw "Invalid line: " + line;
+ return this.trim(line.substring(colon + 1));
+ },
+ /** Returns the number of tuple values read (1, 2 or 4). */
+ readTuple: function (tuple) {
+ var line = this.readLine();
+ var colon = line.indexOf(":");
+ if (colon == -1) throw "Invalid line: " + line;
+ var i = 0, lastMatch = colon + 1;
+ for (; i < 3; i++) {
+ var comma = line.indexOf(",", lastMatch);
+ if (comma == -1) break;
+ tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch));
+ lastMatch = comma + 1;
+ }
+ tuple[i] = this.trim(line.substring(lastMatch));
+ return i + 1;
+ }
+};
+
+spine.AtlasAttachmentLoader = function (atlas) {
+ this.atlas = atlas;
+};
+spine.AtlasAttachmentLoader.prototype = {
+ newRegionAttachment: function (skin, name, path) {
+ var region = this.atlas.findRegion(path);
+ if (!region) throw "Region not found in atlas: " + path + " (region attachment: " + name + ")";
+ var attachment = new spine.RegionAttachment(name);
+ attachment.rendererObject = region;
+ attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate);
+ attachment.regionOffsetX = region.offsetX;
+ attachment.regionOffsetY = region.offsetY;
+ attachment.regionWidth = region.width;
+ attachment.regionHeight = region.height;
+ attachment.regionOriginalWidth = region.originalWidth;
+ attachment.regionOriginalHeight = region.originalHeight;
+ return attachment;
+ },
+ newMeshAttachment: function (skin, name, path) {
+ var region = this.atlas.findRegion(path);
+ if (!region) throw "Region not found in atlas: " + path + " (mesh attachment: " + name + ")";
+ var attachment = new spine.MeshAttachment(name);
+ attachment.rendererObject = region;
+ attachment.regionU = region.u;
+ attachment.regionV = region.v;
+ attachment.regionU2 = region.u2;
+ attachment.regionV2 = region.v2;
+ attachment.regionRotate = region.rotate;
+ attachment.regionOffsetX = region.offsetX;
+ attachment.regionOffsetY = region.offsetY;
+ attachment.regionWidth = region.width;
+ attachment.regionHeight = region.height;
+ attachment.regionOriginalWidth = region.originalWidth;
+ attachment.regionOriginalHeight = region.originalHeight;
+ return attachment;
+ },
+ newSkinnedMeshAttachment: function (skin, name, path) {
+ var region = this.atlas.findRegion(path);
+ if (!region) throw "Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")";
+ var attachment = new spine.SkinnedMeshAttachment(name);
+ attachment.rendererObject = region;
+ attachment.regionU = region.u;
+ attachment.regionV = region.v;
+ attachment.regionU2 = region.u2;
+ attachment.regionV2 = region.v2;
+ attachment.regionRotate = region.rotate;
+ attachment.regionOffsetX = region.offsetX;
+ attachment.regionOffsetY = region.offsetY;
+ attachment.regionWidth = region.width;
+ attachment.regionHeight = region.height;
+ attachment.regionOriginalWidth = region.originalWidth;
+ attachment.regionOriginalHeight = region.originalHeight;
+ return attachment;
+ },
+ newBoundingBoxAttachment: function (skin, name) {
+ return new spine.BoundingBoxAttachment(name);
+ }
+};
+
+spine.SkeletonBounds = function () {
+ this.polygonPool = [];
+ this.polygons = [];
+ this.boundingBoxes = [];
+};
+spine.SkeletonBounds.prototype = {
+ minX: 0, minY: 0, maxX: 0, maxY: 0,
+ update: function (skeleton, updateAabb) {
+ var slots = skeleton.slots;
+ var slotCount = slots.length;
+ var x = skeleton.x, y = skeleton.y;
+ var boundingBoxes = this.boundingBoxes;
+ var polygonPool = this.polygonPool;
+ var polygons = this.polygons;
+
+ boundingBoxes.length = 0;
+ for (var i = 0, n = polygons.length; i < n; i++)
+ polygonPool.push(polygons[i]);
+ polygons.length = 0;
+
+ for (var i = 0; i < slotCount; i++) {
+ var slot = slots[i];
+ var boundingBox = slot.attachment;
+ if (boundingBox.type != spine.AttachmentType.boundingbox) continue;
+ boundingBoxes.push(boundingBox);
+
+ var poolCount = polygonPool.length, polygon;
+ if (poolCount > 0) {
+ polygon = polygonPool[poolCount - 1];
+ polygonPool.splice(poolCount - 1, 1);
+ } else
+ polygon = [];
+ polygons.push(polygon);
+
+ polygon.length = boundingBox.vertices.length;
+ boundingBox.computeWorldVertices(x, y, slot.bone, polygon);
+ }
+
+ if (updateAabb) this.aabbCompute();
+ },
+ aabbCompute: function () {
+ var polygons = this.polygons;
+ var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, maxX = Number.MIN_VALUE, maxY = Number.MIN_VALUE;
+ for (var i = 0, n = polygons.length; i < n; i++) {
+ var vertices = polygons[i];
+ for (var ii = 0, nn = vertices.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;
+ },
+ /** Returns true if the axis aligned bounding box contains the point. */
+ aabbContainsPoint: function (x, y) {
+ return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
+ },
+ /** Returns true if the axis aligned bounding box intersects the line segment. */
+ aabbIntersectsSegment: function (x1, y1, x2, y2) {
+ var minX = this.minX, minY = this.minY, maxX = this.maxX, 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;
+ },
+ /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */
+ aabbIntersectsSkeleton: function (bounds) {
+ return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;
+ },
+ /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
+ * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */
+ containsPoint: function (x, y) {
+ var polygons = this.polygons;
+ for (var i = 0, n = polygons.length; i < n; i++)
+ if (this.polygonContainsPoint(polygons[i], x, y)) return this.boundingBoxes[i];
+ return null;
+ },
+ /** Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually
+ * more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true. */
+ intersectsSegment: function (x1, y1, x2, y2) {
+ var polygons = this.polygons;
+ for (var i = 0, n = polygons.length; i < n; i++)
+ if (polygons[i].intersectsSegment(x1, y1, x2, y2)) return this.boundingBoxes[i];
+ return null;
+ },
+ /** Returns true if the polygon contains the point. */
+ polygonContainsPoint: function (polygon, x, y) {
+ var nn = polygon.length;
+ var prevIndex = nn - 2;
+ var inside = false;
+ for (var ii = 0; ii < nn; ii += 2) {
+ var vertexY = polygon[ii + 1];
+ var prevY = polygon[prevIndex + 1];
+ if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
+ var vertexX = polygon[ii];
+ if (vertexX + (y - vertexY) / (prevY - vertexY) * (polygon[prevIndex] - vertexX) < x) inside = !inside;
+ }
+ prevIndex = ii;
+ }
+ return inside;
+ },
+ /** Returns true if the polygon contains the line segment. */
+ polygonIntersectsSegment: function (polygon, x1, y1, x2, y2) {
+ var nn = polygon.length;
+ var width12 = x1 - x2, height12 = y1 - y2;
+ var det1 = x1 * y2 - y1 * x2;
+ var x3 = polygon[nn - 2], y3 = polygon[nn - 1];
+ for (var ii = 0; ii < nn; ii += 2) {
+ var x4 = polygon[ii], y4 = polygon[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;
+ },
+ getPolygon: function (attachment) {
+ var index = this.boundingBoxes.indexOf(attachment);
+ return index == -1 ? null : this.polygons[index];
+ },
+ getWidth: function () {
+ return this.maxX - this.minX;
+ },
+ getHeight: function () {
+ return this.maxY - this.minY;
+ }
+};
\ No newline at end of file
diff --git a/external/chipmunk/chipmunk.js b/external/chipmunk/chipmunk.js
old mode 100755
new mode 100644
index 38d0d8c191..3be84bfc61
--- a/external/chipmunk/chipmunk.js
+++ b/external/chipmunk/chipmunk.js
@@ -1,1318 +1,1502 @@
(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();
- };
-
+/* 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
+ * 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;l'+' '+'
');return x.create({classes:'loading'+(u()?' centered':''),content:(''+' '+' '+''+' '+' '+' '+' '+' '+' '+'
+ * 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 (str, str, str)
+ {
+ 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 (str, str)
+ {
+ 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 (str, str)
+ {
+ 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 {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 {cc.EventAssetsManager::EventCode} arg2
+ * @param {float} arg3
+ * @param {float} arg4
+ * @param {String} arg5
+ * @param {String} arg6
+ * @param {int} arg7
+ * @param {int} arg8
+ */
+ EventAssetsManager : function (
+ str,
+ assetsmanager,
+ eventcode,
+ float,
+ float,
+ str,
+ str,
+ int,
+ int
+ )
+ {
+ }
+});
+
+
+/**
+ * @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 {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 {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 (str, str)
+ {
+ return cc.AssetsManager;
+ },
+
+ /**
+ * @function AssetsManager
+ * @constructor
+ * @param {String} arg0
+ * @param {String} arg1
+ */
+ ctor : function (str, str)
+ {
+ }
+
+});
+
+/**
+ * @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(){
+ }
+};
\ No newline at end of file
diff --git a/moduleConfig.json b/moduleConfig.json
index 20cdaaefdb..a089e198d8 100644
--- a/moduleConfig.json
+++ b/moduleConfig.json
@@ -27,7 +27,9 @@
"clipping-nodes" : [
"core", "shape-nodes",
- "cocos2d/clipping-nodes/CCClippingNode.js"
+ "cocos2d/clipping-nodes/CCClippingNode.js",
+ "cocos2d/clipping-nodes/CCClippingNodeCanvasRenderCmd.js",
+ "cocos2d/clipping-nodes/CCClippingNodeWebGLRenderCmd.js"
],
"compression" : [
"core",
@@ -70,10 +72,16 @@
"cocos2d/core/event-manager/CCEventManager.js",
"cocos2d/core/event-manager/CCEventExtension.js",
- "cocos2d/core/base-nodes/BaseNodesWebGL.js",
+ "cocos2d/core/renderer/RendererCanvas.js",
+ "cocos2d/core/renderer/RendererWebGL.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",
@@ -84,14 +92,18 @@
"cocos2d/core/scenes/CCScene.js",
"cocos2d/core/scenes/CCLoaderScene.js",
- "cocos2d/core/layers/CCLayerWebGL.js",
- "cocos2d/core/layers/CCLayerPropertyDefine.js",
"cocos2d/core/layers/CCLayer.js",
+ "cocos2d/core/layers/CCLayerCanvasRenderCmd.js",
+ "cocos2d/core/layers/CCLayerWebGLRenderCmd.js",
- "cocos2d/core/sprites/SpritesWebGL.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/CCSpriteBatchNodeCanvasRenderCmd.js",
+ "cocos2d/core/sprites/CCSpriteBatchNodeWebGLRenderCmd.js",
+ "cocos2d/core/sprites/CCBakeSprite.js",
"cocos2d/core/sprites/CCAnimation.js",
"cocos2d/core/sprites/CCAnimationCache.js",
"cocos2d/core/sprites/CCSpriteFrame.js",
@@ -106,9 +118,10 @@
"cocos2d/core/CCDrawingPrimitivesCanvas.js",
"cocos2d/core/CCDrawingPrimitivesWebGL.js",
- "cocos2d/core/labelttf/LabelTTFWebGL.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"
],
@@ -138,7 +151,11 @@
"core",
"cocos2d/labels/CCLabelAtlas.js",
- "cocos2d/labels/CCLabelBMFont.js"
+ "cocos2d/labels/CCLabelAtlasCanvasRenderCmd.js",
+ "cocos2d/labels/CCLabelAtlasWebGLRenderCmd.js",
+ "cocos2d/labels/CCLabelBMFont.js",
+ "cocos2d/labels/CCLabelBMFontCanvasRenderCmd.js",
+ "cocos2d/labels/CCLabelBMFontWebGLRenderCmd.js"
],
"menus" : [
"core", "actions",
@@ -149,17 +166,20 @@
"motion-streak" : [
"core", "shaders", "kazmath", "labels",
- "cocos2d/motion-streak/CCMotionStreak.js"
+ "cocos2d/motion-streak/CCMotionStreak.js",
+ "cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js"
],
"node-grid" : [
"core",
- "cocos2d/node-grid/CCNodeGrid.js"
+ "cocos2d/node-grid/CCNodeGrid.js",
+ "cocos2d/node-grid/CCNodeGridWebGLRenderCmd.js"
],
"parallax" : [
"core",
- "cocos2d/parallax/CCParallaxNode.js"
+ "cocos2d/parallax/CCParallaxNode.js",
+ "cocos2d/parallax/CCParallaxNodeRenderCmd.js"
],
"particle" : [
"core", "compression",
@@ -167,25 +187,37 @@
"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/CCParticleBatchNode.js",
+ "cocos2d/particle/CCParticleBatchNodeCanvasRenderCmd.js",
+ "cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js"
],
"physics" : [
"core", "shape-nodes",
"cocos2d/physics/CCPhysicsSprite.js",
- "cocos2d/physics/CCPhysicsDebugNode.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/CCActionProgressTimer.js",
+ "cocos2d/progress-timer/CCProgressTimerCanvasRenderCmd.js",
+ "cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js"
],
"render-texture" : [
"core",
- "cocos2d/render-texture/CCRenderTexture.js"
+ "cocos2d/render-texture/CCRenderTexture.js",
+ "cocos2d/render-texture/CCRenderTextureCanvasRenderCmd.js",
+ "cocos2d/render-texture/CCRenderTextureWebGLRenderCmd.js"
],
"shaders" : [
"core", "kazmath",
@@ -198,7 +230,9 @@
"shape-nodes" : [
"core",
- "cocos2d/shape-nodes/CCDrawNode.js"
+ "cocos2d/shape-nodes/CCDrawNode.js",
+ "cocos2d/shape-nodes/CCDrawNodeCanvasRenderCmd.js",
+ "cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js"
],
"text-input" : [
"core",
@@ -213,7 +247,9 @@
"cocos2d/tilemap/CCTMXTiledMap.js",
"cocos2d/tilemap/CCTMXXMLParser.js",
"cocos2d/tilemap/CCTMXObjectGroup.js",
- "cocos2d/tilemap/CCTMXLayer.js"
+ "cocos2d/tilemap/CCTMXLayer.js",
+ "cocos2d/tilemap/CCTMXLayerCanvasRenderCmd.js",
+ "cocos2d/tilemap/CCTMXLayerWebGLRenderCmd.js"
],
"transitions" : [
"core", "actions", "render-texture", "progress-timer",
@@ -231,8 +267,6 @@
"text-input", "menus", "tilemap", "parallax", "audio"
],
-
-
"ccbreader" : [
"core", "audio", "gui", "menus", "particle", "actions", "labels",
@@ -254,13 +288,30 @@
"extensions/editbox/CCdomNode.js",
"extensions/editbox/CCEditBox.js"
],
+ "ccpool" : [
+ "core",
+
+ "extensions/ccpool/CCPool.js"
+ ],
"ccui" : [
- "core", "gui", "actions", "labels", "text-input","clipping-nodes",
+ "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/UILayoutDefine.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",
@@ -281,6 +332,7 @@
"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",
@@ -295,11 +347,15 @@
"extensions/cocostudio/armature/display/CCDisplayFactory.js",
"extensions/cocostudio/armature/display/CCDisplayManager.js",
"extensions/cocostudio/armature/display/CCSkin.js",
+ "extensions/cocostudio/armature/display/CCSkinCanvasRenderCmd.js",
+ "extensions/cocostudio/armature/display/CCSkinWebGLRenderCmd.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",
@@ -317,8 +373,20 @@
"extensions/cocostudio/trigger/TriggerMng.js",
"extensions/cocostudio/trigger/TriggerObj.js",
- "extensions/cocostudio/reader/GUIReader.js",
- "extensions/cocostudio/reader/SceneReader.js"
+ "extensions/cocostudio/timeline/ActionTimeline.js",
+ "extensions/cocostudio/timeline/Frame.js",
+ "extensions/cocostudio/timeline/Timeline.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",
@@ -328,6 +396,8 @@
"extensions/gui/control-extension/CCControlUtils.js",
"extensions/gui/control-extension/CCInvocation.js",
"extensions/gui/control-extension/CCScale9Sprite.js",
+ "extensions/gui/control-extension/CCScale9SpriteCanvasRenderCmd.js",
+ "extensions/gui/control-extension/CCScale9SpriteWebGLRenderCmd.js",
"extensions/gui/control-extension/CCMenuPassive.js",
"extensions/gui/control-extension/CCControlSaturationBrightnessPicker.js",
"extensions/gui/control-extension/CCControlHuePicker.js",
@@ -337,6 +407,8 @@
"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"
],
@@ -344,27 +416,47 @@
"pluginx" : [
"core",
- "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/PluginFactory.js",
- "extensions/pluginx/protocols/PluginManager.js",
-
+ "external/pluginx/Plugin.js"
+ ],
+ "plugin-facebook" : [
+ "external/pluginx/platform/facebook_sdk.js",
+ "external/pluginx/platform/facebook.js"
+ ],
- "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",
+ "spine":[
+ "core",
- "extensions/pluginx/plugins/AnalyticsFlurry.js"
+ "extensions/spine/Spine.js",
+ "extensions/spine/CCSkeleton.js",
+ "extensions/spine/CCSkeletonAnimation.js",
+ "extensions/spine/CCSkeletonCanvasRenderCmd.js",
+ "extensions/spine/CCSkeletonWebGLRenderCmd.js"
],
- "extensions" : ["gui", "ccbreader", "editbox", "cocostudio", "pluginx"],
+ "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",
@@ -377,10 +469,9 @@
"external/chipmunk/chipmunk.js"
],
"socketio" : [
-
"external/socketio/socket.io.min.js"
],
- "external" : ["box2d", "chipmunk", "socketio"]
+ "external" : ["box2d", "chipmunk", "socketio", "pluginx", "gaf"]
},
"bootFile" : "CCBoot.js"
}
\ No newline at end of file
diff --git a/template/index.html b/template/index.html
index 1e314249d6..e0f577b927 100644
--- a/template/index.html
+++ b/template/index.html
@@ -19,10 +19,11 @@
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
+
+
+
-
-