spritejs/spritejs

View on GitHub
benchmark/js/cocos2d-js-v3.13.js

Summary

Maintainability
A
0 mins
Test Coverage
var cc = cc || {};
cc._tmp = cc._tmp || {};
cc._LogInfos = {};
var _p = window;
_p.gl;
_p.WebGLRenderingContext;
_p.DeviceOrientationEvent;
_p.DeviceMotionEvent;
_p.AudioContext;
if (!_p.AudioContext) {
    _p.webkitAudioContext;
}
_p.mozAudioContext;
_p = Object.prototype;
_p._super;
_p.ctor;
_p = null;
cc.ORIENTATION_PORTRAIT = 0;
cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1;
cc.ORIENTATION_LANDSCAPE_LEFT = 2;
cc.ORIENTATION_LANDSCAPE_RIGHT = 3;
cc._drawingUtil = null;
cc._renderContext = null;
cc._supportRender = false;
cc._canvas = null;
cc.container = null;
cc._gameDiv = null;
cc.newElement = function (x) {
    return document.createElement(x);
};
cc.each = function (obj, iterator, context) {
    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;
        }
    } else {
        for (var key in obj) {
            if (iterator.call(context, obj[key], key) === false)
                return;
        }
    }
};
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;
};
cc.isFunction = function(obj) {
    return typeof obj === 'function';
};
cc.isNumber = function(obj) {
    return typeof obj === 'number' || Object.prototype.toString.call(obj) === '[object Number]';
};
cc.isString = function(obj) {
    return typeof obj === 'string' || Object.prototype.toString.call(obj) === '[object String]';
};
cc.isArray = function(obj) {
    return Array.isArray(obj) ||
        (typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Array]');
};
cc.isUndefined = function(obj) {
    return typeof obj === 'undefined';
};
cc.isObject = function(obj) {
    return typeof obj === "object" && Object.prototype.toString.call(obj) === '[object Object]';
};
cc.isCrossOrigin = function (url) {
    if (!url) {
        cc.log("invalid URL");
        return false;
    }
    var startIndex = url.indexOf("://");
    if (startIndex === -1)
        return false;
    var endIndex = url.indexOf("/", startIndex + 3);
    var urlOrigin = (endIndex === -1) ? url : url.substring(0, endIndex);
    return urlOrigin !== location.origin;
};
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._errors = srcObj instanceof Array ? [] : {};
    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;
        var item = self._pool.shift();
        var value = item.value, index = item.index;
        self._workingSize++;
        self._iterator.call(self._iteratorTarget, value, index,
            function(err, result) {
                self.finishedSize++;
                self._workingSize--;
                if (err) {
                    self._errors[this.index] = err;
                }
                else {
                    self._results[this.index] = result;
                }
                if (self.finishedSize === self.size) {
                    if (self._onEnd) {
                        var errors = self._errors.length === 0 ? null : self._errors;
                        self._onEnd.call(self._onEndTarget, errors, 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;
        }
        for(var i = 0; i < self._limit; i++)
            self._handleItem();
    };
};
cc.async = {
    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;
    },
    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;
    },
    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;
    },
    map : function(tasks, iterator, callback, target){
        var locIterator = iterator;
        if(typeof(iterator) === "object"){
            callback = iterator.cb;
            target = iterator.iteratorTarget;
            locIterator = iterator.iterator;
        }
        var asyncPool = new cc.AsyncPool(tasks, 0, locIterator, callback, target);
        asyncPool.flow();
        return asyncPool;
    },
    mapLimit : function(tasks, limit, iterator, cb, target){
        var asyncPool = new cc.AsyncPool(tasks, limit, iterator, cb, target);
        asyncPool.flow();
        return asyncPool;
    }
};
cc.path = {
    normalizeRE: /[^\.\/]+\/\.\.\//,
    join: function () {
        var l = arguments.length;
        var result = "";
        for (var i = 0; i < l; i++) {
            result = (result + (result === "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");
        }
        return result;
    },
    extname: function (pathStr) {
        var temp = /(\.[^\.\/\?\\]*)(\?.*)?$/.exec(pathStr);
        return temp ? temp[1] : null;
    },
    mainFileName: function(fileName){
        if(fileName){
            var idx = fileName.lastIndexOf(".");
            if(idx !== -1)
                return fileName.substring(0,idx);
        }
        return fileName;
    },
    basename: function (pathStr, extname) {
        var index = pathStr.indexOf("?");
        if (index > 0) pathStr = pathStr.substring(0, index);
        var reg = /(\/|\\\\)([^(\/|\\\\)]+)$/g;
        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())
            return baseName.substring(0, baseName.length - extname.length);
        return baseName;
    },
    dirname: function (pathStr) {
        return pathStr.replace(/((.*)(\/|\\|\\\\))?(.*?\..*$)?/, '$2');
    },
    changeExtname: function (pathStr, extname) {
        extname = extname || "";
        var index = pathStr.indexOf("?");
        var tempStr = "";
        if (index > 0) {
            tempStr = pathStr.substring(index);
            pathStr = pathStr.substring(0, index);
        }
        index = pathStr.lastIndexOf(".");
        if (index < 0) return pathStr + extname + tempStr;
        return pathStr.substring(0, index) + extname + tempStr;
    },
    changeBasename: function (pathStr, basename, isSameExt) {
        if (basename.indexOf(".") === 0) return this.changeExtname(pathStr, basename);
        var index = pathStr.indexOf("?");
        var tempStr = "";
        var ext = isSameExt ? this.extname(pathStr) : "";
        if (index > 0) {
            tempStr = pathStr.substring(index);
            pathStr = pathStr.substring(0, index);
        }
        index = pathStr.lastIndexOf("/");
        index = index <= 0 ? 0 : index + 1;
        return pathStr.substring(0, index) + basename + ext + tempStr;
    },
    _normalize: function(url){
        var oldUrl = url = String(url);
        do {
            oldUrl = url;
            url = url.replace(this.normalizeRE, "");
        } while(oldUrl.length !== url.length);
        return url;
    }
};
cc.loader = (function () {
    var _jsCache = {},
        _register = {},
        _langPathCache = {},
        _aliases = {},
        _queue = {},
        _urlRegExp = new RegExp(
            "^" +
                "(?:(?:https?|ftp)://)" +
                "(?:\\S+(?::\\S*)?@)?" +
                "(?:" +
                    "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
                    "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
                    "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
                "|" +
                    "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
                    "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
                    "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
                "|" +
                    "(?:localhost)" +
                ")" +
                "(?::\\d{2,5})?" +
                "(?:/\\S*)?" +
            "$", "i"
        );
    return {
        resPath: "",
        audioPath: "",
        cache: {},
        getXMLHttpRequest: function () {
            return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP");
        },
        _getArgs4Js: function (args) {
            var a0 = args[0], a1 = args[1], a2 = args[2], results = ["", null, null];
            if (args.length === 1) {
                results[1] = a0 instanceof Array ? a0 : [a0];
            } else if (args.length === 2) {
                if (typeof a1 === "function") {
                    results[1] = a0 instanceof Array ? a0 : [a0];
                    results[2] = a1;
                } else {
                    results[0] = a0 || "";
                    results[1] = a1 instanceof Array ? a1 : [a1];
                }
            } else if (args.length === 3) {
                results[0] = a0 || "";
                results[1] = a1 instanceof Array ? a1 : [a1];
                results[2] = a2;
            } else throw new Error("arguments error to load js!");
            return results;
        },
        isLoading: function (url) {
            return (_queue[url] !== undefined);
        },
        loadJs: function (baseDir, jsList, cb) {
            var self = this,
                args = self._getArgs4Js(arguments);
            var preDir = args[0], list = args[1], callback = args[2];
            if (navigator.userAgent.indexOf("Trident/5") > -1) {
                self._loadJs4Dependency(preDir, list, 0, callback);
            } else {
                cc.async.map(list, function (item, index, cb1) {
                    var jsPath = cc.path.join(preDir, item);
                    if (_jsCache[jsPath]) return cb1(null);
                    self._createScript(jsPath, false, cb1);
                }, callback);
            }
        },
        loadJsWithImg: function (baseDir, jsList, cb) {
            var self = this, jsLoadingImg = self._loadJsImg(),
                args = self._getArgs4Js(arguments);
            this.loadJs(args[0], args[1], function (err) {
                if (err) throw new Error(err);
                jsLoadingImg.parentNode.removeChild(jsLoadingImg);//remove loading gif
                if (args[2]) args[2]();
            });
        },
        _createScript: function (jsPath, isAsync, cb) {
            var d = document, self = this, s = document.createElement('script');
            s.async = isAsync;
            _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;
            }
            s.addEventListener('load', function () {
                s.parentNode.removeChild(s);
                this.removeEventListener('load', arguments.callee, false);
                cb();
            }, false);
            s.addEventListener('error', function () {
                s.parentNode.removeChild(s);
                cb("Load " + jsPath + " failed!");
            }, false);
            d.body.appendChild(s);
        },
        _loadJs4Dependency: function (baseDir, jsList, index, cb) {
            if (index >= jsList.length) {
                if (cb) cb();
                return;
            }
            var self = this;
            self._createScript(cc.path.join(baseDir, jsList[index]), false, function (err) {
                if (err) return cb(err);
                self._loadJs4Dependency(baseDir, jsList, index + 1, cb);
            });
        },
        _loadJsImg: function () {
            var d = document, jsLoadingImg = d.getElementById("cocos2d_loadJsImg");
            if (!jsLoadingImg) {
                jsLoadingImg = document.createElement('img');
                if (cc._loadingImage)
                    jsLoadingImg.src = cc._loadingImage;
                var canvasNode = d.getElementById(cc.game.config["id"]);
                canvasNode.style.backgroundColor = "transparent";
                canvasNode.parentNode.appendChild(jsLoadingImg);
                var canvasStyle = getComputedStyle ? getComputedStyle(canvasNode) : canvasNode.currentStyle;
                if (!canvasStyle)
                    canvasStyle = {width: canvasNode.width, height: canvasNode.height};
                jsLoadingImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - jsLoadingImg.width) / 2 + "px";
                jsLoadingImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - jsLoadingImg.height) / 2 + "px";
                jsLoadingImg.style.position = "absolute";
            }
            return jsLoadingImg;
        },
        loadTxt: function (url, cb) {
            if (!cc._isNodeJs) {
                var xhr = this.getXMLHttpRequest(),
                    errInfo = "load " + url + " failed!";
                xhr.open("GET", url, true);
                if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
                    xhr.setRequestHeader("Accept-Charset", "utf-8");
                    xhr.onreadystatechange = function () {
                        if(xhr.readyState === 4)
                            xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null);
                    };
                } else {
                    if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
                    xhr.onload = function () {
                        if(xhr.readyState === 4)
                            xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null);
                    };
                    xhr.onerror = function(){
                        cb({status:xhr.status, errorMessage:errInfo}, null);
                    };
                }
                xhr.send(null);
            } else {
                var fs = require("fs");
                fs.readFile(url, function (err, data) {
                    err ? cb(err) : cb(null, data.toString());
                });
            }
        },
        _loadTxtSync: function (url) {
            if (!cc._isNodeJs) {
                var xhr = this.getXMLHttpRequest();
                xhr.open("GET", url, false);
                if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
                    xhr.setRequestHeader("Accept-Charset", "utf-8");
                } else {
                    if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8");
                }
                xhr.send(null);
                if (!xhr.readyState === 4 || xhr.status !== 200) {
                    return null;
                }
                return xhr.responseText;
            } else {
                var fs = require("fs");
                return fs.readFileSync(url).toString();
            }
        },
        loadCsb: function(url, cb){
            var xhr = new XMLHttpRequest(),
                errInfo = "load " + url + " failed!";
            xhr.open("GET", url, true);
            xhr.responseType = "arraybuffer";
            xhr.onload = function () {
                var arrayBuffer = xhr.response;
                if (arrayBuffer) {
                    window.msg = arrayBuffer;
                }
                if(xhr.readyState === 4)
                    xhr.status === 200 ? cb(null, xhr.response) : cb({status:xhr.status, errorMessage:errInfo}, null);
            };
            xhr.onerror = function(){
                cb({status:xhr.status, errorMessage:errInfo}, null);
            };
            xhr.send(null);
        },
        loadJson: function (url, cb) {
            this.loadTxt(url, function (err, txt) {
                if (err) {
                    cb(err);
                }
                else {
                    try {
                        var result = JSON.parse(txt);
                    }
                    catch (e) {
                        throw new Error("parse json [" + url + "] failed : " + e);
                        return;
                    }
                    cb(null, result);
                }
            });
        },
        _checkIsImageURL: function (url) {
            var ext = /(\.png)|(\.jpg)|(\.bmp)|(\.jpeg)|(\.gif)/.exec(url);
            return (ext != null);
        },
        loadImg: function (url, option, callback) {
            var opt = {
                isCrossOrigin: true
            };
            if (callback !== undefined)
                opt.isCrossOrigin = option.isCrossOrigin === undefined ? opt.isCrossOrigin : option.isCrossOrigin;
            else if (option !== undefined)
                callback = option;
            var img = this.getRes(url);
            if (img) {
                callback && callback(null, img);
                return img;
            }
            var queue = _queue[url];
            if (queue) {
                queue.callbacks.push(callback);
                return queue.img;
            }
            img = new Image();
            if (opt.isCrossOrigin && location.origin !== "file://")
                img.crossOrigin = "Anonymous";
            var loadCallback = function () {
                this.removeEventListener('load', loadCallback, false);
                this.removeEventListener('error', errorCallback, false);
                if (!_urlRegExp.test(url)) {
                    cc.loader.cache[url] = img;
                }
                var queue = _queue[url];
                if (queue) {
                    var callbacks = queue.callbacks;
                    for (var i = 0; i < callbacks.length; ++i) {
                        var cb = callbacks[i];
                        if (cb) {
                            cb(null, img);
                        }
                    }
                    queue.img = null;
                    delete _queue[url];
                }
            };
            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 {
                    var queue = _queue[url];
                    if (queue) {
                        var callbacks = queue.callbacks;
                        for (var i = 0; i < callbacks.length; ++i) {
                            var cb = callbacks[i];
                            if (cb) {
                                cb("load image failed");
                            }
                        }
                        queue.img = null;
                        delete _queue[url];
                    }
                }
            };
            _queue[url] = {
                img: img,
                callbacks: callback ? [callback] : []
            };
            img.addEventListener("load", loadCallback);
            img.addEventListener("error", errorCallback);
            img.src = url;
            return img;
        },
        _loadResIterator: function (item, index, cb) {
            var self = this, url = null;
            var type = item.type;
            if (type) {
                type = "." + type.toLowerCase();
                url = item.src ? item.src : item.name + type;
            } else {
                url = item;
                type = cc.path.extname(url);
            }
            var obj = self.getRes(url);
            if (obj)
                return cb(null, obj);
            var loader = null;
            if (type) {
                loader = _register[type.toLowerCase()];
            }
            if (!loader) {
                cc.error("loader for [" + type + "] not exists!");
                return cb();
            }
            var realUrl = url;
            if (!_urlRegExp.test(url))
            {
                var basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
                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({status:520, errorMessage:err}, null);
                } else {
                    self.cache[url] = data;
                    cb(null, data);
                }
            });
        },
        _noCacheRex: /\?/,
        getUrl: function (basePath, url) {
            var self = this, path = cc.path;
            if (basePath !== undefined && url === undefined) {
                url = basePath;
                var type = path.extname(url);
                type = type ? type.toLowerCase() : "";
                var loader = _register[type];
                if (!loader)
                    basePath = self.resPath;
                else
                    basePath = loader.getBasePath ? loader.getBasePath() : self.resPath;
            }
            url = cc.path.join(basePath || "", url);
            if (url.match(/[\/(\\\\)]lang[\/(\\\\)]/i)) {
                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;
            }
            return url;
        },
        load : function(resources, option, loadCallback){
            var self = this;
            var len = arguments.length;
            if(len === 0)
                throw new Error("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(len === 2){
                if(typeof option === "function")
                    option = {cb : option};
            }else if(len === 1){
                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) {
                        var arr = Array.prototype.slice.call(arguments, 1);
                        if (option.trigger)
                            option.trigger.call(option.triggerTarget, arr[0], aPool.size, aPool.finishedSize);
                        AsyncPoolCallback(err, arr[0]);
                    });
                },
                option.cb, option.cbTarget);
            asyncPool.flow();
            return asyncPool;
        },
        _handleAliases: function (fileNames, cb) {
            var self = this;
            var resList = [];
            for (var key in fileNames) {
                var value = fileNames[key];
                _aliases[key] = value;
                resList.push(value);
            }
            this.load(resList, cb);
        },
        loadAliases: function (url, callback) {
            var self = this, dict = self.getRes(url);
            if (!dict) {
                self.load(url, function (err, results) {
                    self._handleAliases(results[0]["filenames"], callback);
                });
            } else
                self._handleAliases(dict["filenames"], callback);
        },
        register: function (extNames, loader) {
            if (!extNames || !loader) return;
            var self = this;
            if (typeof extNames === "string")
                return _register[extNames.trim().toLowerCase()] = loader;
            for (var i = 0, li = extNames.length; i < li; i++) {
                _register["." + extNames[i].trim().toLowerCase()] = loader;
            }
        },
        getRes: function (url) {
            return this.cache[url] || this.cache[_aliases[url]];
        },
        _getAliase: function (url) {
            return _aliases[url];
        },
        release: function (url) {
            var cache = this.cache;
            var queue = _queue[url];
            if (queue) {
                queue.img = null;
                delete _queue[url];
            }
            delete cache[url];
            delete cache[_aliases[url]];
            delete _aliases[url];
        },
        releaseAll: function () {
            var locCache = this.cache;
            for (var key in locCache)
                delete locCache[key];
            for (var key in _aliases)
                delete _aliases[key];
        }
    };
})();
cc.formatStr = function(){
    var args = arguments;
    var l = args.length;
    if(l < 1)
        return "";
    var str = args[0];
    var needToFormat = true;
    if(typeof str === "object"){
        needToFormat = false;
    }
    for(var i = 1; i < l; ++i){
        var arg = args[i];
        if(needToFormat){
            while(true){
                var result = null;
                if(typeof arg === "number"){
                    result = str.match(/(%d)|(%s)/);
                    if(result){
                        str = str.replace(/(%d)|(%s)/, arg);
                        break;
                    }
                }
                result = str.match(/%s/);
                if(result)
                    str = str.replace(/%s/, arg);
                else
                    str += "    " + arg;
                break;
            }
        }else
            str += "    " + arg;
    }
    return str;
};
(function () {
var _tmpCanvas1 = document.createElement("canvas"),
    _tmpCanvas2 = document.createElement("canvas");
cc.create3DContext = function (canvas, opt_attribs) {
    var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
    var context = null;
    for (var ii = 0; ii < names.length; ++ii) {
        try {
            context = canvas.getContext(names[ii], opt_attribs);
        } catch (e) {
        }
        if (context) {
            break;
        }
    }
    return context;
};
var _initSys = function () {
    cc.sys = {};
    var sys = cc.sys;
    sys.LANGUAGE_ENGLISH = "en";
    sys.LANGUAGE_CHINESE = "zh";
    sys.LANGUAGE_FRENCH = "fr";
    sys.LANGUAGE_ITALIAN = "it";
    sys.LANGUAGE_GERMAN = "de";
    sys.LANGUAGE_SPANISH = "es";
    sys.LANGUAGE_DUTCH = "du";
    sys.LANGUAGE_RUSSIAN = "ru";
    sys.LANGUAGE_KOREAN = "ko";
    sys.LANGUAGE_JAPANESE = "ja";
    sys.LANGUAGE_HUNGARIAN = "hu";
    sys.LANGUAGE_PORTUGUESE = "pt";
    sys.LANGUAGE_ARABIC = "ar";
    sys.LANGUAGE_NORWEGIAN = "no";
    sys.LANGUAGE_POLISH = "pl";
    sys.LANGUAGE_UNKNOWN = "unkonwn";
    sys.OS_IOS = "iOS";
    sys.OS_ANDROID = "Android";
    sys.OS_WINDOWS = "Windows";
    sys.OS_MARMALADE = "Marmalade";
    sys.OS_LINUX = "Linux";
    sys.OS_BADA = "Bada";
    sys.OS_BLACKBERRY = "Blackberry";
    sys.OS_OSX = "OS X";
    sys.OS_WP8 = "WP8";
    sys.OS_WINRT = "WINRT";
    sys.OS_UNKNOWN = "Unknown";
    sys.UNKNOWN = -1;
    sys.WIN32 = 0;
    sys.LINUX = 1;
    sys.MACOS = 2;
    sys.ANDROID = 3;
    sys.IPHONE = 4;
    sys.IPAD = 5;
    sys.BLACKBERRY = 6;
    sys.NACL = 7;
    sys.EMSCRIPTEN = 8;
    sys.TIZEN = 9;
    sys.WINRT = 10;
    sys.WP8 = 11;
    sys.MOBILE_BROWSER = 100;
    sys.DESKTOP_BROWSER = 101;
    sys.BROWSER_TYPE_WECHAT = "wechat";
    sys.BROWSER_TYPE_ANDROID = "androidbrowser";
    sys.BROWSER_TYPE_IE = "ie";
    sys.BROWSER_TYPE_QQ = "qqbrowser";
    sys.BROWSER_TYPE_MOBILE_QQ = "mqqbrowser";
    sys.BROWSER_TYPE_UC = "ucbrowser";
    sys.BROWSER_TYPE_360 = "360browser";
    sys.BROWSER_TYPE_BAIDU_APP = "baiduboxapp";
    sys.BROWSER_TYPE_BAIDU = "baidubrowser";
    sys.BROWSER_TYPE_MAXTHON = "maxthon";
    sys.BROWSER_TYPE_OPERA = "opera";
    sys.BROWSER_TYPE_OUPENG = "oupeng";
    sys.BROWSER_TYPE_MIUI = "miuibrowser";
    sys.BROWSER_TYPE_FIREFOX = "firefox";
    sys.BROWSER_TYPE_SAFARI = "safari";
    sys.BROWSER_TYPE_CHROME = "chrome";
    sys.BROWSER_TYPE_LIEBAO = "liebao";
    sys.BROWSER_TYPE_QZONE = "qzone";
    sys.BROWSER_TYPE_SOUGOU = "sogou";
    sys.BROWSER_TYPE_UNKNOWN = "unknown";
    sys.isNative = false;
    var win = window, nav = win.navigator, doc = document, docEle = doc.documentElement;
    var ua = nav.userAgent.toLowerCase();
    sys.isMobile = ua.indexOf('mobile') !== -1 || ua.indexOf('android') !== -1;
    sys.platform = sys.isMobile ? sys.MOBILE_BROWSER : sys.DESKTOP_BROWSER;
    var currLanguage = nav.language;
    currLanguage = currLanguage ? currLanguage : nav.browserLanguage;
    currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH;
    sys.language = currLanguage;
    var isAndroid = false, iOS = false, osVersion = '', osMainVersion = 0;
    var uaResult = /android (\d+(?:\.\d+)+)/i.exec(ua) || /android (\d+(?:\.\d+)+)/i.exec(nav.platform);
    if (uaResult) {
        isAndroid = true;
        osVersion = uaResult[1] || '';
        osMainVersion = parseInt(osVersion) || 0;
    }
    uaResult = /(iPad|iPhone|iPod).*OS ((\d+_?){2,3})/i.exec(ua);
    if (uaResult) {
        iOS = true;
        osVersion = uaResult[2] || '';
        osMainVersion = parseInt(osVersion) || 0;
    }
    var osName = sys.OS_UNKNOWN;
    if (nav.appVersion.indexOf("Win") !== -1) osName = sys.OS_WINDOWS;
    else if (iOS) osName = sys.OS_IOS;
    else if (nav.appVersion.indexOf("Mac") !== -1) osName = sys.OS_OSX;
    else if (nav.appVersion.indexOf("X11") !== -1 && nav.appVersion.indexOf("Linux") === -1) osName = sys.OS_UNIX;
    else if (isAndroid) osName = sys.OS_ANDROID;
    else if (nav.appVersion.indexOf("Linux") !== -1) osName = sys.OS_LINUX;
    sys.os = osName;
    sys.osVersion = osVersion;
    sys.osMainVersion = osMainVersion;
    sys.browserType = sys.BROWSER_TYPE_UNKNOWN;
    (function(){
        var typeReg1 = /mqqbrowser|sogou|qzone|liebao|micromessenger|ucbrowser|360 aphone|360browser|baiduboxapp|baidubrowser|maxthon|mxbrowser|trident|miuibrowser/i;
        var typeReg2 = /qqbrowser|chrome|safari|firefox|opr|oupeng|opera/i;
        var browserTypes = typeReg1.exec(ua);
        if(!browserTypes) browserTypes = typeReg2.exec(ua);
        var browserType = browserTypes ? browserTypes[0] : sys.BROWSER_TYPE_UNKNOWN;
        if (browserType === 'micromessenger')
            browserType = sys.BROWSER_TYPE_WECHAT;
        else if (browserType === "safari" && (ua.match(/android.*applewebkit/)))
            browserType = sys.BROWSER_TYPE_ANDROID;
        else if (browserType === "trident")
            browserType = sys.BROWSER_TYPE_IE;
        else if (browserType === "360 aphone")
            browserType = sys.BROWSER_TYPE_360;
        else if (browserType === "mxbrowser")
            browserType = sys.BROWSER_TYPE_MAXTHON;
        else if (browserType === "opr")
            browserType = sys.BROWSER_TYPE_OPERA;
        sys.browserType = browserType;
    })();
    sys.browserVersion = "";
    (function(){
        var versionReg1 = /(micromessenger|qq|mx|maxthon|baidu|sogou)(mobile)?(browser)?\/?([\d.]+)/i;
        var versionReg2 = /(msie |rv:|firefox|chrome|ucbrowser|oupeng|opera|opr|safari|miui)(mobile)?(browser)?\/?([\d.]+)/i;
        var tmp = ua.match(versionReg1);
        if(!tmp) tmp = ua.match(versionReg2);
        sys.browserVersion = tmp ? tmp[4] : "";
    })();
    var w = window.innerWidth || document.documentElement.clientWidth;
    var h = window.innerHeight || document.documentElement.clientHeight;
    var ratio = window.devicePixelRatio || 1;
    sys.windowPixelResolution = {
        width: ratio * w,
        height: ratio * h
    };
    sys._checkWebGLRenderMode = function () {
        if (cc._renderType !== cc.game.RENDER_TYPE_WEBGL)
            throw new Error("This feature supports WebGL render mode only.");
    };
    sys._supportCanvasNewBlendModes = (function(){
        var canvas = _tmpCanvas1;
        canvas.width = 1;
        canvas.height = 1;
        var context = canvas.getContext('2d');
        context.fillStyle = '#000';
        context.fillRect(0,0,1,1);
        context.globalCompositeOperation = 'multiply';
        var canvas2 = _tmpCanvas2;
        canvas2.width = 1;
        canvas2.height = 1;
        var context2 = canvas2.getContext('2d');
        context2.fillStyle = '#fff';
        context2.fillRect(0,0,1,1);
        context.drawImage(canvas2, 0, 0, 1, 1);
        return context.getImageData(0,0,1,1).data[0] === 0;
    })();
    if (cc.sys.isMobile) {
        var fontStyle = document.createElement("style");
        fontStyle.type = "text/css";
        document.body.appendChild(fontStyle);
        fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;"
                                + "-webkit-tap-highlight-color:rgba(0,0,0,0);}";
    }
    try {
        var localStorage = sys.localStorage = win.localStorage;
        localStorage.setItem("storage", "");
        localStorage.removeItem("storage");
        localStorage = null;
    } catch (e) {
        var warn = function () {
            cc.warn("Warning: localStorage isn't enabled. Please confirm browser cookie or privacy option");
        };
        sys.localStorage = {
            getItem : warn,
            setItem : warn,
            removeItem : warn,
            clear : warn
        };
    }
    var _supportCanvas = !!_tmpCanvas1.getContext("2d");
    var _supportWebGL = false;
    if (win.WebGLRenderingContext) {
        var tmpCanvas = document.createElement("CANVAS");
        try{
            var context = cc.create3DContext(tmpCanvas, {'stencil': true});
            if(context) {
                _supportWebGL = true;
            }
            if (_supportWebGL && sys.os === sys.OS_ANDROID) {
                var browserVer = parseFloat(sys.browserVersion);
                switch (sys.browserType) {
                case sys.BROWSER_TYPE_MOBILE_QQ:
                case sys.BROWSER_TYPE_BAIDU:
                case sys.BROWSER_TYPE_BAIDU_APP:
                    if (browserVer >= 6.2) {
                        _supportWebGL = true;
                    }
                    else {
                        _supportWebGL = false;
                    }
                    break;
                case sys.BROWSER_TYPE_CHROME:
                    if(browserVer >= 30.0) {
                      _supportWebGL = true;
                    } else {
                      _supportWebGL = false;
                    }
                    break;
                case sys.BROWSER_TYPE_ANDROID:
                    if (sys.osMainVersion && sys.osMainVersion >= 5) {
                        _supportWebGL = true;
                    }
                    break;
                case sys.BROWSER_TYPE_UNKNOWN:
                case sys.BROWSER_TYPE_360:
                case sys.BROWSER_TYPE_MIUI:
                case sys.BROWSER_TYPE_UC:
                    _supportWebGL = false;
                }
            }
        }
        catch (e) {}
        tmpCanvas = null;
    }
    var capabilities = sys.capabilities = {
        "canvas": _supportCanvas,
        "opengl": _supportWebGL
    };
    if (docEle['ontouchstart'] !== undefined || doc['ontouchstart'] !== undefined || nav.msPointerEnabled)
        capabilities["touches"] = true;
    if (docEle['onmouseup'] !== undefined)
        capabilities["mouse"] = true;
    if (docEle['onkeyup'] !== undefined)
        capabilities["keyboard"] = true;
    if (win.DeviceMotionEvent || win.DeviceOrientationEvent)
        capabilities["accelerometer"] = true;
    sys.garbageCollect = function () {
    };
    sys.dumpRoot = function () {
    };
    sys.restartVM = function () {
    };
    sys.cleanScript = function (jsfile) {
    };
    sys.isObjectValid = function (obj) {
        if (obj) return true;
        else return false;
    };
    sys.dump = function () {
        var self = this;
        var str = "";
        str += "isMobile : " + self.isMobile + "\r\n";
        str += "language : " + self.language + "\r\n";
        str += "browserType : " + self.browserType + "\r\n";
        str += "browserVersion : " + self.browserVersion + "\r\n";
        str += "capabilities : " + JSON.stringify(self.capabilities) + "\r\n";
        str += "os : " + self.os + "\r\n";
        str += "osVersion : " + self.osVersion + "\r\n";
        str += "platform : " + self.platform + "\r\n";
        str += "Using " + (cc._renderType === cc.game.RENDER_TYPE_WEBGL ? "WEBGL" : "CANVAS") + " renderer." + "\r\n";
        cc.log(str);
    };
    sys.openURL = function(url){
        window.open(url);
    };
};
_initSys();
_tmpCanvas1 = null;
_tmpCanvas2 = null;
cc.log = cc.warn = cc.error = cc.assert = function () {
};
var _config = null,
    _jsAddedCache = {},
    _engineInitCalled = false,
    _engineLoadedCallback = null;
cc._engineLoaded = false;
function _determineRenderType(config) {
    var CONFIG_KEY = cc.game.CONFIG_KEY,
        userRenderMode = parseInt(config[CONFIG_KEY.renderMode]) || 0;
    if (isNaN(userRenderMode) || userRenderMode > 2 || userRenderMode < 0)
        config[CONFIG_KEY.renderMode] = 0;
    cc._renderType = cc.game.RENDER_TYPE_CANVAS;
    cc._supportRender = false;
    if (userRenderMode === 0) {
        if (cc.sys.capabilities["opengl"]) {
            cc._renderType = cc.game.RENDER_TYPE_WEBGL;
            cc._supportRender = true;
        }
        else if (cc.sys.capabilities["canvas"]) {
            cc._renderType = cc.game.RENDER_TYPE_CANVAS;
            cc._supportRender = true;
        }
    }
    else if (userRenderMode === 1 && cc.sys.capabilities["canvas"]) {
        cc._renderType = cc.game.RENDER_TYPE_CANVAS;
        cc._supportRender = true;
    }
    else if (userRenderMode === 2 && cc.sys.capabilities["opengl"]) {
        cc._renderType = cc.game.RENDER_TYPE_WEBGL;
        cc._supportRender = true;
    }
}
function _getJsListOfModule(moduleMap, moduleName, dir) {
    if (_jsAddedCache[moduleName]) return null;
    dir = dir || "";
    var jsList = [];
    var tempList = moduleMap[moduleName];
    if (!tempList) throw new Error("can not find module [" + moduleName + "]");
    var ccPath = cc.path;
    for (var i = 0, li = tempList.length; i < li; i++) {
        var item = tempList[i];
        if (_jsAddedCache[item]) continue;
        var extname = ccPath.extname(item);
        if (!extname) {
            var arr = _getJsListOfModule(moduleMap, item, dir);
            if (arr) jsList = jsList.concat(arr);
        } else if (extname.toLowerCase() === ".js") jsList.push(ccPath.join(dir, item));
        _jsAddedCache[item] = 1;
    }
    return jsList;
}
function _afterEngineLoaded(config) {
    if (cc._initDebugSetting)
        cc._initDebugSetting(config[cc.game.CONFIG_KEY.debugMode]);
    cc._engineLoaded = true;
    cc.log(cc.ENGINE_VERSION);
    if (_engineLoadedCallback) _engineLoadedCallback();
}
function _load(config) {
    var self = this;
    var CONFIG_KEY = cc.game.CONFIG_KEY, engineDir = config[CONFIG_KEY.engineDir], loader = cc.loader;
    if (cc.Class) {
        _afterEngineLoaded(config);
    } else {
        var ccModulesPath = cc.path.join(engineDir, "moduleConfig.json");
        loader.loadJson(ccModulesPath, function (err, modulesJson) {
            if (err) throw new Error(err);
            var modules = config["modules"] || [];
            var moduleMap = modulesJson["module"];
            var jsList = [];
            if (cc.sys.capabilities["opengl"] && modules.indexOf("base4webgl") < 0) modules.splice(0, 0, "base4webgl");
            else if (modules.indexOf("core") < 0) modules.splice(0, 0, "core");
            for (var i = 0, li = modules.length; i < li; i++) {
                var arr = _getJsListOfModule(moduleMap, modules[i], engineDir);
                if (arr) jsList = jsList.concat(arr);
            }
            cc.loader.loadJsWithImg(jsList, function (err) {
                if (err) throw err;
                _afterEngineLoaded(config);
            });
        });
    }
}
function _windowLoaded() {
    this.removeEventListener('load', _windowLoaded, false);
    _load(cc.game.config);
}
cc.initEngine = function (config, cb) {
    if (_engineInitCalled) {
        var previousCallback = _engineLoadedCallback;
        _engineLoadedCallback = function () {
            previousCallback && previousCallback();
            cb && cb();
        }
        return;
    }
    _engineLoadedCallback = cb;
    if (!cc.game.config && config) {
        cc.game.config = config;
    }
    else if (!cc.game.config) {
        cc.game._loadConfig();
    }
    config = cc.game.config;
    _determineRenderType(config);
    document.body ? _load(config) : cc._addEventListener(window, 'load', _windowLoaded, false);
    _engineInitCalled = true;
};
})();
cc.game = {
    DEBUG_MODE_NONE: 0,
    DEBUG_MODE_INFO: 1,
    DEBUG_MODE_WARN: 2,
    DEBUG_MODE_ERROR: 3,
    DEBUG_MODE_INFO_FOR_WEB_PAGE: 4,
    DEBUG_MODE_WARN_FOR_WEB_PAGE: 5,
    DEBUG_MODE_ERROR_FOR_WEB_PAGE: 6,
    EVENT_HIDE: "game_on_hide",
    EVENT_SHOW: "game_on_show",
    EVENT_RESIZE: "game_on_resize",
    EVENT_RENDERER_INITED: "renderer_inited",
    RENDER_TYPE_CANVAS: 0,
    RENDER_TYPE_WEBGL: 1,
    RENDER_TYPE_OPENGL: 2,
    _eventHide: null,
    _eventShow: null,
    CONFIG_KEY: {
        width: "width",
        height: "height",
        engineDir: "engineDir",
        modules: "modules",
        debugMode: "debugMode",
        showFPS: "showFPS",
        frameRate: "frameRate",
        id: "id",
        renderMode: "renderMode",
        jsList: "jsList"
    },
    _paused: true,//whether the game is paused
    _prepareCalled: false,//whether the prepare function has been called
    _prepared: false,//whether the engine has prepared
    _rendererInitialized: false,
    _renderContext: null,
    _intervalId: null,//interval target of main
    _lastTime: null,
    _frameTime: null,
    frame: null,
    container: null,
    canvas: null,
    config: null,
    onStart: null,
    onStop: null,
    setFrameRate: function (frameRate) {
        var self = this, config = self.config, CONFIG_KEY = self.CONFIG_KEY;
        config[CONFIG_KEY.frameRate] = frameRate;
        if (self._intervalId)
            window.cancelAnimationFrame(self._intervalId);
        self._paused = true;
        self._setAnimFrame();
        self._runMainLoop();
    },
    step: function () {
        cc.director.mainLoop();
    },
    pause: function () {
        if (this._paused) return;
        this._paused = true;
        if (cc.audioEngine) {
            cc.audioEngine.stopAllEffects();
            cc.audioEngine.pauseMusic();
        }
        if (this._intervalId)
            window.cancelAnimationFrame(this._intervalId);
        this._intervalId = 0;
    },
    resume: function () {
        if (!this._paused) return;
        this._paused = false;
        if (cc.audioEngine) {
            cc.audioEngine.resumeMusic();
        }
        this._runMainLoop();
    },
    isPaused: function () {
        return this._paused;
    },
    restart: function () {
        cc.director.popToSceneStackLevel(0);
        cc.audioEngine && cc.audioEngine.end();
        cc.game.onStart();
    },
    end: function () {
        close();
    },
    prepare: function (cb) {
        var self = this,
            config = self.config,
            CONFIG_KEY = self.CONFIG_KEY;
        this._loadConfig();
        if (this._prepared) {
            if (cb) cb();
            return;
        }
        if (this._prepareCalled) {
            return;
        }
        if (cc._engineLoaded) {
            this._prepareCalled = true;
            this._initRenderer(config[CONFIG_KEY.width], config[CONFIG_KEY.height]);
            cc.view = cc.EGLView._getInstance();
            cc.director = cc.Director._getInstance();
            if (cc.director.setOpenGLView)
                cc.director.setOpenGLView(cc.view);
            cc.winSize = cc.director.getWinSize();
            this._initEvents();
            this._setAnimFrame();
            this._runMainLoop();
            var jsList = config[CONFIG_KEY.jsList];
            if (jsList) {
                cc.loader.loadJsWithImg(jsList, function (err) {
                    if (err) throw new Error(err);
                    self._prepared = true;
                    if (cb) cb();
                });
            }
            else {
                if (cb) cb();
            }
            return;
        }
        cc.initEngine(this.config, function () {
            self.prepare(cb);
        });
    },
    run: function (config, onStart) {
        if (typeof config === 'function') {
            cc.game.onStart = config;
        }
        else {
            if (config) {
                if (typeof config === 'string') {
                    if (!cc.game.config) this._loadConfig();
                    cc.game.config[cc.game.CONFIG_KEY.id] = config;
                } else {
                    cc.game.config = config;
                }
            }
            if (typeof onStart === 'function') {
                cc.game.onStart = onStart;
            }
        }
        this.prepare(cc.game.onStart && cc.game.onStart.bind(cc.game));
    },
    _setAnimFrame: function () {
        this._lastTime = new Date();
        this._frameTime = 1000 / cc.game.config[cc.game.CONFIG_KEY.frameRate];
        if((cc.sys.os === cc.sys.OS_IOS && cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT) || cc.game.config[cc.game.CONFIG_KEY.frameRate] !== 60) {
            window.requestAnimFrame = this._stTime;
            window.cancelAnimationFrame = this._ctTime;
        }
        else {
            window.requestAnimFrame = window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            this._stTime;
            window.cancelAnimationFrame = window.cancelAnimationFrame ||
            window.cancelRequestAnimationFrame ||
            window.msCancelRequestAnimationFrame ||
            window.mozCancelRequestAnimationFrame ||
            window.oCancelRequestAnimationFrame ||
            window.webkitCancelRequestAnimationFrame ||
            window.msCancelAnimationFrame ||
            window.mozCancelAnimationFrame ||
            window.webkitCancelAnimationFrame ||
            window.oCancelAnimationFrame ||
            this._ctTime;
        }
    },
    _stTime: function(callback){
        var currTime = new Date().getTime();
        var timeToCall = Math.max(0, cc.game._frameTime - (currTime - cc.game._lastTime));
        var id = window.setTimeout(function() { callback(); },
            timeToCall);
        cc.game._lastTime = currTime + timeToCall;
        return id;
    },
    _ctTime: function(id){
        window.clearTimeout(id);
    },
    _runMainLoop: function () {
        var self = this, callback, config = self.config, CONFIG_KEY = self.CONFIG_KEY,
            director = cc.director;
        director.setDisplayStats(config[CONFIG_KEY.showFPS]);
        callback = function () {
            if (!self._paused) {
                director.mainLoop();
                if(self._intervalId)
                    window.cancelAnimationFrame(self._intervalId);
                self._intervalId = window.requestAnimFrame(callback);
            }
        };
        window.requestAnimFrame(callback);
        self._paused = false;
    },
    _loadConfig: function () {
        if (this.config) {
            this._initConfig(this.config);
            return;
        }
        if (document["ccConfig"]) {
            this._initConfig(document["ccConfig"]);
        }
        else {
            var data = {};
            try {
                var cocos_script = document.getElementsByTagName('script');
                for(var i = 0; i < cocos_script.length; i++){
                    var _t = cocos_script[i].getAttribute('cocos');
                    if(_t === '' || _t) {
                        break;
                    }
                }
                var _src, txt, _resPath;
                if(i < cocos_script.length){
                    _src = cocos_script[i].src;
                    if(_src){
                        _resPath = /(.*)\//.exec(_src)[0];
                        cc.loader.resPath = _resPath;
                        _src = cc.path.join(_resPath, 'project.json');
                    }
                    txt = cc.loader._loadTxtSync(_src);
                }
                if(!txt){
                    txt = cc.loader._loadTxtSync("project.json");
                }
                data = JSON.parse(txt);
            } catch (e) {
                cc.log("Failed to read or parse project.json");
            }
            this._initConfig(data);
        }
    },
    _initConfig: function (config) {
        var CONFIG_KEY = this.CONFIG_KEY,
            modules = config[CONFIG_KEY.modules];
        config[CONFIG_KEY.showFPS] = typeof config[CONFIG_KEY.showFPS] === 'undefined' ? true : config[CONFIG_KEY.showFPS];
        config[CONFIG_KEY.engineDir] = config[CONFIG_KEY.engineDir] || "frameworks/cocos2d-html5";
        if (config[CONFIG_KEY.debugMode] == null)
            config[CONFIG_KEY.debugMode] = 0;
        config[CONFIG_KEY.frameRate] = config[CONFIG_KEY.frameRate] || 60;
        if (config[CONFIG_KEY.renderMode] == null)
            config[CONFIG_KEY.renderMode] = 0;
        if (config[CONFIG_KEY.registerSystemEvent] == null)
            config[CONFIG_KEY.registerSystemEvent] = true;
        if (modules && modules.indexOf("core") < 0) modules.splice(0, 0, "core");
        modules && (config[CONFIG_KEY.modules] = modules);
        this.config = config;
    },
    _initRenderer: function (width, height) {
        if (this._rendererInitialized) return;
        if (!cc._supportRender) {
            throw new Error("The renderer doesn't support the renderMode " + this.config[this.CONFIG_KEY.renderMode]);
        }
        var el = this.config[cc.game.CONFIG_KEY.id],
            win = window,
            element = cc.$(el) || cc.$('#' + el),
            localCanvas, localContainer, localConStyle;
        if (element.tagName === "CANVAS") {
            width = width || element.width;
            height = height || element.height;
            this.canvas = cc._canvas = localCanvas = element;
            this.container = cc.container = localContainer = document.createElement("DIV");
            if (localCanvas.parentNode)
                localCanvas.parentNode.insertBefore(localContainer, localCanvas);
        } else {
            if (element.tagName !== "DIV") {
                cc.log("Warning: target element is not a DIV or CANVAS");
            }
            width = width || element.clientWidth;
            height = height || element.clientHeight;
            this.canvas = cc._canvas = localCanvas = document.createElement("CANVAS");
            this.container = cc.container = localContainer = document.createElement("DIV");
            element.appendChild(localContainer);
        }
        localContainer.setAttribute('id', 'Cocos2dGameContainer');
        localContainer.appendChild(localCanvas);
        this.frame = (localContainer.parentNode === document.body) ? document.documentElement : localContainer.parentNode;
        localCanvas.addClass("gameCanvas");
        localCanvas.setAttribute("width", width || 480);
        localCanvas.setAttribute("height", height || 320);
        localCanvas.setAttribute("tabindex", 99);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
            this._renderContext = cc._renderContext = cc.webglContext
             = cc.create3DContext(localCanvas, {
                'stencil': true,
                'antialias': !cc.sys.isMobile,
                'alpha': false
            });
        }
        if (this._renderContext) {
            cc.renderer = cc.rendererWebGL;
            win.gl = this._renderContext;
            cc.renderer.init();
            cc.shaderCache._init();
            cc._drawingUtil = new cc.DrawingPrimitiveWebGL(this._renderContext);
            cc.textureCache._initializingRenderer();
            cc.glExt = {};
            cc.glExt.instanced_arrays = win.gl.getExtension("ANGLE_instanced_arrays");
            cc.glExt.element_uint = win.gl.getExtension("OES_element_index_uint");
        } else {
            cc._renderType = cc.game.RENDER_TYPE_CANVAS;
            cc.renderer = cc.rendererCanvas;
            this._renderContext = cc._renderContext = new cc.CanvasContextWrapper(localCanvas.getContext("2d"));
            cc._drawingUtil = cc.DrawingPrimitiveCanvas ? new cc.DrawingPrimitiveCanvas(this._renderContext) : null;
        }
        cc._gameDiv = localContainer;
        cc.game.canvas.oncontextmenu = function () {
            if (!cc._isContextMenuEnable) return false;
        };
        this.dispatchEvent(this.EVENT_RENDERER_INITED, true);
        this._rendererInitialized = true;
    },
    _initEvents: function () {
        var win = window, self = this, hidden, visibilityChange, _undef = "undefined";
        this._eventHide = this._eventHide || new cc.EventCustom(this.EVENT_HIDE);
        this._eventHide.setUserData(this);
        this._eventShow = this._eventShow || new cc.EventCustom(this.EVENT_SHOW);
        this._eventShow.setUserData(this);
        if (this.config[this.CONFIG_KEY.registerSystemEvent])
            cc.inputManager.registerSystemEvent(this.canvas);
        if (!cc.isUndefined(document.hidden)) {
            hidden = "hidden";
            visibilityChange = "visibilitychange";
        } else if (!cc.isUndefined(document.mozHidden)) {
            hidden = "mozHidden";
            visibilityChange = "mozvisibilitychange";
        } else if (!cc.isUndefined(document.msHidden)) {
            hidden = "msHidden";
            visibilityChange = "msvisibilitychange";
        } else if (!cc.isUndefined(document.webkitHidden)) {
            hidden = "webkitHidden";
            visibilityChange = "webkitvisibilitychange";
        }
        var onHidden = function () {
            if (cc.eventManager && cc.game._eventHide)
                cc.eventManager.dispatchEvent(cc.game._eventHide);
        };
        var onShow = function () {
            if (cc.eventManager && cc.game._eventShow)
                cc.eventManager.dispatchEvent(cc.game._eventShow);
        };
        if (hidden) {
            document.addEventListener(visibilityChange, function () {
                if (document[hidden]) onHidden();
                else onShow();
            }, false);
        } else {
            win.addEventListener("blur", onHidden, false);
            win.addEventListener("focus", onShow, false);
        }
        if(navigator.userAgent.indexOf("MicroMessenger") > -1){
            win.onfocus = function(){ onShow() };
        }
        if ("onpageshow" in window && "onpagehide" in window) {
            win.addEventListener("pagehide", onHidden, false);
            win.addEventListener("pageshow", onShow, false);
        }
        cc.eventManager.addCustomListener(cc.game.EVENT_HIDE, function () {
            cc.game.pause();
        });
        cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () {
            cc.game.resume();
        });
    }
};
Function.prototype.bind = Function.prototype.bind || function (oThis) {
    if (!cc.isFunction(this)) {
        throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }
    var aArgs = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP = function () {},
        fBound = function () {
            return fToBind.apply(this instanceof fNOP && oThis
                ? this
                : oThis,
                aArgs.concat(Array.prototype.slice.call(arguments)));
        };
    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
};
cc._urlRegExp = new RegExp(
    "^" +
        "(?:(?:https?|ftp)://)" +
        "(?:\\S+(?::\\S*)?@)?" +
        "(?:" +
            "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
            "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
            "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
        "|" +
            "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
            "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
            "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
        "|" +
            "(?:localhost)" +
        ")" +
        "(?::\\d{2,5})?" +
        "(?:/\\S*)?" +
    "$", "i"
);
cc.SimplePool = function () {
    this._pool = [];
};
cc.SimplePool.prototype = {
    constructor: cc.SimplePool,
    size: function () {
        return this._pool.length;
    },
    put: function (obj) {
        if (obj && this._pool.indexOf(obj) === -1) {
            this._pool.unshift(obj);
        }
    },
    get: function () {
        var last = this._pool.length-1;
        if (last < 0) {
            return null;
        }
        else {
            var obj = this._pool[last];
            this._pool.length = last;
            return obj;
        }
    },
    find: function (finder, end) {
        var found, i, obj, pool = this._pool, last = pool.length-1;
        for (i = pool.length; i >= 0; --i) {
            obj = pool[i];
            found = finder(i, obj);
            if (found) {
                pool[i] = pool[last];
                pool.length = last;
                return obj;
            }
        }
        if (end) {
            var index = end();
            if (index >= 0) {
                pool[index] = pool[last];
                pool.length = last;
                return obj;
            }
        }
        return null;
    }
};
cc.EventHelper = function(){};
cc.EventHelper.prototype = {
    constructor: cc.EventHelper,
    apply: function ( object ) {
        object.addEventListener = cc.EventHelper.prototype.addEventListener;
        object.hasEventListener = cc.EventHelper.prototype.hasEventListener;
        object.removeEventListener = cc.EventHelper.prototype.removeEventListener;
        object.dispatchEvent = cc.EventHelper.prototype.dispatchEvent;
    },
    addEventListener: function ( type, listener, target ) {
        if(type === "load" && this._textureLoaded){
            setTimeout(function(){
                listener.call(target);
            }, 0);
            return;
        }
        if ( this._listeners === undefined )
            this._listeners = {};
        var listeners = this._listeners;
        if ( listeners[ type ] === undefined )
            listeners[ type ] = [];
        if ( !this.hasEventListener(type, listener, target))
            listeners[ type ].push( {callback:listener, eventTarget: target} );
    },
    hasEventListener: function ( type, listener, target ) {
        if ( this._listeners === undefined )
            return false;
        var listeners = this._listeners;
        if ( listeners[ type ] !== undefined ) {
            for(var i = 0, len = listeners.length; i < len ; i++){
                var selListener = listeners[i];
                if(selListener.callback === listener && selListener.eventTarget === target)
                    return true;
            }
        }
        return false;
    },
    removeEventListener: function( type, listener, target){
        if ( this._listeners === undefined )
            return;
        var listeners = this._listeners;
        var listenerArray = listeners[ type ];
        if ( listenerArray !== undefined ) {
            for(var i = 0; i < listenerArray.length ; ){
                var selListener = listenerArray[i];
                if(selListener.eventTarget === target && selListener.callback === listener)
                    listenerArray.splice( i, 1 );
                else
                    i++
            }
        }
    },
    removeEventTarget: function( type, listener, target){
        if ( this._listeners === undefined )
            return;
        var listeners = this._listeners;
        var listenerArray = listeners[ type ];
        if ( listenerArray !== undefined ) {
            for(var i = 0; i < listenerArray.length ; ){
                var selListener = listenerArray[i];
                if(selListener.eventTarget === target)
                    listenerArray.splice( i, 1 );
                else
                    i++
            }
        }
    },
    dispatchEvent: function ( event, clearAfterDispatch ) {
        if ( this._listeners === undefined )
            return;
        if(clearAfterDispatch == null)
            clearAfterDispatch = true;
        var listeners = this._listeners;
        var listenerArray = listeners[ event];
        if ( listenerArray !== undefined ) {
            var array = [];
            var length = listenerArray.length;
            for ( var i = 0; i < length; i ++ ) {
                array[ i ] = listenerArray[ i ];
            }
            for ( i = 0; i < length; i ++ ) {
                array[ i ].callback.call( array[i].eventTarget, this );
            }
            if(clearAfterDispatch)
                listenerArray.length = 0;
        }
    }
};
cc.EventHelper.prototype.apply(cc.game);
var cc = cc || {};
cc._loadingImage = "data:image/gif;base64,R0lGODlhEAAQALMNAD8/P7+/vyoqKlVVVX9/fxUVFUBAQGBgYMDAwC8vL5CQkP///wAAAP///wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAANACwAAAAAEAAQAAAEO5DJSau9OOvNex0IMnDIsiCkiW6g6BmKYlBFkhSUEgQKlQCARG6nEBwOgl+QApMdCIRD7YZ5RjlGpCUCACH5BAUAAA0ALAAAAgAOAA4AAAQ6kLGB0JA4M7QW0hrngRllkYyhKAYqKUGguAws0ypLS8JxCLQDgXAIDg+FRKIA6v0SAECCBpXSkstMBAAh+QQFAAANACwAAAAACgAQAAAEOJDJORAac6K1kDSKYmydpASBUl0mqmRfaGTCcQgwcxDEke+9XO2WkxQSiUIuAQAkls0n7JgsWq8RACH5BAUAAA0ALAAAAAAOAA4AAAQ6kMlplDIzTxWC0oxwHALnDQgySAdBHNWFLAvCukc215JIZihVIZEogDIJACBxnCSXTcmwGK1ar1hrBAAh+QQFAAANACwAAAAAEAAKAAAEN5DJKc4RM+tDyNFTkSQF5xmKYmQJACTVpQSBwrpJNteZSGYoFWjIGCAQA2IGsVgglBOmEyoxIiMAIfkEBQAADQAsAgAAAA4ADgAABDmQSVZSKjPPBEDSGucJxyGA1XUQxAFma/tOpDlnhqIYN6MEAUXvF+zldrMBAjHoIRYLhBMqvSmZkggAIfkEBQAADQAsBgAAAAoAEAAABDeQyUmrnSWlYhMASfeFVbZdjHAcgnUQxOHCcqWylKEohqUEAYVkgEAMfkEJYrFA6HhKJsJCNFoiACH5BAUAAA0ALAIAAgAOAA4AAAQ3kMlJq704611SKloCAEk4lln3DQgyUMJxCBKyLAh1EMRR3wiDQmHY9SQslyIQUMRmlmVTIyRaIgA7";
cc._fpsImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAgCAYAAAD9qabkAAAKQ2lDQ1BJQ0MgcHJvZmlsZQAAeNqdU3dYk/cWPt/3ZQ9WQtjwsZdsgQAiI6wIyBBZohCSAGGEEBJAxYWIClYUFRGcSFXEgtUKSJ2I4qAouGdBiohai1VcOO4f3Ke1fXrv7e371/u855zn/M55zw+AERImkeaiagA5UoU8Otgfj09IxMm9gAIVSOAEIBDmy8JnBcUAAPADeXh+dLA//AGvbwACAHDVLiQSx+H/g7pQJlcAIJEA4CIS5wsBkFIAyC5UyBQAyBgAsFOzZAoAlAAAbHl8QiIAqg0A7PRJPgUA2KmT3BcA2KIcqQgAjQEAmShHJAJAuwBgVYFSLALAwgCgrEAiLgTArgGAWbYyRwKAvQUAdo5YkA9AYACAmUIszAAgOAIAQx4TzQMgTAOgMNK/4KlfcIW4SAEAwMuVzZdL0jMUuJXQGnfy8ODiIeLCbLFCYRcpEGYJ5CKcl5sjE0jnA0zODAAAGvnRwf44P5Dn5uTh5mbnbO/0xaL+a/BvIj4h8d/+vIwCBAAQTs/v2l/l5dYDcMcBsHW/a6lbANpWAGjf+V0z2wmgWgrQevmLeTj8QB6eoVDIPB0cCgsL7SViob0w44s+/zPhb+CLfvb8QB7+23rwAHGaQJmtwKOD/XFhbnauUo7nywRCMW735yP+x4V//Y4p0eI0sVwsFYrxWIm4UCJNx3m5UpFEIcmV4hLpfzLxH5b9CZN3DQCshk/ATrYHtctswH7uAQKLDljSdgBAfvMtjBoLkQAQZzQyefcAAJO/+Y9AKwEAzZek4wAAvOgYXKiUF0zGCAAARKCBKrBBBwzBFKzADpzBHbzAFwJhBkRADCTAPBBCBuSAHAqhGJZBGVTAOtgEtbADGqARmuEQtMExOA3n4BJcgetwFwZgGJ7CGLyGCQRByAgTYSE6iBFijtgizggXmY4EImFINJKApCDpiBRRIsXIcqQCqUJqkV1II/ItchQ5jVxA+pDbyCAyivyKvEcxlIGyUQPUAnVAuagfGorGoHPRdDQPXYCWomvRGrQePYC2oqfRS+h1dAB9io5jgNExDmaM2WFcjIdFYIlYGibHFmPlWDVWjzVjHVg3dhUbwJ5h7wgkAouAE+wIXoQQwmyCkJBHWExYQ6gl7CO0EroIVwmDhDHCJyKTqE+0JXoS+cR4YjqxkFhGrCbuIR4hniVeJw4TX5NIJA7JkuROCiElkDJJC0lrSNtILaRTpD7SEGmcTCbrkG3J3uQIsoCsIJeRt5APkE+S+8nD5LcUOsWI4kwJoiRSpJQSSjVlP+UEpZ8yQpmgqlHNqZ7UCKqIOp9aSW2gdlAvU4epEzR1miXNmxZDy6Qto9XQmmlnafdoL+l0ugndgx5Fl9CX0mvoB+nn6YP0dwwNhg2Dx0hiKBlrGXsZpxi3GS+ZTKYF05eZyFQw1zIbmWeYD5hvVVgq9ip8FZHKEpU6lVaVfpXnqlRVc1U/1XmqC1SrVQ+rXlZ9pkZVs1DjqQnUFqvVqR1Vu6k2rs5Sd1KPUM9RX6O+X/2C+mMNsoaFRqCGSKNUY7fGGY0hFsYyZfFYQtZyVgPrLGuYTWJbsvnsTHYF+xt2L3tMU0NzqmasZpFmneZxzQEOxrHg8DnZnErOIc4NznstAy0/LbHWaq1mrX6tN9p62r7aYu1y7Rbt69rvdXCdQJ0snfU6bTr3dQm6NrpRuoW623XP6j7TY+t56Qn1yvUO6d3RR/Vt9KP1F+rv1u/RHzcwNAg2kBlsMThj8MyQY+hrmGm40fCE4agRy2i6kcRoo9FJoye4Ju6HZ+M1eBc+ZqxvHGKsNN5l3Gs8YWJpMtukxKTF5L4pzZRrmma60bTTdMzMyCzcrNisyeyOOdWca55hvtm82/yNhaVFnMVKizaLx5balnzLBZZNlvesmFY+VnlW9VbXrEnWXOss623WV2xQG1ebDJs6m8u2qK2brcR2m23fFOIUjynSKfVTbtox7PzsCuya7AbtOfZh9iX2bfbPHcwcEh3WO3Q7fHJ0dcx2bHC866ThNMOpxKnD6VdnG2ehc53zNRemS5DLEpd2lxdTbaeKp26fesuV5RruutK10/Wjm7ub3K3ZbdTdzD3Ffav7TS6bG8ldwz3vQfTw91jicczjnaebp8LzkOcvXnZeWV77vR5Ps5wmntYwbcjbxFvgvct7YDo+PWX6zukDPsY+Ap96n4e+pr4i3z2+I37Wfpl+B/ye+zv6y/2P+L/hefIW8U4FYAHBAeUBvYEagbMDawMfBJkEpQc1BY0FuwYvDD4VQgwJDVkfcpNvwBfyG/ljM9xnLJrRFcoInRVaG/owzCZMHtYRjobPCN8Qfm+m+UzpzLYIiOBHbIi4H2kZmRf5fRQpKjKqLupRtFN0cXT3LNas5Fn7Z72O8Y+pjLk722q2cnZnrGpsUmxj7Ju4gLiquIF4h/hF8ZcSdBMkCe2J5MTYxD2J43MC52yaM5zkmlSWdGOu5dyiuRfm6c7Lnnc8WTVZkHw4hZgSl7I/5YMgQlAvGE/lp25NHRPyhJuFT0W+oo2iUbG3uEo8kuadVpX2ON07fUP6aIZPRnXGMwlPUit5kRmSuSPzTVZE1t6sz9lx2S05lJyUnKNSDWmWtCvXMLcot09mKyuTDeR55m3KG5OHyvfkI/lz89sVbIVM0aO0Uq5QDhZML6greFsYW3i4SL1IWtQz32b+6vkjC4IWfL2QsFC4sLPYuHhZ8eAiv0W7FiOLUxd3LjFdUrpkeGnw0n3LaMuylv1Q4lhSVfJqedzyjlKD0qWlQyuCVzSVqZTJy26u9Fq5YxVhlWRV72qX1VtWfyoXlV+scKyorviwRrjm4ldOX9V89Xlt2treSrfK7etI66Trbqz3Wb+vSr1qQdXQhvANrRvxjeUbX21K3nShemr1js20zcrNAzVhNe1bzLas2/KhNqP2ep1/XctW/a2rt77ZJtrWv913e/MOgx0VO97vlOy8tSt4V2u9RX31btLugt2PGmIbur/mft24R3dPxZ6Pe6V7B/ZF7+tqdG9s3K+/v7IJbVI2jR5IOnDlm4Bv2pvtmne1cFoqDsJB5cEn36Z8e+NQ6KHOw9zDzd+Zf7f1COtIeSvSOr91rC2jbaA9ob3v6IyjnR1eHUe+t/9+7zHjY3XHNY9XnqCdKD3x+eSCk+OnZKeenU4/PdSZ3Hn3TPyZa11RXb1nQ8+ePxd07ky3X/fJ897nj13wvHD0Ivdi2yW3S609rj1HfnD94UivW2/rZffL7Vc8rnT0Tes70e/Tf/pqwNVz1/jXLl2feb3vxuwbt24m3Ry4Jbr1+Hb27Rd3Cu5M3F16j3iv/L7a/eoH+g/qf7T+sWXAbeD4YMBgz8NZD+8OCYee/pT/04fh0kfMR9UjRiONj50fHxsNGr3yZM6T4aeypxPPyn5W/3nrc6vn3/3i+0vPWPzY8Av5i8+/rnmp83Lvq6mvOscjxx+8znk98ab8rc7bfe+477rfx70fmSj8QP5Q89H6Y8en0E/3Pud8/vwv94Tz+4A5JREAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcAgcQLxxUBNp/AAAQZ0lEQVR42u2be3QVVZbGv1N17829eRLyIKAEOiISEtPhJTJAYuyBDmhWjAEx4iAGBhxA4wABbVAMWUAeykMCM+HRTcBRWkNH2l5moS0LCCrQTkYeQWBQSCAIgYRXEpKbW/XNH5zS4noR7faPEeu31l0h4dSpvc+t/Z199jkFWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY/H9D/MR9qfKnLj/00U71aqfJn9+HCkCR/Wk36ddsgyJ/1wF4fkDfqqm9/gPsUeTnVr6a2xlQfnxdI7zs0W7irzD17Ytb2WT7EeNv/r4ox1O3Quf2QP2pgt9utwfout4FQE8AVBSlnaRmfvAURQkg2RlAbwB9AThlW5L0GaiKojhJhgOIBqDa7XaPrusdPtr5kQwF0BVAAoBIABRCKDd5aFUhRDAAw57eAOwAhKIoupft3zoqhB1AqLwuHIBut9uFt02qqvqRDJR2dAEQJj/BAOjn56dqmma+xiaECAEQAWAggLsB6A6HQ2iaZggBhBAqgEAAnQB0kzaEmT4hAITT6VQ8Ho/HJAKKECJQtr8LwD1y/A1/vcdfEUIEyfZ9AcQbYvZ942Px88L2UwlJR0dH0EMPPbRj5syZPUeNGrXR7Xb/641xIwJ1XY9NSUlZm52dfW+XLl1w8uRJzJ8//+OGhoYJqqqe1TSt1Wsm9NN1PSIqKmr12rVrR5WUlHy1bdu2AQCumWc3IYRD1/UwVVXnFRQUTIuNjUVzczN2797dWFJSkq8oymZd15sAGAEnFEUJ1nX9nzIzM1dnZmZGh4SE4OTJk5g5c+Zf29vbp9pstrMej6fVOyhIhgAYU1hY+B+hoaGoqKg4XVlZea+XTULTNFdCQsLGiRMnPuR2u3UhBOV9eeDAAWXTpk095DUe6WsoyRE5OTlr0tLSAux2O/bs2cO5c+e+pijKUpIXSHaQVAGkvPLKK++6XK4OksJLCFlXV2cvKSlJBFAjhU+x2WwhHo9nUHp6+urMzMy7wsLCUF9fjxdffPHjxsbGiTab7WuPx9NiEutOuq4PyMjI+M+srKyYqKgoHD58GDNmzNjq8XhyVFU9b/q+LH7hBAEYu3PnTlZVVRFAGgCX6f/tAHoOHDjwa0p27txp/JO9e/f+QM7cipw9nfL3kQBKt2zZQpJ87rnn6mQmoHilw2EACs+cOUOSrK+vZ1NTE0nyo48+IoBpxswoBcMJ4Ndjx471kOTFixe5d+9ekqTH42H//v13A4jyzpAURfEH0H/OnDnthu1z5sw558MmFUCPWbNmnaMP3nrrLZoyDmP8Hl68eDFJ8siRI9/Yc+zYMQKYKdtAztrTrl27xptRXV1NAKMAOAyBBBA/Y8aMdpLs6Ojgxx9//E37+++//29yvFXppwvAwMcee8xjtDHsuXLlCqOjo//ia3wsfpkoALqFhoZuIckJEyackimm3dQmEMDUmpoakmRISMhhAHOHDx/eQJIbN24kgKEyMAHAFRMTs2XXrl1saWkhSZ0kp0+ffhrAr3wEW/S8efOukORLL72kA1gKYMPWrVtJkk899dRJAHeYrgsEsIQkjx8/TgDvAPjd448/3kaSb7zxBmUa7vC6z53BwcFbSHL9+vU6Sc6aNes8gF5ewWAH0PfVV18lSQL4DMBGIcQ6AKtcLleBFC2jXtFt8ODBe0iyoqKCAJYByC8qKmJDQwOzsrK+MAmqo1OnTveHhoa+GRkZ+XZkZOSWiIiIvzgcjk9mzpypkWRmZuZpmbYbGV4AgPnNzc1sa2sjgN0A5iQmJtaSZHl5OQHcb/K3s81mW0uSTU1NBFAFYFbfvn1Pk+Tbb79NAA8IIVzW42/hByA+Pz/fLR/2ZXIda05NI/z9/TeR5J49ewhgqlxTrtI0jY2NjQQw3zTLuWJiYjaUlJToS5Ys6fjkk080kwDEeAmADcA9GzZsIElGRUW9CyAWwLApU6Y0kOSKFSsog9QICGdERMTGsrIyZmVlEcC9AB4IDw/fTpLbtm0jgN94CUAnAJmVlZVcs2aNZ/LkyRdJcvbs2b4EwAkgZfPmzTxw4AABFAN4BkC6vFeUSewcAO5duXIlSTIhIaEawGMAxgKYAmAGgCS73e5vrKVk/yGythANYEhCQsIhkly+fDkBpKqqGmL6DgIALDKN/3yZpVWQZGVlJQE8aPI3KiMjo5okV61aRQAjAPQBMPfIkSN0u90EUCBtsPiFEwpgbn19PdetW2fM5N4zQ9ekpKQqkty0aRMBpMjiWM6JEydIkoqirJUFJ6iq6pAPVy8A6cZMehMBUACEuVyuFwG8HBwcPEIWx367ZMkSjSQXLVrUJouTRorrkAHdA8BdQogsAOsKCwtJkmPGjDkvMw2bDDo/ADEjRoz4XylyFbm5uY0mAbjLyyZ/AOOrq6tZVlbWsWDBgo69e/eyoqKCgwcPPg4gSQaoIRbp27dvN7KF+tLSUr28vJwFBQXtMpvpYRIM7+wrAkDeqVOnePbsWQIoNKfzpiXPg8uXLydJJicnNwF4f+nSpW6STEtLq5fjYwhk1wkTJtSQ5Ouvv04AqTKj+N2xY8dIkgEBAW/Ie1v8wncRegwZMmQvSfbr12+3Ua33WqPfOWbMmP0kWVpaSgCDZAqcfejQIWNZsEGKgvnh9gfQb9myZd8nAEJVVZtMkUNk8CcNHTq0liR1XWdYWNhmH1mJIme80OnTp18x1rp5eXkEsNJms92Fb7e/IgEsvHz5Mp999tkmAI/l5uZeMC0B7vEqqAYAyL106RJJsra2lpWVld+sucePH38ZQG+5NncBeOrgwYMkqbe3t/Po0aOsra011wAWyl0H7x0JJ4DE+fPnu0kyPT29DsDdUrBuyNKEEAkAdpw/f/6GeoEM8GUmfwEgPCIiopwkGxsbabPZPgOw6L777vvm4p49e26VGYjFLxUhhD+ApLKyMp44ccIoVnXybgbgzkcfffRzklyzZg0BDJYCMMmoCwQFBXkLgLGWvvcWAgBToSsKwNPTp09vMR7UuLi4rwH0lgU8c/Db5ezbeeTIkRWzZ8++aMxu+fn5BPCADBwHgP4LFy701NXVEUAJgAnPP/98kyxMNgHo53A4zH77BQQETMvPz7+Um5vbBuAlAFMSExPPmdbVL0qh8Acw8fDhw5SCchVAEYAVb775JknyhRdeaJYztHfxMwLAaqNwCGC2FArv8x0hAHKNLGPKlCme5OTk/Zs3bzb7O0wKiiG8KXl5ed8IxenTp0mSR48e1UmyW7duWywBuD2xyQcgFECgoih+8H1gyJgZV5Lkyy+/3CbTRIePtl2HDBmyw1QBHyGDdXZdXR1JUghRKkXBjOMHCoBdpr0L3nvvPZLkF198wejo6O0A4lVVDTb74HQ6AwD8Wq7Jh8rgGgDgQ13XjVR8qaxJuADMbmlpYXl5uV5UVNRWUFDgfv/993Vj/ZydnU1c37eHXML4S3viAcQqitJD2l104cIFY8lTKsXSBWBMVVWVcd9yed2A1NTUQ6Zl00CvLMMOoHdubm6zFIlWOf5+PsY/Kj09vdrU11QAwwGsv3jxIk21m2DZr10I0RXAuAcffPBgaWkpV69eTYfDcdiwUxY0w6xw+flX8L1xApjevXv3lREREaW6rofB93aPDUDQpEmTMgHgtddeqwBwEd/utZvpqK6uPgEAcXFxkA94NwB9unfvjrNnz4LklwDcf08iIqv66Zs2bXrl4YcfxooVKxAbG7uqrq5uAYA2TdOEqqpGYIi2tjbl6aeffu/YsWPv5uTk7JaC1wHg4Pnz542MwoVvTx+21dbWYvjw4WLixIl+2dnZ9lGjRgmSTE1NRUpKCkwFTGiaxtTU1OXTpk3707Bhw/6g67pDipnT4biuj7qut+Lbk3Vf1tTUXI9qu91Pjq1QFEUBgJaWFgBo8yGOQ8eNGxcAAOvXr/8QwBUfYygAKL169eoCABcuXACAWtn2hOGv0+kMNO1KiPDw8F4A4rZv3/7R1KlTR0+bNu1ht9u9r1+/fqitrQXJgwDarRC6/QjPzs4+QJIffPCB9/aQmSAA43ft2mW0e1QGoi8CAPyLsZccExNTC2BlRkbGRdOyYJCP2csBIN6UAZzCd7cBbQCijYp/dXU1ExMTz6SmptaMHj36f9LS0vYlJCRsl6mxIWSdu3fv/g5J7t+/nwC2AShMTk6+SJKff/45AWRLYbD7+fndAeDf5BJnLoCCyZMnt5JkdnZ2C4B/F0KEm1Pu+Pj4rST55ZdfEsBWAK+mpaVdMo3raDn7KwDuSEpK+m+S3LBhAwG8DuCtHTt2UBbpjgC408vvcFVV15HkuXPnjMp+p5uMf0RcXNyHJNnQ0EBVVfcCWBQXF3fG+Jv0yxABPwB5LS0tRmFxN4BlTzzxxGWSXLx4sS5F3GGFy+1Hp5SUlJq6ujoWFxdTpsZ2H+0iIyMj/0iSWVlZX5mr5jfJFroPGzasxlhTnjp1iiTZ3NxMl8tlrCd9pfa9SkpKSJI5OTmnZOageLUZZqxvfVFWVkZcPwdgNwnSCKPqb17jkmR8fPzfZMDZ5CRsFBmNI7h95s2b1yhT7/MAYmStwCx4vy0uLqa3v5qmEcCfvSr1QQAeXb16NY3Cm3HQ55133iGAp+SxZTNhKSkpfzUddkrFjYevzAQCeGjp0qXfsYckY2NjTwD4leGDLCL2HTdunNtoY+zWSHFcIHdsFCtcfuZ1vO9Eqs3m7/F47sb1k2qX/f3997W2tl7BjWfpBYDOzzzzzIVJkyZh0KBBCwEsB3AJvl9AETabLcDj8dwRFRW1ctasWb8JCgpSzp07d62wsPC/Wltb8xRFadR1/ZqPXYbgAQMGbI2Pjw/+6quv9ldVVT0r01ezuPRJSUn5Y9euXXVd11WzDaqq6kePHm3+7LPPRgO4KlNuxWazhXo8nuTk5OSXMjIyEl0uFxoaGtqKior+dPXq1VdUVT0jj7r68ieoT58+vx8yZMjdx48fP1JVVTVF9m20VW02WyfZf97YsWPjXS4X6urqWvPy8jYCWCyEuEDS8FdVFKWzruv//OSTTy5OTk7uqWkaPv3007qysrJ8RVH+LI8ym8/rB3Tu3HnRI488knLo0KG2ffv2ZQI4C98vP6mqqoZqmpaclpa2cOTIkX39/f3R0NDQUVxc/G5TU9PLqqrWa5rWLH1QVFUN0TStX1JSUvH48eP7BwYG4uDBg1cKCgpeBbBe2u+2Qug2EwD5N5sMPuNtMe8XP4TT6Qxoa2sbIGeXvUKIK7d4IISiKC5d1wPljOfA9bPwzYqiXNV13dd6Uqiq6qdpml2mpe02m63d4/G4vcTF5fF47LJf71nJA6BZVVW3pmntuPHlmAD5wk6Q9NnbHp9vHaqq6tA0zU/64PZhk1FfCZB9G/23ALiqKEqzD39tpvbGUqoFwFUhRLP3yzpCCDtJpxyXDulfG27+pqRR3DXsUWVd4Yq0x/taVQjhIhksC8L+ABpM9ljBf5sKwI8pIBr75L5E4vvu+UNeG/a+hv+AL7yFH8qPtOfHjtOP6V/Bja8D6z/B2Nys/1u9Xv33tLf4GfF/LC4GCJwByWIAAAAASUVORK5CYII=";
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=";
cc.loader.loadBinary = function (url, cb) {
    var self = this;
    var xhr = this.getXMLHttpRequest(),
        errInfo = "load " + url + " failed!";
    xhr.open("GET", url, true);
    if (cc.loader.loadBinary._IEFilter) {
        xhr.setRequestHeader("Accept-Charset", "x-user-defined");
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                var fileContents = cc._convertResponseBodyToText(xhr["responseBody"]);
                cb(null, self._str2Uint8Array(fileContents));
            } else cb(errInfo);
        };
    } else {
        if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=x-user-defined");
        xhr.onload = function () {
            xhr.readyState === 4 && xhr.status === 200 ? cb(null, self._str2Uint8Array(xhr.responseText)) : cb(errInfo);
        };
    }
    xhr.send(null);
};
cc.loader.loadBinary._IEFilter = (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) && window.IEBinaryToArray_ByteStr && window.IEBinaryToArray_ByteStr_Last);
cc.loader._str2Uint8Array = function (strData) {
    if (!strData)
        return null;
    var arrData = new Uint8Array(strData.length);
    for (var i = 0; i < strData.length; i++) {
        arrData[i] = strData.charCodeAt(i) & 0xff;
    }
    return arrData;
};
cc.loader.loadBinarySync = function (url) {
    var self = this;
    var req = this.getXMLHttpRequest();
    var errInfo = "load " + url + " failed!";
    req.open('GET', url, false);
    var arrayInfo = null;
    if (cc.loader.loadBinary._IEFilter) {
        req.setRequestHeader("Accept-Charset", "x-user-defined");
        req.send(null);
        if (req.status !== 200) {
            cc.log(errInfo);
            return null;
        }
        var fileContents = cc._convertResponseBodyToText(req["responseBody"]);
        if (fileContents) {
            arrayInfo = self._str2Uint8Array(fileContents);
        }
    } else {
        if (req.overrideMimeType)
            req.overrideMimeType('text\/plain; charset=x-user-defined');
        req.send(null);
        if (req.status !== 200) {
            cc.log(errInfo);
            return null;
        }
        arrayInfo = this._str2Uint8Array(req.responseText);
    }
    return arrayInfo;
};
window.Uint8Array = window.Uint8Array || window.Array;
if (cc.loader.loadBinary._IEFilter) {
    var IEBinaryToArray_ByteStr_Script =
        "<!-- IEBinaryToArray_ByteStr -->\r\n" +
            "Function IEBinaryToArray_ByteStr(Binary)\r\n" +
            "   IEBinaryToArray_ByteStr = CStr(Binary)\r\n" +
            "End Function\r\n" +
            "Function IEBinaryToArray_ByteStr_Last(Binary)\r\n" +
            "   Dim lastIndex\r\n" +
            "   lastIndex = LenB(Binary)\r\n" +
            "   if lastIndex mod 2 Then\r\n" +
            "       IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )\r\n" +
            "   Else\r\n" +
            "       IEBinaryToArray_ByteStr_Last = " + '""' + "\r\n" +
            "   End If\r\n" +
            "End Function\r\n";// +
    var myVBScript = document.createElement('script');
    myVBScript.type = "text/vbscript";
    myVBScript.textContent = IEBinaryToArray_ByteStr_Script;
    document.body.appendChild(myVBScript);
    cc._convertResponseBodyToText = function (binary) {
        var byteMapping = {};
        for (var i = 0; i < 256; i++) {
            for (var j = 0; j < 256; j++) {
                byteMapping[ String.fromCharCode(i + j * 256) ] =
                    String.fromCharCode(i) + String.fromCharCode(j);
            }
        }
        var rawBytes = IEBinaryToArray_ByteStr(binary);
        var lastChr = IEBinaryToArray_ByteStr_Last(binary);
        return rawBytes.replace(/[\s\S]/g,
            function (match) {
                return byteMapping[match];
            }) + lastChr;
    };
}
var cc = cc || {};
var ClassManager = {
    id : (0|(Math.random()*998)),
    instanceId : (0|(Math.random()*998)),
    getNewID : function(){
        return this.id++;
    },
    getNewInstanceId : function(){
        return this.instanceId++;
    }
};
(function () {
    var fnTest = /\b_super\b/;
    cc.Class = function () {
    };
    cc.Class.extend = function (props) {
        var _super = this.prototype;
        var prototype = Object.create(_super);
        var classId = ClassManager.getNewID();
        ClassManager[classId] = _super;
        var desc = { writable: true, enumerable: false, configurable: true };
        prototype.__instanceId = null;
        function Class() {
            this.__instanceId = ClassManager.getNewInstanceId();
            if (this.ctor)
                this.ctor.apply(this, arguments);
        }
        Class.id = classId;
        desc.value = classId;
        Object.defineProperty(prototype, '__pid', desc);
        Class.prototype = prototype;
        desc.value = Class;
        Object.defineProperty(Class.prototype, 'constructor', desc);
        this.__getters__ && (Class.__getters__ = cc.clone(this.__getters__));
        this.__setters__ && (Class.__setters__ = cc.clone(this.__setters__));
        for(var idx = 0, li = arguments.length; idx < li; ++idx) {
            var prop = arguments[idx];
            for (var name in prop) {
                var isFunc = (typeof prop[name] === "function");
                var override = (typeof _super[name] === "function");
                var hasSuperCall = fnTest.test(prop[name]);
                if (isFunc && override && hasSuperCall) {
                    desc.value = (function (name, fn) {
                        return function () {
                            var tmp = this._super;
                            this._super = _super[name];
                            var ret = fn.apply(this, arguments);
                            this._super = tmp;
                            return ret;
                        };
                    })(name, prop[name]);
                    Object.defineProperty(prototype, name, desc);
                } else if (isFunc) {
                    desc.value = prop[name];
                    Object.defineProperty(prototype, name, desc);
                } else {
                    prototype[name] = prop[name];
                }
                if (isFunc) {
                    var getter, setter, propertyName;
                    if (this.__getters__ && this.__getters__[name]) {
                        propertyName = this.__getters__[name];
                        for (var i in this.__setters__) {
                            if (this.__setters__[i] === propertyName) {
                                setter = i;
                                break;
                            }
                        }
                        cc.defineGetterSetter(prototype, propertyName, prop[name], prop[setter] ? prop[setter] : prototype[setter], name, setter);
                    }
                    if (this.__setters__ && this.__setters__[name]) {
                        propertyName = this.__setters__[name];
                        for (var i in this.__getters__) {
                            if (this.__getters__[i] === propertyName) {
                                getter = i;
                                break;
                            }
                        }
                        cc.defineGetterSetter(prototype, propertyName, prop[getter] ? prop[getter] : prototype[getter], prop[name], getter, name);
                    }
                }
            }
        }
        Class.extend = cc.Class.extend;
        Class.implement = function (prop) {
            for (var name in prop) {
                prototype[name] = prop[name];
            }
        };
        return Class;
    };
})();
cc.defineGetterSetter = function (proto, prop, getter, setter, getterName, setterName){
    if (proto.__defineGetter__) {
        getter && proto.__defineGetter__(prop, getter);
        setter && proto.__defineSetter__(prop, setter);
    } else if (Object.defineProperty) {
        var desc = { enumerable: false, configurable: true };
        getter && (desc.get = getter);
        setter && (desc.set = setter);
        Object.defineProperty(proto, prop, desc);
    } else {
        throw new Error("browser does not support getters");
    }
    if(!getterName && !setterName) {
        var hasGetter = (getter != null), hasSetter = (setter != undefined), props = Object.getOwnPropertyNames(proto);
        for (var i = 0; i < props.length; i++) {
            var name = props[i];
            if( (proto.__lookupGetter__ ? proto.__lookupGetter__(name)
                                        : Object.getOwnPropertyDescriptor(proto, name))
                || typeof proto[name] !== "function" )
                continue;
            var func = proto[name];
            if (hasGetter && func === getter) {
                getterName = name;
                if(!hasSetter || setterName) break;
            }
            if (hasSetter && func === setter) {
                setterName = name;
                if(!hasGetter || getterName) break;
            }
        }
    }
    var ctor = proto.constructor;
    if (getterName) {
        if (!ctor.__getters__) {
            ctor.__getters__ = {};
        }
        ctor.__getters__[getterName] = prop;
    }
    if (setterName) {
        if (!ctor.__setters__) {
            ctor.__setters__ = {};
        }
        ctor.__setters__[setterName] = prop;
    }
};
cc.clone = function (obj) {
    var newObj = (obj.constructor) ? new obj.constructor : {};
    for (var key in obj) {
        var copy = obj[key];
        if (((typeof copy) === "object") && copy &&
            !(copy instanceof cc.Node) && !(copy instanceof HTMLElement)) {
            newObj[key] = cc.clone(copy);
        } else {
            newObj[key] = copy;
        }
    }
    return newObj;
};
cc.inject = function(srcPrototype, destPrototype){
    for(var key in srcPrototype)
        destPrototype[key] = srcPrototype[key];
};
cc.Point = function (x, y) {
    this.x = x || 0;
    this.y = y || 0;
};
cc.p = function (x, y) {
    if (x === undefined)
        return {x: 0, y: 0};
    if (y === undefined)
        return {x: x.x, y: x.y};
    return {x: x, y: y};
};
cc.pointEqualToPoint = function (point1, point2) {
    return point1 && point2 && (point1.x === point2.x) && (point1.y === point2.y);
};
cc.Size = function (width, height) {
    this.width = width || 0;
    this.height = height || 0;
};
cc.size = function (w, h) {
    if (w === undefined)
        return {width: 0, height: 0};
    if (h === undefined)
        return {width: w.width, height: w.height};
    return {width: w, height: h};
};
cc.sizeEqualToSize = function (size1, size2) {
    return (size1 && size2 && (size1.width === size2.width) && (size1.height === size2.height));
};
cc.Rect = function (x, y, width, height) {
    this.x = x||0;
    this.y = y||0;
    this.width = width||0;
    this.height = height||0;
};
cc.rect = function (x, y, w, h) {
    if (x === undefined)
        return {x: 0, y: 0, width: 0, height: 0};
    if (y === undefined)
        return {x: x.x, y: x.y, width: x.width, height: x.height};
    return {x: x, y: y, width: w, height: h };
};
cc.rectEqualToRect = function (rect1, rect2) {
    return rect1 && rect2 && (rect1.x === rect2.x) && (rect1.y === rect2.y) && (rect1.width === rect2.width) && (rect1.height === rect2.height);
};
cc._rectEqualToZero = function(rect){
    return rect && (rect.x === 0) && (rect.y === 0) && (rect.width === 0) && (rect.height === 0);
};
cc.rectContainsRect = function (rect1, rect2) {
    if (!rect1 || !rect2)
        return false;
    return !((rect1.x >= rect2.x) || (rect1.y >= rect2.y) ||
        ( rect1.x + rect1.width <= rect2.x + rect2.width) ||
        ( rect1.y + rect1.height <= rect2.y + rect2.height));
};
cc.rectGetMaxX = function (rect) {
    return (rect.x + rect.width);
};
cc.rectGetMidX = function (rect) {
    return (rect.x + rect.width / 2.0);
};
cc.rectGetMinX = function (rect) {
    return rect.x;
};
cc.rectGetMaxY = function (rect) {
    return(rect.y + rect.height);
};
cc.rectGetMidY = function (rect) {
    return rect.y + rect.height / 2.0;
};
cc.rectGetMinY = function (rect) {
    return rect.y;
};
cc.rectContainsPoint = function (rect, point) {
    return (point.x >= cc.rectGetMinX(rect) && point.x <= cc.rectGetMaxX(rect) &&
        point.y >= cc.rectGetMinY(rect) && point.y <= cc.rectGetMaxY(rect)) ;
};
cc.rectIntersectsRect = function (ra, rb) {
    var maxax = ra.x + ra.width,
        maxay = ra.y + ra.height,
        maxbx = rb.x + rb.width,
        maxby = rb.y + rb.height;
    return !(maxax < rb.x || maxbx < ra.x || maxay < rb.y || maxby < ra.y);
};
cc.rectOverlapsRect = function (rectA, rectB) {
    return !((rectA.x + rectA.width < rectB.x) ||
        (rectB.x + rectB.width < rectA.x) ||
        (rectA.y + rectA.height < rectB.y) ||
        (rectB.y + rectB.height < rectA.y));
};
cc.rectUnion = function (rectA, rectB) {
    var rect = cc.rect(0, 0, 0, 0);
    rect.x = Math.min(rectA.x, rectB.x);
    rect.y = Math.min(rectA.y, rectB.y);
    rect.width = Math.max(rectA.x + rectA.width, rectB.x + rectB.width) - rect.x;
    rect.height = Math.max(rectA.y + rectA.height, rectB.y + rectB.height) - rect.y;
    return rect;
};
cc.rectIntersection = function (rectA, rectB) {
    var intersection = cc.rect(
        Math.max(cc.rectGetMinX(rectA), cc.rectGetMinX(rectB)),
        Math.max(cc.rectGetMinY(rectA), cc.rectGetMinY(rectB)),
        0, 0);
    intersection.width = Math.min(cc.rectGetMaxX(rectA), cc.rectGetMaxX(rectB)) - cc.rectGetMinX(intersection);
    intersection.height = Math.min(cc.rectGetMaxY(rectA), cc.rectGetMaxY(rectB)) - cc.rectGetMinY(intersection);
    return intersection;
};
cc.SAXParser = cc.Class.extend({
    _parser: null,
    _isSupportDOMParser: null,
    ctor: function () {
        if (window.DOMParser) {
            this._isSupportDOMParser = true;
            this._parser = new DOMParser();
        } else {
            this._isSupportDOMParser = false;
        }
    },
    parse : function(xmlTxt){
        return this._parseXML(xmlTxt);
    },
    _parseXML: function (textxml) {
        var xmlDoc;
        if (this._isSupportDOMParser) {
            xmlDoc = this._parser.parseFromString(textxml, "text/xml");
        } else {
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async = "false";
            xmlDoc.loadXML(textxml);
        }
        return xmlDoc;
    }
});
cc.PlistParser = cc.SAXParser.extend({
    parse : function (xmlTxt) {
        var xmlDoc = this._parseXML(xmlTxt);
        var plist = xmlDoc.documentElement;
        if (plist.tagName !== 'plist') {
            cc.warn("Not a plist file!");
            return {};
        }
        var node = null;
        for (var i = 0, len = plist.childNodes.length; i < len; i++) {
            node = plist.childNodes[i];
            if (node.nodeType === 1)
                break;
        }
        xmlDoc = null;
        return this._parseNode(node);
    },
    _parseNode: function (node) {
        var data = null, tagName = node.tagName;
        if(tagName === "dict"){
            data = this._parseDict(node);
        }else if(tagName === "array"){
            data = this._parseArray(node);
        }else if(tagName === "string"){
            if (node.childNodes.length === 1)
                data = node.firstChild.nodeValue;
            else {
                data = "";
                for (var i = 0; i < node.childNodes.length; i++)
                    data += node.childNodes[i].nodeValue;
            }
        }else if(tagName === "false"){
            data = false;
        }else if(tagName === "true"){
            data = true;
        }else if(tagName === "real"){
            data = parseFloat(node.firstChild.nodeValue);
        }else if(tagName === "integer"){
            data = parseInt(node.firstChild.nodeValue, 10);
        }
        return data;
    },
    _parseArray: function (node) {
        var data = [];
        for (var i = 0, len = node.childNodes.length; i < len; i++) {
            var child = node.childNodes[i];
            if (child.nodeType !== 1)
                continue;
            data.push(this._parseNode(child));
        }
        return data;
    },
    _parseDict: function (node) {
        var data = {};
        var key = null;
        for (var i = 0, len = node.childNodes.length; i < len; i++) {
            var child = node.childNodes[i];
            if (child.nodeType !== 1)
                continue;
            if (child.tagName === 'key')
                key = child.firstChild.nodeValue;
            else
                data[key] = this._parseNode(child);
        }
        return data;
    }
});
cc.saxParser = new cc.SAXParser();
cc.plistParser = new cc.PlistParser();
cc._txtLoader = {
    load : function(realUrl, url, res, cb){
        cc.loader.loadTxt(realUrl, cb);
    }
};
cc.loader.register(["txt", "xml", "vsh", "fsh", "atlas"], cc._txtLoader);
cc._jsonLoader = {
    load : function(realUrl, url, res, cb){
        cc.loader.loadJson(realUrl, cb);
    }
};
cc.loader.register(["json", "ExportJson"], cc._jsonLoader);
cc._jsLoader = {
    load : function(realUrl, url, res, cb){
        cc.loader.loadJs(realUrl, cb);
    }
};
cc.loader.register(["js"], cc._jsLoader);
cc._imgLoader = {
    load : function(realUrl, url, res, cb){
        var callback;
        if (cc.loader.isLoading(realUrl)) {
            callback = cb;
        }
        else {
            callback = function(err, img){
                if(err)
                    return cb(err);
                cc.loader.cache[url] = img;
                cc.textureCache.handleLoadedTexture(url);
                cb(null, img);
            };
        }
        cc.loader.loadImg(realUrl, callback);
    }
};
cc.loader.register(["png", "jpg", "bmp","jpeg","gif", "ico", "tiff", "webp"], cc._imgLoader);
cc._serverImgLoader = {
    load : function(realUrl, url, res, cb){
        cc._imgLoader.load(res.src, url, res, cb);
    }
};
cc.loader.register(["serverImg"], cc._serverImgLoader);
cc._plistLoader = {
    load : function(realUrl, url, res, cb){
        cc.loader.loadTxt(realUrl, function(err, txt){
            if(err)
                return cb(err);
            cb(null, cc.plistParser.parse(txt));
        });
    }
};
cc.loader.register(["plist"], cc._plistLoader);
cc._fontLoader = {
    TYPE : {
        ".eot" : "embedded-opentype",
        ".ttf" : "truetype",
        ".ttc" : "truetype",
        ".woff" : "woff",
        ".svg" : "svg"
    },
    _loadFont : function(name, srcs, type){
        var doc = document, path = cc.path, TYPE = this.TYPE, fontStyle = document.createElement("style");
        fontStyle.type = "text/css";
        doc.body.appendChild(fontStyle);
        var fontStr = "";
        if(isNaN(name - 0))
            fontStr += "@font-face { font-family:" + name + "; src:";
        else
            fontStr += "@font-face { font-family:'" + name + "'; src:";
        if(srcs instanceof Array){
            for(var i = 0, li = srcs.length; i < li; i++){
                var src = srcs[i];
                type = path.extname(src).toLowerCase();
                fontStr += "url('" + srcs[i] + "') format('" + TYPE[type] + "')";
                fontStr += (i === li - 1) ? ";" : ",";
            }
        }else{
            type = type.toLowerCase();
            fontStr += "url('" + srcs + "') format('" + TYPE[type] + "');";
        }
        fontStyle.textContent += fontStr + "}";
        var preloadDiv = document.createElement("div");
        var _divStyle =  preloadDiv.style;
        _divStyle.fontFamily = name;
        preloadDiv.innerHTML = ".";
        _divStyle.position = "absolute";
        _divStyle.left = "-100px";
        _divStyle.top = "-100px";
        doc.body.appendChild(preloadDiv);
    },
    load : function(realUrl, url, res, cb){
        var self = this;
        var type = res.type, name = res.name, srcs = res.srcs;
        if(cc.isString(res)){
            type = cc.path.extname(res);
            name = cc.path.basename(res, type);
            self._loadFont(name, res, type);
        }else{
            self._loadFont(name, srcs);
        }
        if(document.fonts){
            document.fonts.load("1em " + name).then(function(){
                cb(null, true);
            }, function(err){
                cb(err);
            });
        }else{
            cb(null, true);
        }
    }
};
cc.loader.register(["font", "eot", "ttf", "woff", "svg", "ttc"], cc._fontLoader);
cc._binaryLoader = {
    load : function(realUrl, url, res, cb){
        cc.loader.loadBinary(realUrl, cb);
    }
};
cc._csbLoader = {
    load: function(realUrl, url, res, cb){
        cc.loader.loadCsb(realUrl, cb);
    }
};
cc.loader.register(["csb"], cc._csbLoader);
window["CocosEngine"] = cc.ENGINE_VERSION = "Cocos2d-JS v3.13";
cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL = 0;
cc.DIRECTOR_STATS_POSITION = cc.p(0, 0);
cc.DIRECTOR_FPS_INTERVAL = 0.5;
cc.COCOSNODE_RENDER_SUBPIXEL = 1;
cc.SPRITEBATCHNODE_RENDER_SUBPIXEL = 1;
cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA = 1;
cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP = 0;
cc.TEXTURE_ATLAS_USE_VAO = 0;
cc.TEXTURE_NPOT_SUPPORT = 0;
cc.RETINA_DISPLAY_SUPPORT = 1;
cc.RETINA_DISPLAY_FILENAME_SUFFIX = "-hd";
cc.USE_LA88_LABELS = 1;
cc.SPRITE_DEBUG_DRAW = 0;
cc.SPRITEBATCHNODE_DEBUG_DRAW = 0;
cc.LABELBMFONT_DEBUG_DRAW = 0;
cc.LABELATLAS_DEBUG_DRAW = 0;
cc.IS_RETINA_DISPLAY_SUPPORTED = 1;
cc.DEFAULT_ENGINE = cc.ENGINE_VERSION + "-canvas";
cc.ENABLE_STACKABLE_ACTIONS = 1;
cc.ENABLE_GL_STATE_CACHE = 1;
cc.$ = function (x) {
    var parent = (this === cc) ? document : this;
    var el = (x instanceof HTMLElement) ? x : parent.querySelector(x);
    if (el) {
        el.find = el.find || cc.$;
        el.hasClass = el.hasClass || function (cls) {
            return this.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
        };
        el.addClass = el.addClass || function (cls) {
            if (!this.hasClass(cls)) {
                if (this.className) {
                    this.className += " ";
                }
                this.className += cls;
            }
            return this;
        };
        el.removeClass = el.removeClass || function (cls) {
            if (this.hasClass(cls)) {
                this.className = this.className.replace(cls, '');
            }
            return this;
        };
        el.remove = el.remove || function () {
            if (this.parentNode)
                this.parentNode.removeChild(this);
            return this;
        };
        el.appendTo = el.appendTo || function (x) {
            x.appendChild(this);
            return this;
        };
        el.prependTo = el.prependTo || function (x) {
            ( x.childNodes[0]) ? x.insertBefore(this, x.childNodes[0]) : x.appendChild(this);
            return this;
        };
        el.transforms = el.transforms || function () {
            this.style[cc.$.trans] = cc.$.translate(this.position) + cc.$.rotate(this.rotation) + cc.$.scale(this.scale) + cc.$.skew(this.skew);
            return this;
        };
        el.position = el.position || {x: 0, y: 0};
        el.rotation = el.rotation || 0;
        el.scale = el.scale || {x: 1, y: 1};
        el.skew = el.skew || {x: 0, y: 0};
        el.translates = function (x, y) {
            this.position.x = x;
            this.position.y = y;
            this.transforms();
            return this
        };
        el.rotate = function (x) {
            this.rotation = x;
            this.transforms();
            return this
        };
        el.resize = function (x, y) {
            this.scale.x = x;
            this.scale.y = y;
            this.transforms();
            return this
        };
        el.setSkew = function (x, y) {
            this.skew.x = x;
            this.skew.y = y;
            this.transforms();
            return this
        };
    }
    return el;
};
switch (cc.sys.browserType) {
    case cc.sys.BROWSER_TYPE_FIREFOX:
        cc.$.pfx = "Moz";
        cc.$.hd = true;
        break;
    case cc.sys.BROWSER_TYPE_CHROME:
    case cc.sys.BROWSER_TYPE_SAFARI:
        cc.$.pfx = "webkit";
        cc.$.hd = true;
        break;
    case cc.sys.BROWSER_TYPE_OPERA:
        cc.$.pfx = "O";
        cc.$.hd = false;
        break;
    case cc.sys.BROWSER_TYPE_IE:
        cc.$.pfx = "ms";
        cc.$.hd = false;
        break;
    default:
        cc.$.pfx = "webkit";
        cc.$.hd = true;
}
cc.$.trans = cc.$.pfx + "Transform";
cc.$.translate = (cc.$.hd) ? function (a) {
    return "translate3d(" + a.x + "px, " + a.y + "px, 0) "
} : function (a) {
    return "translate(" + a.x + "px, " + a.y + "px) "
};
cc.$.rotate = (cc.$.hd) ? function (a) {
    return "rotateZ(" + a + "deg) ";
} : function (a) {
    return "rotate(" + a + "deg) ";
};
cc.$.scale = function (a) {
    return "scale(" + a.x + ", " + a.y + ") "
};
cc.$.skew = function (a) {
    return "skewX(" + -a.x + "deg) skewY(" + a.y + "deg)";
};
cc.$new = function (x) {
    return cc.$(document.createElement(x))
};
cc.$.findpos = function (obj) {
    var curleft = 0;
    var curtop = 0;
    do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
    } while (obj = obj.offsetParent);
    return {x: curleft, y: curtop};
};
cc.INVALID_INDEX = -1;
cc.PI = Math.PI;
cc.FLT_MAX = parseFloat('3.402823466e+38F');
cc.FLT_MIN = parseFloat("1.175494351e-38F");
cc.RAD = cc.PI / 180;
cc.DEG = 180 / cc.PI;
cc.UINT_MAX = 0xffffffff;
cc.swap = function (x, y, ref) {
    if (cc.isObject(ref) && !cc.isUndefined(ref.x) && !cc.isUndefined(ref.y)) {
        var tmp = ref[x];
        ref[x] = ref[y];
        ref[y] = tmp;
    } else
        cc.log(cc._LogInfos.swap);
};
cc.lerp = function (a, b, r) {
    return a + (b - a) * r;
};
cc.rand = function () {
    return Math.random() * 0xffffff;
};
cc.randomMinus1To1 = function () {
    return (Math.random() - 0.5) * 2;
};
cc.random0To1 = Math.random;
cc.degreesToRadians = function (angle) {
    return angle * cc.RAD;
};
cc.radiansToDegrees = function (angle) {
    return angle * cc.DEG;
};
cc.radiansToDegress = function (angle) {
    cc.log(cc._LogInfos.radiansToDegress);
    return angle * cc.DEG;
};
cc.REPEAT_FOREVER = Number.MAX_VALUE - 1;
cc.nodeDrawSetup = function (node) {
    if (node._shaderProgram) {
        node._shaderProgram.use();
        node._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
    }
};
cc.enableDefaultGLStates = function () {
};
cc.disableDefaultGLStates = function () {
};
cc.incrementGLDraws = function (addNumber) {
    cc.g_NumberOfDraws += addNumber;
};
cc.FLT_EPSILON = 0.0000001192092896;
cc.contentScaleFactor = cc.IS_RETINA_DISPLAY_SUPPORTED ? function () {
    return cc.director.getContentScaleFactor();
} : function () {
    return 1;
};
cc.pointPointsToPixels = function (points) {
    var scale = cc.contentScaleFactor();
    return cc.p(points.x * scale, points.y * scale);
};
cc.pointPixelsToPoints = function (pixels) {
    var scale = cc.contentScaleFactor();
    return cc.p(pixels.x / scale, pixels.y / scale);
};
cc._pointPixelsToPointsOut = function(pixels, outPoint){
    var scale = cc.contentScaleFactor();
    outPoint.x = pixels.x / scale;
    outPoint.y = pixels.y / scale;
};
cc.sizePointsToPixels = function (sizeInPoints) {
    var scale = cc.contentScaleFactor();
    return cc.size(sizeInPoints.width * scale, sizeInPoints.height * scale);
};
cc.sizePixelsToPoints = function (sizeInPixels) {
    var scale = cc.contentScaleFactor();
    return cc.size(sizeInPixels.width / scale, sizeInPixels.height / scale);
};
cc._sizePixelsToPointsOut = function (sizeInPixels, outSize) {
    var scale = cc.contentScaleFactor();
    outSize.width = sizeInPixels.width / scale;
    outSize.height = sizeInPixels.height / scale;
};
cc.rectPixelsToPoints = cc.IS_RETINA_DISPLAY_SUPPORTED ? function (pixel) {
    var scale = cc.contentScaleFactor();
    return cc.rect(pixel.x / scale, pixel.y / scale,
        pixel.width / scale, pixel.height / scale);
} : function (p) {
    return p;
};
cc.rectPointsToPixels = cc.IS_RETINA_DISPLAY_SUPPORTED ? function (point) {
   var scale = cc.contentScaleFactor();
    return cc.rect(point.x * scale, point.y * scale,
        point.width * scale, point.height * scale);
} : function (p) {
    return p;
};
cc.ONE = 1;
cc.ZERO = 0;
cc.SRC_ALPHA = 0x0302;
cc.SRC_ALPHA_SATURATE = 0x308;
cc.SRC_COLOR = 0x300;
cc.DST_ALPHA = 0x304;
cc.DST_COLOR = 0x306;
cc.ONE_MINUS_SRC_ALPHA = 0x0303;
cc.ONE_MINUS_SRC_COLOR = 0x301;
cc.ONE_MINUS_DST_ALPHA = 0x305;
cc.ONE_MINUS_DST_COLOR = 0x0307;
cc.ONE_MINUS_CONSTANT_ALPHA    = 0x8004;
cc.ONE_MINUS_CONSTANT_COLOR    = 0x8002;
cc.LINEAR    = 0x2601;
cc.REPEAT    = 0x2901;
cc.CLAMP_TO_EDGE    = 0x812f;
cc.MIRRORED_REPEAT   = 0x8370;
cc.BLEND_SRC = cc.SRC_ALPHA;
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_WEBGL
         && cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA) {
        cc.BLEND_SRC = cc.ONE;
    }
});
cc.BLEND_DST = cc.ONE_MINUS_SRC_ALPHA;
cc.checkGLErrorDebug = function () {
    if (cc.renderMode === cc.game.RENDER_TYPE_WEBGL) {
        var _error = cc._renderContext.getError();
        if (_error) {
            cc.log(cc._LogInfos.checkGLErrorDebug, _error);
        }
    }
};
cc.ORIENTATION_PORTRAIT = 1;
cc.ORIENTATION_LANDSCAPE = 2;
cc.ORIENTATION_AUTO = 3;
cc.VERTEX_ATTRIB_FLAG_NONE = 0;
cc.VERTEX_ATTRIB_FLAG_POSITION = 1 << 0;
cc.VERTEX_ATTRIB_FLAG_COLOR = 1 << 1;
cc.VERTEX_ATTRIB_FLAG_TEX_COORDS = 1 << 2;
cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX = ( cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS );
cc.GL_ALL = 0;
cc.VERTEX_ATTRIB_POSITION = 0;
cc.VERTEX_ATTRIB_COLOR = 1;
cc.VERTEX_ATTRIB_TEX_COORDS = 2;
cc.VERTEX_ATTRIB_MAX = 7;
cc.UNIFORM_PMATRIX = 0;
cc.UNIFORM_MVMATRIX = 1;
cc.UNIFORM_MVPMATRIX = 2;
cc.UNIFORM_TIME = 3;
cc.UNIFORM_SINTIME = 4;
cc.UNIFORM_COSTIME = 5;
cc.UNIFORM_RANDOM01 = 6;
cc.UNIFORM_SAMPLER = 7;
cc.UNIFORM_MAX = 8;
cc.SHADER_POSITION_TEXTURECOLOR = "ShaderPositionTextureColor";
cc.SHADER_SPRITE_POSITION_TEXTURECOLOR = "ShaderSpritePositionTextureColor";
cc.SHADER_POSITION_TEXTURECOLORALPHATEST = "ShaderPositionTextureColorAlphaTest";
cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST = "ShaderSpritePositionTextureColorAlphaTest";
cc.SHADER_POSITION_COLOR = "ShaderPositionColor";
cc.SHADER_SPRITE_POSITION_COLOR = "ShaderSpritePositionColor";
cc.SHADER_POSITION_TEXTURE = "ShaderPositionTexture";
cc.SHADER_POSITION_TEXTURE_UCOLOR = "ShaderPositionTexture_uColor";
cc.SHADER_POSITION_TEXTUREA8COLOR = "ShaderPositionTextureA8Color";
cc.SHADER_POSITION_UCOLOR = "ShaderPosition_uColor";
cc.SHADER_POSITION_LENGTHTEXTURECOLOR = "ShaderPositionLengthTextureColor";
cc.UNIFORM_PMATRIX_S = "CC_PMatrix";
cc.UNIFORM_MVMATRIX_S = "CC_MVMatrix";
cc.UNIFORM_MVPMATRIX_S = "CC_MVPMatrix";
cc.UNIFORM_TIME_S = "CC_Time";
cc.UNIFORM_SINTIME_S = "CC_SinTime";
cc.UNIFORM_COSTIME_S = "CC_CosTime";
cc.UNIFORM_RANDOM01_S = "CC_Random01";
cc.UNIFORM_SAMPLER_S = "CC_Texture0";
cc.UNIFORM_ALPHA_TEST_VALUE_S = "CC_alpha_value";
cc.ATTRIBUTE_NAME_COLOR = "a_color";
cc.ATTRIBUTE_NAME_POSITION = "a_position";
cc.ATTRIBUTE_NAME_TEX_COORD = "a_texCoord";
cc.ATTRIBUTE_NAME_MVMAT = "a_mvMatrix";
cc.ITEM_SIZE = 32;
cc.CURRENT_ITEM = 0xc0c05001;
cc.ZOOM_ACTION_TAG = 0xc0c05002;
cc.NORMAL_TAG = 8801;
cc.SELECTED_TAG = 8802;
cc.DISABLE_TAG = 8803;
cc.arrayVerifyType = function (arr, type) {
    if (arr && arr.length > 0) {
        for (var i = 0; i < arr.length; i++) {
            if (!(arr[i] instanceof  type)) {
                cc.log("element type is wrong!");
                return false;
            }
        }
    }
    return true;
};
cc.arrayRemoveObject = function (arr, delObj) {
    for (var i = 0, l = arr.length; i < l; i++) {
        if (arr[i] === delObj) {
            arr.splice(i, 1);
            break;
        }
    }
};
cc.arrayRemoveArray = function (arr, minusArr) {
    for (var i = 0, l = minusArr.length; i < l; i++) {
        cc.arrayRemoveObject(arr, minusArr[i]);
    }
};
cc.arrayAppendObjectsToIndex = function(arr, addObjs,index){
    arr.splice.apply(arr, [index, 0].concat(addObjs));
    return arr;
};
cc.copyArray = function(arr){
    var i, len = arr.length, arr_clone = new Array(len);
    for (i = 0; i < len; i += 1)
        arr_clone[i] = arr[i];
    return arr_clone;
};
cc._tmp.PrototypeColor = function () {
    var _p = cc.color;
    _p._getWhite = function () {
        return _p(255, 255, 255);
    };
    _p._getYellow = function () {
        return _p(255, 255, 0);
    };
    _p._getBlue = function () {
        return  _p(0, 0, 255);
    };
    _p._getGreen = function () {
        return _p(0, 255, 0);
    };
    _p._getRed = function () {
        return _p(255, 0, 0);
    };
    _p._getMagenta = function () {
        return _p(255, 0, 255);
    };
    _p._getBlack = function () {
        return _p(0, 0, 0);
    };
    _p._getOrange = function () {
        return _p(255, 127, 0);
    };
    _p._getGray = function () {
        return _p(166, 166, 166);
    };
    _p.WHITE;
    cc.defineGetterSetter(_p, "WHITE", _p._getWhite);
    _p.YELLOW;
    cc.defineGetterSetter(_p, "YELLOW", _p._getYellow);
    _p.BLUE;
    cc.defineGetterSetter(_p, "BLUE", _p._getBlue);
    _p.GREEN;
    cc.defineGetterSetter(_p, "GREEN", _p._getGreen);
    _p.RED;
    cc.defineGetterSetter(_p, "RED", _p._getRed);
    _p.MAGENTA;
    cc.defineGetterSetter(_p, "MAGENTA", _p._getMagenta);
    _p.BLACK;
    cc.defineGetterSetter(_p, "BLACK", _p._getBlack);
    _p.ORANGE;
    cc.defineGetterSetter(_p, "ORANGE", _p._getOrange);
    _p.GRAY;
    cc.defineGetterSetter(_p, "GRAY", _p._getGray);
    cc.BlendFunc._disable = function(){
        return new cc.BlendFunc(cc.ONE, cc.ZERO);
    };
    cc.BlendFunc._alphaPremultiplied = function(){
        return new cc.BlendFunc(cc.ONE, cc.ONE_MINUS_SRC_ALPHA);
    };
    cc.BlendFunc._alphaNonPremultiplied = function(){
        return new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
    };
    cc.BlendFunc._additive = function(){
        return new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE);
    };
    cc.BlendFunc.DISABLE;
    cc.defineGetterSetter(cc.BlendFunc, "DISABLE", cc.BlendFunc._disable);
    cc.BlendFunc.ALPHA_PREMULTIPLIED;
    cc.defineGetterSetter(cc.BlendFunc, "ALPHA_PREMULTIPLIED", cc.BlendFunc._alphaPremultiplied);
    cc.BlendFunc.ALPHA_NON_PREMULTIPLIED;
    cc.defineGetterSetter(cc.BlendFunc, "ALPHA_NON_PREMULTIPLIED", cc.BlendFunc._alphaNonPremultiplied);
    cc.BlendFunc.ADDITIVE;
    cc.defineGetterSetter(cc.BlendFunc, "ADDITIVE", cc.BlendFunc._additive);
};
var cc = cc || {};
cc._tmp = cc._tmp || {};
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType !== cc.game.RENDER_TYPE_WEBGL) {
        return;
    }
    cc.color = function (r, g, b, a, arrayBuffer, offset) {
        if (r === undefined)
            return new cc.Color(0, 0, 0, 255, arrayBuffer, offset);
        if (cc.isString(r)) {
            var color = cc.hexToColor(r);
            return new cc.Color(color.r, color.g, color.b, color.a);
        }
        if (cc.isObject(r))
            return new cc.Color(r.r, r.g, r.b, r.a, r.arrayBuffer, r.offset);
        return new cc.Color(r, g, b, a, arrayBuffer, offset);
    };
    cc.Color = function (r, g, b, a, arrayBuffer, offset) {
        this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Color.BYTES_PER_ELEMENT);
        this._offset = offset || 0;
        var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
        this._view = new Uint8Array(locArrayBuffer, locOffset, 4);
        this._view[0] = r || 0;
        this._view[1] = g || 0;
        this._view[2] = b || 0;
        this._view[3] = (a == null) ? 255 : a;
        if (a === undefined)
            this.a_undefined = true;
    };
    cc.Color.BYTES_PER_ELEMENT = 4;
    var _p = cc.Color.prototype;
    _p._getR = function () {
        return this._view[0];
    };
    _p._setR = function (value) {
        this._view[0] = value < 0 ? 0 : value;
    };
    _p._getG = function () {
        return this._view[1];
    };
    _p._setG = function (value) {
        this._view[1] = value < 0 ? 0 : value;
    };
    _p._getB = function () {
        return this._view[2];
    };
    _p._setB = function (value) {
        this._view[2] = value < 0 ? 0 : value;
    };
    _p._getA = function () {
        return this._view[3];
    };
    _p._setA = function (value) {
        this._view[3] = value < 0 ? 0 : value;
    };
    _p.r;
    cc.defineGetterSetter(_p, "r", _p._getR, _p._setR);
    _p.g;
    cc.defineGetterSetter(_p, "g", _p._getG, _p._setG);
    _p.b;
    cc.defineGetterSetter(_p, "b", _p._getB, _p._setB);
    _p.a;
    cc.defineGetterSetter(_p, "a", _p._getA, _p._setA);
    cc.assert(cc.isFunction(cc._tmp.PrototypeColor), cc._LogInfos.MissingFile, "CCTypesPropertyDefine.js");
    cc._tmp.PrototypeColor();
    delete cc._tmp.PrototypeColor;
});
cc.Color = function (r, g, b, a) {
    this.r = r || 0;
    this.g = g || 0;
    this.b = b || 0;
    this.a = (a == null) ? 255 : a;
};
cc.color = function (r, g, b, a) {
    if (r === undefined)
        return {r: 0, g: 0, b: 0, a: 255};
    if (cc.isString(r))
        return cc.hexToColor(r);
    if (cc.isObject(r))
        return {r: r.r, g: r.g, b: r.b, a: (r.a == null) ? 255 : r.a};
    return  {r: r, g: g, b: b, a: (a == null ? 255 : a)};
};
cc.colorEqual = function (color1, color2) {
    return color1.r === color2.r && color1.g === color2.g && color1.b === color2.b;
};
cc.Acceleration = function (x, y, z, timestamp) {
    this.x = x || 0;
    this.y = y || 0;
    this.z = z || 0;
    this.timestamp = timestamp || 0;
};
cc.Vertex2F = function (x, y, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex2F.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    this._view = new Float32Array(this._arrayBuffer, this._offset, 2);
    this._view[0] = x || 0;
    this._view[1] = y || 0;
};
cc.Vertex2F.BYTES_PER_ELEMENT = 8;
_p = cc.Vertex2F.prototype;
_p._getX = function () {
    return this._view[0];
};
_p._setX = function (xValue) {
    this._view[0] = xValue;
};
_p._getY = function () {
    return this._view[1];
};
_p._setY = function (yValue) {
    this._view[1] = yValue;
};
_p.x;
cc.defineGetterSetter(_p, "x", _p._getX, _p._setX);
_p.y;
cc.defineGetterSetter(_p, "y", _p._getY, _p._setY);
cc.Vertex3F = function (x, y, z, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex3F.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
    this._view = new Float32Array(locArrayBuffer, locOffset, 3);
    this._view[0] = x || 0;
    this._view[1] = y || 0;
    this._view[2] = z || 0;
};
cc.Vertex3F.BYTES_PER_ELEMENT = 12;
_p = cc.Vertex3F.prototype;
_p._getX = function () {
    return this._view[0];
};
_p._setX = function (xValue) {
    this._view[0] = xValue;
};
_p._getY = function () {
    return this._view[1];
};
_p._setY = function (yValue) {
    this._view[1] = yValue;
};
_p._getZ = function () {
    return this._view[2];
};
_p._setZ = function (zValue) {
    this._view[2] = zValue;
};
_p.x;
cc.defineGetterSetter(_p, "x", _p._getX, _p._setX);
_p.y;
cc.defineGetterSetter(_p, "y", _p._getY, _p._setY);
_p.z;
cc.defineGetterSetter(_p, "z", _p._getZ, _p._setZ);
cc.Tex2F = function (u, v, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Tex2F.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    this._view = new Float32Array(this._arrayBuffer, this._offset, 2);
    this._view[0] = u || 0;
    this._view[1] = v || 0;
};
cc.Tex2F.BYTES_PER_ELEMENT = 8;
_p = cc.Tex2F.prototype;
_p._getU = function () {
    return this._view[0];
};
_p._setU = function (xValue) {
    this._view[0] = xValue;
};
_p._getV = function () {
    return this._view[1];
};
_p._setV = function (yValue) {
    this._view[1] = yValue;
};
_p.u;
cc.defineGetterSetter(_p, "u", _p._getU, _p._setU);
_p.v;
cc.defineGetterSetter(_p, "v", _p._getV, _p._setV);
cc.Quad2 = function (tl, tr, bl, br, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Quad2.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex2F.BYTES_PER_ELEMENT;
    this._tl = tl ? new cc.Vertex2F(tl.x, tl.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._tr = tr ? new cc.Vertex2F(tr.x, tr.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._bl = bl ? new cc.Vertex2F(bl.x, bl.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._br = br ? new cc.Vertex2F(br.x, br.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
};
cc.Quad2.BYTES_PER_ELEMENT = 32;
_p = cc.Quad2.prototype;
_p._getTL = function () {
    return this._tl;
};
_p._setTL = function (tlValue) {
    this._tl._view[0] = tlValue.x;
    this._tl._view[1] = tlValue.y;
};
_p._getTR = function () {
    return this._tr;
};
_p._setTR = function (trValue) {
    this._tr._view[0] = trValue.x;
    this._tr._view[1] = trValue.y;
};
_p._getBL = function() {
    return this._bl;
};
_p._setBL = function (blValue) {
    this._bl._view[0] = blValue.x;
    this._bl._view[1] = blValue.y;
};
_p._getBR = function () {
    return this._br;
};
_p._setBR = function (brValue) {
    this._br._view[0] = brValue.x;
    this._br._view[1] = brValue.y;
};
_p.tl;
cc.defineGetterSetter(_p, "tl", _p._getTL, _p._setTL);
_p.tr;
cc.defineGetterSetter(_p, "tr", _p._getTR, _p._setTR);
_p.bl;
cc.defineGetterSetter(_p, "bl", _p._getBL, _p._setBL);
_p.br;
cc.defineGetterSetter(_p, "br", _p._getBR, _p._setBR);
cc.Quad3 = function (bl, br, tl, tr, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Quad3.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex3F.BYTES_PER_ELEMENT;
    this.bl = bl ? new cc.Vertex3F(bl.x, bl.y, bl.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this.br = br ? new cc.Vertex3F(br.x, br.y, br.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this.tl = tl ? new cc.Vertex3F(tl.x, tl.y, tl.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this.tr = tr ? new cc.Vertex3F(tr.x, tr.y, tr.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
};
cc.Quad3.BYTES_PER_ELEMENT = 48;
cc.V3F_C4B_T2F = function (vertices, colors, texCoords, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
    this._vertices = vertices ? new cc.Vertex3F(vertices.x, vertices.y, vertices.z, locArrayBuffer, locOffset) :
        new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
    locOffset += cc.Vertex3F.BYTES_PER_ELEMENT;
    this._colors = colors ? new cc.Color(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset) :
        new cc.Color(0, 0, 0, 0, locArrayBuffer, locOffset);
    locOffset += cc.Color.BYTES_PER_ELEMENT;
    this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset) :
        new cc.Tex2F(0, 0, locArrayBuffer, locOffset);
};
cc.V3F_C4B_T2F.BYTES_PER_ELEMENT = 24;
_p = cc.V3F_C4B_T2F.prototype;
_p._getVertices = function () {
    return this._vertices;
};
_p._setVertices = function (verticesValue) {
    var locVertices = this._vertices;
    locVertices._view[0] = verticesValue.x;
    locVertices._view[1] = verticesValue.y;
    locVertices._view[2] = verticesValue.z;
};
_p._getColor = function () {
    return this._colors;
};
_p._setColor = function (colorValue) {
    var locColors = this._colors;
    locColors._view[0] = colorValue.r;
    locColors._view[1] = colorValue.g;
    locColors._view[2] = colorValue.b;
    locColors._view[3] = colorValue.a;
};
_p._getTexCoords = function () {
    return this._texCoords;
};
_p._setTexCoords = function (texValue) {
    this._texCoords._view[0] = texValue.u;
    this._texCoords._view[1] = texValue.v;
};
_p.vertices;
cc.defineGetterSetter(_p, "vertices", _p._getVertices, _p._setVertices);
_p.colors;
cc.defineGetterSetter(_p, "colors", _p._getColor, _p._setColor);
_p.texCoords;
cc.defineGetterSetter(_p, "texCoords", _p._getTexCoords, _p._setTexCoords);
cc.V3F_C4B_T2F_Quad = function (tl, bl, tr, br, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
    this._tl = tl ? new cc.V3F_C4B_T2F(tl.vertices, tl.colors, tl.texCoords, locArrayBuffer, locOffset) :
        new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._bl = bl ? new cc.V3F_C4B_T2F(bl.vertices, bl.colors, bl.texCoords, locArrayBuffer, locOffset) :
        new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._tr = tr ? new cc.V3F_C4B_T2F(tr.vertices, tr.colors, tr.texCoords, locArrayBuffer, locOffset) :
        new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._br = br ? new cc.V3F_C4B_T2F(br.vertices, br.colors, br.texCoords, locArrayBuffer, locOffset) :
        new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
};
cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT = 96;
_p = cc.V3F_C4B_T2F_Quad.prototype;
_p._getTL = function () {
    return this._tl;
};
_p._setTL = function (tlValue) {
    var locTl = this._tl;
    locTl.vertices = tlValue.vertices;
    locTl.colors = tlValue.colors;
    locTl.texCoords = tlValue.texCoords;
};
_p._getBL = function () {
    return this._bl;
};
_p._setBL = function (blValue) {
    var locBl = this._bl;
    locBl.vertices = blValue.vertices;
    locBl.colors = blValue.colors;
    locBl.texCoords = blValue.texCoords;
};
_p._getTR = function () {
    return this._tr;
};
_p._setTR = function (trValue) {
    var locTr = this._tr;
    locTr.vertices = trValue.vertices;
    locTr.colors = trValue.colors;
    locTr.texCoords = trValue.texCoords;
};
_p._getBR = function () {
    return this._br;
};
_p._setBR = function (brValue) {
    var locBr = this._br;
    locBr.vertices = brValue.vertices;
    locBr.colors = brValue.colors;
    locBr.texCoords = brValue.texCoords;
};
_p._getArrayBuffer = function () {
    return this._arrayBuffer;
};
_p.tl;
cc.defineGetterSetter(_p, "tl", _p._getTL, _p._setTL);
_p.tr;
cc.defineGetterSetter(_p, "tr", _p._getTR, _p._setTR);
_p.bl;
cc.defineGetterSetter(_p, "bl", _p._getBL, _p._setBL);
_p.br;
cc.defineGetterSetter(_p, "br", _p._getBR, _p._setBR);
_p.arrayBuffer;
cc.defineGetterSetter(_p, "arrayBuffer", _p._getArrayBuffer, null);
cc.V3F_C4B_T2F_QuadZero = function () {
    return new cc.V3F_C4B_T2F_Quad();
};
cc.V3F_C4B_T2F_QuadCopy = function (sourceQuad) {
    if (!sourceQuad)
        return  cc.V3F_C4B_T2F_QuadZero();
    var srcTL = sourceQuad.tl, srcBL = sourceQuad.bl, srcTR = sourceQuad.tr, srcBR = sourceQuad.br;
    return {
        tl: {vertices: {x: srcTL.vertices.x, y: srcTL.vertices.y, z: srcTL.vertices.z},
            colors: {r: srcTL.colors.r, g: srcTL.colors.g, b: srcTL.colors.b, a: srcTL.colors.a},
            texCoords: {u: srcTL.texCoords.u, v: srcTL.texCoords.v}},
        bl: {vertices: {x: srcBL.vertices.x, y: srcBL.vertices.y, z: srcBL.vertices.z},
            colors: {r: srcBL.colors.r, g: srcBL.colors.g, b: srcBL.colors.b, a: srcBL.colors.a},
            texCoords: {u: srcBL.texCoords.u, v: srcBL.texCoords.v}},
        tr: {vertices: {x: srcTR.vertices.x, y: srcTR.vertices.y, z: srcTR.vertices.z},
            colors: {r: srcTR.colors.r, g: srcTR.colors.g, b: srcTR.colors.b, a: srcTR.colors.a},
            texCoords: {u: srcTR.texCoords.u, v: srcTR.texCoords.v}},
        br: {vertices: {x: srcBR.vertices.x, y: srcBR.vertices.y, z: srcBR.vertices.z},
            colors: {r: srcBR.colors.r, g: srcBR.colors.g, b: srcBR.colors.b, a: srcBR.colors.a},
            texCoords: {u: srcBR.texCoords.u, v: srcBR.texCoords.v}}
    };
};
cc.V3F_C4B_T2F_QuadsCopy = function (sourceQuads) {
    if (!sourceQuads)
        return [];
    var retArr = [];
    for (var i = 0; i < sourceQuads.length; i++) {
        retArr.push(cc.V3F_C4B_T2F_QuadCopy(sourceQuads[i]));
    }
    return retArr;
};
cc.V2F_C4B_T2F = function (vertices, colors, texCoords, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
    this._vertices = vertices ? new cc.Vertex2F(vertices.x, vertices.y, locArrayBuffer, locOffset) :
        new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
    locOffset += cc.Vertex2F.BYTES_PER_ELEMENT;
    this._colors = colors ? cc.color(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset) :
        cc.color(0, 0, 0, 0, locArrayBuffer, locOffset);
    locOffset += cc.Color.BYTES_PER_ELEMENT;
    this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset) :
        new cc.Tex2F(0, 0, locArrayBuffer, locOffset);
};
cc.V2F_C4B_T2F.BYTES_PER_ELEMENT = 20;
_p = cc.V2F_C4B_T2F.prototype;
_p._getVertices = function () {
    return this._vertices;
};
_p._setVertices = function (verticesValue) {
    this._vertices._view[0] = verticesValue.x;
    this._vertices._view[1] = verticesValue.y;
};
_p._getColor = function () {
    return this._colors;
};
_p._setColor = function (colorValue) {
    var locColors = this._colors;
    locColors._view[0] = colorValue.r;
    locColors._view[1] = colorValue.g;
    locColors._view[2] = colorValue.b;
    locColors._view[3] = colorValue.a;
};
_p._getTexCoords = function () {
    return this._texCoords;
};
_p._setTexCoords = function (texValue) {
    this._texCoords._view[0] = texValue.u;
    this._texCoords._view[1] = texValue.v;
};
_p.vertices;
cc.defineGetterSetter(_p, "vertices", _p._getVertices, _p._setVertices);
_p.colors;
cc.defineGetterSetter(_p, "colors", _p._getColor, _p._setColor);
_p.texCoords;
cc.defineGetterSetter(_p, "texCoords", _p._getTexCoords, _p._setTexCoords);
cc.V2F_C4B_T2F_Triangle = function (a, b, c, arrayBuffer, offset) {
    this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT);
    this._offset = offset || 0;
    var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
    this._a = a ? new cc.V2F_C4B_T2F(a.vertices, a.colors, a.texCoords, locArrayBuffer, locOffset) :
        new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._b = b ? new cc.V2F_C4B_T2F(b.vertices, b.colors, b.texCoords, locArrayBuffer, locOffset) :
        new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
    locOffset += locElementLen;
    this._c = c ? new cc.V2F_C4B_T2F(c.vertices, c.colors, c.texCoords, locArrayBuffer, locOffset) :
        new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
};
cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT = 60;
_p = cc.V2F_C4B_T2F_Triangle.prototype;
_p._getA = function () {
    return this._a;
};
_p._setA = function (aValue) {
    var locA = this._a;
    locA.vertices = aValue.vertices;
    locA.colors = aValue.colors;
    locA.texCoords = aValue.texCoords;
};
_p._getB = function () {
    return this._b;
};
_p._setB = function (bValue) {
    var locB = this._b;
    locB.vertices = bValue.vertices;
    locB.colors = bValue.colors;
    locB.texCoords = bValue.texCoords;
};
_p._getC = function () {
    return this._c;
};
_p._setC = function (cValue) {
    var locC = this._c;
    locC.vertices = cValue.vertices;
    locC.colors = cValue.colors;
    locC.texCoords = cValue.texCoords;
};
_p.a;
cc.defineGetterSetter(_p, "a", _p._getA, _p._setA);
_p.b;
cc.defineGetterSetter(_p, "b", _p._getB, _p._setB);
_p.c;
cc.defineGetterSetter(_p, "c", _p._getC, _p._setC);
cc.vertex2 = function (x, y) {
    return new cc.Vertex2F(x, y);
};
cc.vertex3 = function (x, y, z) {
    return new cc.Vertex3F(x, y, z);
};
cc.tex2 = function (u, v) {
    return new cc.Tex2F(u, v);
};
cc.BlendFunc = function (src1, dst1) {
    this.src = src1;
    this.dst = dst1;
};
cc.blendFuncDisable = function () {
    return new cc.BlendFunc(cc.ONE, cc.ZERO);
};
cc.hexToColor = function (hex) {
    hex = hex.replace(/^#?/, "0x");
    var c = parseInt(hex);
    var r = c >> 16;
    var g = (c >> 8) % 256;
    var b = c % 256;
    return cc.color(r, g, b);
};
cc.colorToHex = function (color) {
    var hR = color.r.toString(16), hG = color.g.toString(16), hB = color.b.toString(16);
    return "#" + (color.r < 16 ? ("0" + hR) : hR) + (color.g < 16 ? ("0" + hG) : hG) + (color.b < 16 ? ("0" + hB) : hB);
};
cc.TEXT_ALIGNMENT_LEFT = 0;
cc.TEXT_ALIGNMENT_CENTER = 1;
cc.TEXT_ALIGNMENT_RIGHT = 2;
cc.VERTICAL_TEXT_ALIGNMENT_TOP = 0;
cc.VERTICAL_TEXT_ALIGNMENT_CENTER = 1;
cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM = 2;
cc._Dictionary = cc.Class.extend({
    _keyMapTb: null,
    _valueMapTb: null,
    __currId: 0,
    ctor: function () {
        this._keyMapTb = {};
        this._valueMapTb = {};
        this.__currId = 2 << (0 | (Math.random() * 10));
    },
    __getKey: function () {
        this.__currId++;
        return "key_" + this.__currId;
    },
    setObject: function (value, key) {
        if (key == null)
            return;
        var keyId = this.__getKey();
        this._keyMapTb[keyId] = key;
        this._valueMapTb[keyId] = value;
    },
    objectForKey: function (key) {
        if (key == null)
            return null;
        var locKeyMapTb = this._keyMapTb;
        for (var keyId in locKeyMapTb) {
            if (locKeyMapTb[keyId] === key)
                return this._valueMapTb[keyId];
        }
        return null;
    },
    valueForKey: function (key) {
        return this.objectForKey(key);
    },
    removeObjectForKey: function (key) {
        if (key == null)
            return;
        var locKeyMapTb = this._keyMapTb;
        for (var keyId in locKeyMapTb) {
            if (locKeyMapTb[keyId] === key) {
                delete this._valueMapTb[keyId];
                delete locKeyMapTb[keyId];
                return;
            }
        }
    },
    removeObjectsForKeys: function (keys) {
        if (keys == null)
            return;
        for (var i = 0; i < keys.length; i++)
            this.removeObjectForKey(keys[i]);
    },
    allKeys: function () {
        var keyArr = [], locKeyMapTb = this._keyMapTb;
        for (var key in locKeyMapTb)
            keyArr.push(locKeyMapTb[key]);
        return keyArr;
    },
    removeAllObjects: function () {
        this._keyMapTb = {};
        this._valueMapTb = {};
    },
    count: function () {
        return this.allKeys().length;
    }
});
cc.FontDefinition = function (properties) {
    var _t = this;
    _t.fontName = "Arial";
    _t.fontSize = 12;
    _t.textAlign = cc.TEXT_ALIGNMENT_CENTER;
    _t.verticalAlign = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
    _t.fillStyle = cc.color(255, 255, 255, 255);
    _t.boundingWidth = 0;
    _t.boundingHeight = 0;
    _t.strokeEnabled = false;
    _t.strokeStyle = cc.color(255, 255, 255, 255);
    _t.lineWidth = 1;
    _t.lineHeight = "normal";
    _t.fontStyle = "normal";
    _t.fontWeight = "normal";
    _t.shadowEnabled = false;
    _t.shadowOffsetX = 0;
    _t.shadowOffsetY = 0;
    _t.shadowBlur = 0;
    _t.shadowOpacity = 1.0;
    if(properties && properties instanceof Object){
         for(var key in properties){
             _t[key] = properties[key];
         }
    }
};
cc.FontDefinition.prototype._getCanvasFontStr = function(){
    var lineHeight = !this.lineHeight.charAt ? this.lineHeight+"px" : this.lineHeight;
    return this.fontStyle + " " + this.fontWeight + " " + this.fontSize + "px/"+lineHeight+" '" + this.fontName + "'";
};
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
        cc.assert(cc.isFunction(cc._tmp.PrototypeColor), cc._LogInfos.MissingFile, "CCTypesPropertyDefine.js");
        cc._tmp.PrototypeColor();
        delete cc._tmp.PrototypeColor;
    }
});
cc.Touches = [];
cc.TouchesIntergerDict = {};
cc.DENSITYDPI_DEVICE = "device-dpi";
cc.DENSITYDPI_HIGH = "high-dpi";
cc.DENSITYDPI_MEDIUM = "medium-dpi";
cc.DENSITYDPI_LOW = "low-dpi";
var __BrowserGetter = {
    init: function(){
        this.html = document.getElementsByTagName("html")[0];
    },
    availWidth: function(frame){
        if(!frame || frame === this.html)
            return window.innerWidth;
        else
            return frame.clientWidth;
    },
    availHeight: function(frame){
        if(!frame || frame === this.html)
            return window.innerHeight;
        else
            return frame.clientHeight;
    },
    meta: {
        "width": "device-width"
    },
    adaptationType: cc.sys.browserType
};
if(window.navigator.userAgent.indexOf("OS 8_1_") > -1)
    __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_MIUI;
if(cc.sys.os === cc.sys.OS_IOS)
    __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_SAFARI;
switch(__BrowserGetter.adaptationType){
    case cc.sys.BROWSER_TYPE_SAFARI:
        __BrowserGetter.meta["minimal-ui"] = "true";
        __BrowserGetter.availWidth = function(frame){
            return frame.clientWidth;
        };
        __BrowserGetter.availHeight = function(frame){
            return frame.clientHeight;
        };
        break;
    case cc.sys.BROWSER_TYPE_CHROME:
        __BrowserGetter.__defineGetter__("target-densitydpi", function(){
            return cc.view._targetDensityDPI;
        });
    case cc.sys.BROWSER_TYPE_SOUGOU:
    case cc.sys.BROWSER_TYPE_UC:
        __BrowserGetter.availWidth = function(frame){
            return frame.clientWidth;
        };
        __BrowserGetter.availHeight = function(frame){
            return frame.clientHeight;
        };
        break;
    case cc.sys.BROWSER_TYPE_MIUI:
        __BrowserGetter.init = function(view){
            if(view.__resizeWithBrowserSize) return;
            var resize = function(){
                view.setDesignResolutionSize(
                    view._designResolutionSize.width,
                    view._designResolutionSize.height,
                    view._resolutionPolicy
                );
                window.removeEventListener("resize", resize, false);
            };
            window.addEventListener("resize", resize, false);
        };
        break;
}
var _scissorRect = cc.rect();
cc.EGLView = cc.Class.extend({
    _delegate: null,
    _frameSize: null,
    _designResolutionSize: null,
    _originalDesignResolutionSize: null,
    _viewPortRect: null,
    _visibleRect: null,
    _retinaEnabled: false,
    _autoFullScreen: false,
    _devicePixelRatio: 1,
    _viewName: "",
    _resizeCallback: null,
    _scaleX: 1,
    _originalScaleX: 1,
    _scaleY: 1,
    _originalScaleY: 1,
    _isRotated: false,
    _orientation: 3,
    _resolutionPolicy: null,
    _rpExactFit: null,
    _rpShowAll: null,
    _rpNoBorder: null,
    _rpFixedHeight: null,
    _rpFixedWidth: null,
    _initialized: false,
    _contentTranslateLeftTop: null,
    _frame: null,
    _frameZoomFactor: 1.0,
    __resizeWithBrowserSize: false,
    _isAdjustViewPort: true,
    _targetDensityDPI: null,
    ctor: function () {
        var _t = this, d = document, _strategyer = cc.ContainerStrategy, _strategy = cc.ContentStrategy;
        __BrowserGetter.init(this);
        _t._frame = (cc.container.parentNode === d.body) ? d.documentElement : cc.container.parentNode;
        _t._frameSize = cc.size(0, 0);
        _t._initFrameSize();
        var w = cc._canvas.width, h = cc._canvas.height;
        _t._designResolutionSize = cc.size(w, h);
        _t._originalDesignResolutionSize = cc.size(w, h);
        _t._viewPortRect = cc.rect(0, 0, w, h);
        _t._visibleRect = cc.rect(0, 0, w, h);
        _t._contentTranslateLeftTop = {left: 0, top: 0};
        _t._viewName = "Cocos2dHTML5";
        var sys = cc.sys;
        _t.enableRetina(sys.os === sys.OS_IOS || sys.os === sys.OS_OSX);
        _t.enableAutoFullScreen(sys.isMobile && sys.browserType !== sys.BROWSER_TYPE_BAIDU);
        cc.visibleRect && cc.visibleRect.init(_t._visibleRect);
        _t._rpExactFit = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.EXACT_FIT);
        _t._rpShowAll = new cc.ResolutionPolicy(_strategyer.PROPORTION_TO_FRAME, _strategy.SHOW_ALL);
        _t._rpNoBorder = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.NO_BORDER);
        _t._rpFixedHeight = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_HEIGHT);
        _t._rpFixedWidth = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_WIDTH);
        _t._targetDensityDPI = cc.DENSITYDPI_HIGH;
    },
    _resizeEvent: function () {
        var view;
        if (this.setDesignResolutionSize) {
            view = this;
        } else {
            view = cc.view;
        }
        var prevFrameW = view._frameSize.width, prevFrameH = view._frameSize.height, prevRotated = view._isRotated;
        view._initFrameSize();
        if (view._isRotated === prevRotated && view._frameSize.width === prevFrameW && view._frameSize.height === prevFrameH)
            return;
        if (view._resizeCallback) {
            view._resizeCallback.call();
        }
        var width = view._originalDesignResolutionSize.width;
        var height = view._originalDesignResolutionSize.height;
        if (width > 0) {
            view.setDesignResolutionSize(width, height, view._resolutionPolicy);
        }
    },
    setTargetDensityDPI: function(densityDPI){
        this._targetDensityDPI = densityDPI;
        this._adjustViewportMeta();
    },
    getTargetDensityDPI: function(){
        return this._targetDensityDPI;
    },
    resizeWithBrowserSize: function (enabled) {
        if (enabled) {
            if (!this.__resizeWithBrowserSize) {
                this.__resizeWithBrowserSize = true;
                window.addEventListener('resize', this._resizeEvent);
                window.addEventListener('orientationchange', this._resizeEvent);
            }
        } else {
            if (this.__resizeWithBrowserSize) {
                this.__resizeWithBrowserSize = false;
                window.removeEventListener('resize', this._resizeEvent);
                window.removeEventListener('orientationchange', this._resizeEvent);
            }
        }
    },
    setResizeCallback: function (callback) {
        if (cc.isFunction(callback) || callback == null) {
            this._resizeCallback = callback;
        }
    },
    setOrientation: function (orientation) {
        orientation = orientation & cc.ORIENTATION_AUTO;
        if (orientation) {
            this._orientation = orientation;
        }
    },
    _initFrameSize: function () {
        var locFrameSize = this._frameSize;
        var w = __BrowserGetter.availWidth(this._frame);
        var h = __BrowserGetter.availHeight(this._frame);
        var isLandscape = w >= h;
        if (!cc.sys.isMobile ||
            (isLandscape && this._orientation & cc.ORIENTATION_LANDSCAPE) ||
            (!isLandscape && this._orientation & cc.ORIENTATION_PORTRAIT)) {
            locFrameSize.width = w;
            locFrameSize.height = h;
            cc.container.style['-webkit-transform'] = 'rotate(0deg)';
            cc.container.style.transform = 'rotate(0deg)';
            this._isRotated = false;
        }
        else {
            locFrameSize.width = h;
            locFrameSize.height = w;
            cc.container.style['-webkit-transform'] = 'rotate(90deg)';
            cc.container.style.transform = 'rotate(90deg)';
            cc.container.style['-webkit-transform-origin'] = '0px 0px 0px';
            cc.container.style.transformOrigin = '0px 0px 0px';
            this._isRotated = true;
        }
    },
    _adjustSizeKeepCanvasSize: function () {
        var designWidth = this._originalDesignResolutionSize.width;
        var designHeight = this._originalDesignResolutionSize.height;
        if (designWidth > 0)
            this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy);
    },
    _setViewportMeta: function (metas, overwrite) {
        var vp = document.getElementById("cocosMetaElement");
        if(vp && overwrite){
            document.head.removeChild(vp);
        }
        var elems = document.getElementsByName("viewport"),
            currentVP = elems ? elems[0] : null,
            content, key, pattern;
        content = currentVP ? currentVP.content : "";
        vp = vp || document.createElement("meta");
        vp.id = "cocosMetaElement";
        vp.name = "viewport";
        vp.content = "";
        for (key in metas) {
            if (content.indexOf(key) == -1) {
                content += "," + key + "=" + metas[key];
            }
            else if (overwrite) {
                pattern = new RegExp(key+"\s*=\s*[^,]+");
                content.replace(pattern, key + "=" + metas[key]);
            }
        }
        if(/^,/.test(content))
            content = content.substr(1);
        vp.content = content;
        if (currentVP)
            currentVP.content = content;
        document.head.appendChild(vp);
    },
    _adjustViewportMeta: function () {
        if (this._isAdjustViewPort) {
            this._setViewportMeta(__BrowserGetter.meta, false);
            this._isAdjustViewPort = false;
        }
    },
    _setScaleXYForRenderTexture: function () {
        var scaleFactor = cc.contentScaleFactor();
        this._scaleX = scaleFactor;
        this._scaleY = scaleFactor;
    },
    _resetScale: function () {
        this._scaleX = this._originalScaleX;
        this._scaleY = this._originalScaleY;
    },
    _adjustSizeToBrowser: function () {
    },
    initialize: function () {
        this._initialized = true;
    },
    adjustViewPort: function (enabled) {
        this._isAdjustViewPort = enabled;
    },
    enableRetina: function(enabled) {
        this._retinaEnabled = enabled ? true : false;
    },
    isRetinaEnabled: function() {
        return this._retinaEnabled;
    },
    enableAutoFullScreen: function(enabled) {
        if (enabled && enabled !== this._autoFullScreen && cc.sys.isMobile && this._frame === document.documentElement) {
            this._autoFullScreen = true;
            cc.screen.autoFullScreen(this._frame);
        }
        else {
            this._autoFullScreen = false;
        }
    },
    isAutoFullScreenEnabled: function() {
        return this._autoFullScreen;
    },
    end: function () {
    },
    isOpenGLReady: function () {
        return (cc.game.canvas && cc._renderContext);
    },
    setFrameZoomFactor: function (zoomFactor) {
        this._frameZoomFactor = zoomFactor;
        this.centerWindow();
        cc.director.setProjection(cc.director.getProjection());
    },
    swapBuffers: function () {
    },
    setIMEKeyboardState: function (isOpen) {
    },
    setContentTranslateLeftTop: function (offsetLeft, offsetTop) {
        this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop};
    },
    getContentTranslateLeftTop: function () {
        return this._contentTranslateLeftTop;
    },
    getCanvasSize: function () {
        return cc.size(cc._canvas.width, cc._canvas.height);
    },
    getFrameSize: function () {
        return cc.size(this._frameSize.width, this._frameSize.height);
    },
    setFrameSize: function (width, height) {
        this._frameSize.width = width;
        this._frameSize.height = height;
        this._frame.style.width = width + "px";
        this._frame.style.height = height + "px";
        this._resizeEvent();
        cc.director.setProjection(cc.director.getProjection());
    },
    centerWindow: function () {
    },
    getVisibleSize: function () {
        return cc.size(this._visibleRect.width,this._visibleRect.height);
    },
    getVisibleSizeInPixel: function () {
        return cc.size( this._visibleRect.width * this._scaleX,
                        this._visibleRect.height * this._scaleY );
    },
    getVisibleOrigin: function () {
        return cc.p(this._visibleRect.x,this._visibleRect.y);
    },
    getVisibleOriginInPixel: function () {
        return cc.p(this._visibleRect.x * this._scaleX,
                    this._visibleRect.y * this._scaleY);
    },
    canSetContentScaleFactor: function () {
        return true;
    },
    getResolutionPolicy: function () {
        return this._resolutionPolicy;
    },
    setResolutionPolicy: function (resolutionPolicy) {
        var _t = this;
        if (resolutionPolicy instanceof cc.ResolutionPolicy) {
            _t._resolutionPolicy = resolutionPolicy;
        }
        else {
            var _locPolicy = cc.ResolutionPolicy;
            if(resolutionPolicy === _locPolicy.EXACT_FIT)
                _t._resolutionPolicy = _t._rpExactFit;
            if(resolutionPolicy === _locPolicy.SHOW_ALL)
                _t._resolutionPolicy = _t._rpShowAll;
            if(resolutionPolicy === _locPolicy.NO_BORDER)
                _t._resolutionPolicy = _t._rpNoBorder;
            if(resolutionPolicy === _locPolicy.FIXED_HEIGHT)
                _t._resolutionPolicy = _t._rpFixedHeight;
            if(resolutionPolicy === _locPolicy.FIXED_WIDTH)
                _t._resolutionPolicy = _t._rpFixedWidth;
        }
    },
    setDesignResolutionSize: function (width, height, resolutionPolicy) {
        if( !(width > 0 || height > 0) ){
            cc.log(cc._LogInfos.EGLView_setDesignResolutionSize);
            return;
        }
        this.setResolutionPolicy(resolutionPolicy);
        var policy = this._resolutionPolicy;
        if (!policy){
            cc.log(cc._LogInfos.EGLView_setDesignResolutionSize_2);
            return;
        }
        policy.preApply(this);
        if(cc.sys.isMobile)
            this._adjustViewportMeta();
        this._initFrameSize();
        this._originalDesignResolutionSize.width = this._designResolutionSize.width = width;
        this._originalDesignResolutionSize.height = this._designResolutionSize.height = height;
        var result = policy.apply(this, this._designResolutionSize);
        if(result.scale && result.scale.length === 2){
            this._scaleX = result.scale[0];
            this._scaleY = result.scale[1];
        }
        if(result.viewport){
            var vp = this._viewPortRect,
                vb = this._visibleRect,
                rv = result.viewport;
            vp.x = rv.x;
            vp.y = rv.y;
            vp.width = rv.width;
            vp.height = rv.height;
            vb.x = -vp.x / this._scaleX;
            vb.y = -vp.y / this._scaleY;
            vb.width = cc._canvas.width / this._scaleX;
            vb.height = cc._canvas.height / this._scaleY;
            cc._renderContext.setOffset && cc._renderContext.setOffset(vp.x, -vp.y);
        }
        var director = cc.director;
        director._winSizeInPoints.width = this._designResolutionSize.width;
        director._winSizeInPoints.height = this._designResolutionSize.height;
        policy.postApply(this);
        cc.winSize.width = director._winSizeInPoints.width;
        cc.winSize.height = director._winSizeInPoints.height;
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
            director.setGLDefaultValues();
        }
        this._originalScaleX = this._scaleX;
        this._originalScaleY = this._scaleY;
        if (cc.DOM)
            cc.DOM._resetEGLViewDiv();
        cc.visibleRect && cc.visibleRect.init(this._visibleRect);
    },
    getDesignResolutionSize: function () {
        return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
    },
    setRealPixelResolution: function (width, height, resolutionPolicy) {
        this._setViewportMeta({"width": width, "target-densitydpi": cc.DENSITYDPI_DEVICE}, true);
        document.body.style.width = width + "px";
        document.body.style.left = "0px";
        document.body.style.top = "0px";
        this.setDesignResolutionSize(width, height, resolutionPolicy);
    },
    setViewPortInPoints: function (x, y, w, h) {
        var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
        cc._renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
            (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
            (w * locScaleX * locFrameZoomFactor),
            (h * locScaleY * locFrameZoomFactor));
    },
    setScissorInPoints: function (x, y, w, h) {
        var zoomFactor = this._frameZoomFactor, scaleX = this._scaleX, scaleY = this._scaleY;
        _scissorRect.x = x;
        _scissorRect.y = y;
        _scissorRect.width = w;
        _scissorRect.height = h;
        cc._renderContext.scissor(x * scaleX * zoomFactor + this._viewPortRect.x * zoomFactor,
                                  y * scaleY * zoomFactor + this._viewPortRect.y * zoomFactor,
                                  w * scaleX * zoomFactor,
                                  h * scaleY * zoomFactor);
    },
    isScissorEnabled: function () {
        return cc._renderContext.isEnabled(gl.SCISSOR_TEST);
    },
    getScissorRect: function () {
        return cc.rect(_scissorRect);
    },
    setViewName: function (viewName) {
        if (viewName != null && viewName.length > 0) {
            this._viewName = viewName;
        }
    },
    getViewName: function () {
        return this._viewName;
    },
    getViewPortRect: function () {
        return this._viewPortRect;
    },
    getScaleX: function () {
        return this._scaleX;
    },
    getScaleY: function () {
        return this._scaleY;
    },
    getDevicePixelRatio: function() {
        return this._devicePixelRatio;
    },
    convertToLocationInView: function (tx, ty, relatedPos) {
        var x = this._devicePixelRatio * (tx - relatedPos.left);
        var y = this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty);
        return this._isRotated ? {x: this._viewPortRect.width - y, y: x} : {x: x, y: y};
    },
    _convertMouseToLocationInView: function(point, relatedPos) {
        var locViewPortRect = this._viewPortRect, _t = this;
        point.x = ((_t._devicePixelRatio * (point.x - relatedPos.left)) - locViewPortRect.x) / _t._scaleX;
        point.y = (_t._devicePixelRatio * (relatedPos.top + relatedPos.height - point.y) - locViewPortRect.y) / _t._scaleY;
    },
    _convertPointWithScale: function (point) {
        var viewport = this._viewPortRect;
        point.x = (point.x - viewport.x) / this._scaleX;
        point.y = (point.y - viewport.y) / this._scaleY;
    },
    _convertTouchesWithScale: function (touches) {
        var viewport = this._viewPortRect, scaleX = this._scaleX, scaleY = this._scaleY,
            selTouch, selPoint, selPrePoint;
        for( var i = 0; i < touches.length; i++){
            selTouch = touches[i];
            selPoint = selTouch._point;
            selPrePoint = selTouch._prevPoint;
            selPoint.x = (selPoint.x - viewport.x) / scaleX;
            selPoint.y = (selPoint.y - viewport.y) / scaleY;
            selPrePoint.x = (selPrePoint.x - viewport.x) / scaleX;
            selPrePoint.y = (selPrePoint.y - viewport.y) / scaleY;
        }
    }
});
cc.EGLView._getInstance = function () {
    if (!this._instance) {
        this._instance = this._instance || new cc.EGLView();
        this._instance.initialize();
    }
    return this._instance;
};
cc.ContainerStrategy = cc.Class.extend({
    preApply: function (view) {
    },
    apply: function (view, designedResolution) {
    },
    postApply: function (view) {
    },
    _setupContainer: function (view, w, h) {
        var locCanvas = cc.game.canvas, locContainer = cc.game.container;
        locContainer.style.width = locCanvas.style.width = w + 'px';
        locContainer.style.height = locCanvas.style.height = h + 'px';
        var devicePixelRatio = view._devicePixelRatio = 1;
        if (view.isRetinaEnabled())
            devicePixelRatio = view._devicePixelRatio = Math.min(2, window.devicePixelRatio || 1);
        locCanvas.width = w * devicePixelRatio;
        locCanvas.height = h * devicePixelRatio;
        cc._renderContext.resetCache && cc._renderContext.resetCache();
    },
    _fixContainer: function () {
        document.body.insertBefore(cc.container, document.body.firstChild);
        var bs = document.body.style;
        bs.width = window.innerWidth + "px";
        bs.height = window.innerHeight + "px";
        bs.overflow = "hidden";
        var contStyle = cc.container.style;
        contStyle.position = "fixed";
        contStyle.left = contStyle.top = "0px";
        document.body.scrollTop = 0;
    }
});
cc.ContentStrategy = cc.Class.extend({
    _result: {
        scale: [1, 1],
        viewport: null
    },
    _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
        Math.abs(containerW - contentW) < 2 && (contentW = containerW);
        Math.abs(containerH - contentH) < 2 && (contentH = containerH);
        var viewport = cc.rect(Math.round((containerW - contentW) / 2),
                               Math.round((containerH - contentH) / 2),
                               contentW, contentH);
        if (cc._renderType === cc.game.RENDER_TYPE_CANVAS){
        }
        this._result.scale = [scaleX, scaleY];
        this._result.viewport = viewport;
        return this._result;
    },
    preApply: function (view) {
    },
    apply: function (view, designedResolution) {
        return {"scale": [1, 1]};
    },
    postApply: function (view) {
    }
});
(function () {
    var EqualToFrame = cc.ContainerStrategy.extend({
        apply: function (view) {
            var frameH = view._frameSize.height, containerStyle = cc.container.style;
            this._setupContainer(view, view._frameSize.width, view._frameSize.height);
            if (view._isRotated) {
                containerStyle.marginLeft = frameH + 'px';
            }
            else {
                containerStyle.margin = '0px';
            }
        }
    });
    var ProportionalToFrame = cc.ContainerStrategy.extend({
        apply: function (view, designedResolution) {
            var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style,
                designW = designedResolution.width, designH = designedResolution.height,
                scaleX = frameW / designW, scaleY = frameH / designH,
                containerW, containerH;
            scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH);
            var offx = Math.round((frameW - containerW) / 2);
            var offy = Math.round((frameH - containerH) / 2);
            containerW = frameW - 2 * offx;
            containerH = frameH - 2 * offy;
            this._setupContainer(view, containerW, containerH);
            if (view._isRotated) {
                containerStyle.marginLeft = frameH + 'px';
            }
            else {
                containerStyle.margin = '0px';
            }
            containerStyle.paddingLeft = offx + "px";
            containerStyle.paddingRight = offx + "px";
            containerStyle.paddingTop = offy + "px";
            containerStyle.paddingBottom = offy + "px";
        }
    });
    var EqualToWindow = EqualToFrame.extend({
        preApply: function (view) {
            this._super(view);
            view._frame = document.documentElement;
        },
        apply: function (view) {
            this._super(view);
            this._fixContainer();
        }
    });
    var ProportionalToWindow = ProportionalToFrame.extend({
        preApply: function (view) {
            this._super(view);
            view._frame = document.documentElement;
        },
        apply: function (view, designedResolution) {
            this._super(view, designedResolution);
            this._fixContainer();
        }
    });
    var OriginalContainer = cc.ContainerStrategy.extend({
        apply: function (view) {
            this._setupContainer(view, cc._canvas.width, cc._canvas.height);
        }
    });
    cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame();
    cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame();
    cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer();
    var ExactFit = cc.ContentStrategy.extend({
        apply: function (view, designedResolution) {
            var containerW = cc._canvas.width, containerH = cc._canvas.height,
                scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height;
            return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY);
        }
    });
    var ShowAll = cc.ContentStrategy.extend({
        apply: function (view, designedResolution) {
            var containerW = cc._canvas.width, containerH = cc._canvas.height,
                designW = designedResolution.width, designH = designedResolution.height,
                scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
                contentW, contentH;
            scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
                : (scale = scaleY, contentW = designW * scale, contentH = containerH);
            return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
        }
    });
    var NoBorder = cc.ContentStrategy.extend({
        apply: function (view, designedResolution) {
            var containerW = cc._canvas.width, containerH = cc._canvas.height,
                designW = designedResolution.width, designH = designedResolution.height,
                scaleX = containerW / designW, scaleY = containerH / designH, scale,
                contentW, contentH;
            scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH)
                : (scale = scaleX, contentW = containerW, contentH = designH * scale);
            return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
        }
    });
    var FixedHeight = cc.ContentStrategy.extend({
        apply: function (view, designedResolution) {
            var containerW = cc._canvas.width, containerH = cc._canvas.height,
                designH = designedResolution.height, scale = containerH / designH,
                contentW = containerW, contentH = containerH;
            return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
        },
        postApply: function (view) {
            cc.director._winSizeInPoints = view.getVisibleSize();
        }
    });
    var FixedWidth = cc.ContentStrategy.extend({
        apply: function (view, designedResolution) {
            var containerW = cc._canvas.width, containerH = cc._canvas.height,
                designW = designedResolution.width, scale = containerW / designW,
                contentW = containerW, contentH = containerH;
            return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
        },
        postApply: function (view) {
            cc.director._winSizeInPoints = view.getVisibleSize();
        }
    });
    cc.ContentStrategy.EXACT_FIT = new ExactFit();
    cc.ContentStrategy.SHOW_ALL = new ShowAll();
    cc.ContentStrategy.NO_BORDER = new NoBorder();
    cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight();
    cc.ContentStrategy.FIXED_WIDTH = new FixedWidth();
})();
cc.ResolutionPolicy = cc.Class.extend({
    _containerStrategy: null,
    _contentStrategy: null,
    ctor: function (containerStg, contentStg) {
        this.setContainerStrategy(containerStg);
        this.setContentStrategy(contentStg);
    },
    preApply: function (view) {
        this._containerStrategy.preApply(view);
        this._contentStrategy.preApply(view);
    },
    apply: function (view, designedResolution) {
        this._containerStrategy.apply(view, designedResolution);
        return this._contentStrategy.apply(view, designedResolution);
    },
    postApply: function (view) {
        this._containerStrategy.postApply(view);
        this._contentStrategy.postApply(view);
    },
    setContainerStrategy: function (containerStg) {
        if (containerStg instanceof cc.ContainerStrategy)
            this._containerStrategy = containerStg;
    },
    setContentStrategy: function (contentStg) {
        if (contentStg instanceof cc.ContentStrategy)
            this._contentStrategy = contentStg;
    }
});
cc.ResolutionPolicy.EXACT_FIT = 0;
cc.ResolutionPolicy.NO_BORDER = 1;
cc.ResolutionPolicy.SHOW_ALL = 2;
cc.ResolutionPolicy.FIXED_HEIGHT = 3;
cc.ResolutionPolicy.FIXED_WIDTH = 4;
cc.ResolutionPolicy.UNKNOWN = 5;
cc.screen = {
    _supportsFullScreen: false,
    _preOnFullScreenChange: null,
    _touchEvent: "",
    _fn: null,
    _fnMap: [
        [
            'requestFullscreen',
            'exitFullscreen',
            'fullscreenchange',
            'fullscreenEnabled',
            'fullscreenElement'
        ],
        [
            'requestFullScreen',
            'exitFullScreen',
            'fullScreenchange',
            'fullScreenEnabled',
            'fullScreenElement'
        ],
        [
            'webkitRequestFullScreen',
            'webkitCancelFullScreen',
            'webkitfullscreenchange',
            'webkitIsFullScreen',
            'webkitCurrentFullScreenElement'
        ],
        [
            'mozRequestFullScreen',
            'mozCancelFullScreen',
            'mozfullscreenchange',
            'mozFullScreen',
            'mozFullScreenElement'
        ],
        [
            'msRequestFullscreen',
            'msExitFullscreen',
            'MSFullscreenChange',
            'msFullscreenEnabled',
            'msFullscreenElement'
        ]
    ],
    init: function () {
        this._fn = {};
        var i, val, map = this._fnMap, valL;
        for (i = 0, l = map.length; i < l; i++) {
            val = map[i];
            if (val && val[1] in document) {
                for (i = 0, valL = val.length; i < valL; i++) {
                    this._fn[map[0][i]] = val[i];
                }
                break;
            }
        }
        this._supportsFullScreen = (typeof this._fn.requestFullscreen !== 'undefined');
        this._touchEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown';
    },
    fullScreen: function () {
        if(!this._supportsFullScreen)   return false;
        else if( document[this._fn.fullscreenElement] === undefined || document[this._fn.fullscreenElement] === null )
            return false;
        else
            return true;
    },
    requestFullScreen: function (element, onFullScreenChange) {
        if (!this._supportsFullScreen) {
            return;
        }
        element = element || document.documentElement;
        if (onFullScreenChange) {
            var eventName = this._fn.fullscreenchange;
            if (this._preOnFullScreenChange) {
                document.removeEventListener(eventName, this._preOnFullScreenChange);
            }
            this._preOnFullScreenChange = onFullScreenChange;
            document.addEventListener(eventName, onFullScreenChange, false);
        }
        return element[this._fn.requestFullscreen]();
    },
    exitFullScreen: function () {
        return this._supportsFullScreen ? document[this._fn.exitFullscreen]() : true;
    },
    autoFullScreen: function (element, onFullScreenChange) {
        element = element || document.body;
        var touchTarget = cc.game.canvas || element;
        var theScreen = this;
        function callback() {
            touchTarget.removeEventListener(theScreen._touchEvent, callback);
            theScreen.requestFullScreen(element, onFullScreenChange);
        }
        this.requestFullScreen(element, onFullScreenChange);
        touchTarget.addEventListener(this._touchEvent, callback);
    }
};
cc.screen.init();
cc.visibleRect = {
    topLeft:cc.p(0,0),
    topRight:cc.p(0,0),
    top:cc.p(0,0),
    bottomLeft:cc.p(0,0),
    bottomRight:cc.p(0,0),
    bottom:cc.p(0,0),
    center:cc.p(0,0),
    left:cc.p(0,0),
    right:cc.p(0,0),
    width:0,
    height:0,
    init:function(visibleRect){
        var w = this.width = visibleRect.width;
        var h = this.height = visibleRect.height;
        var l = visibleRect.x,
            b = visibleRect.y,
            t = b + h,
            r = l + w;
        this.topLeft.x = l;
        this.topLeft.y = t;
        this.topRight.x = r;
        this.topRight.y = t;
        this.top.x = l + w/2;
        this.top.y = t;
        this.bottomLeft.x = l;
        this.bottomLeft.y = b;
        this.bottomRight.x = r;
        this.bottomRight.y = b;
        this.bottom.x = l + w/2;
        this.bottom.y = b;
        this.center.x = l + w/2;
        this.center.y = b + h/2;
        this.left.x = l;
        this.left.y = b + h/2;
        this.right.x = r;
        this.right.y = b + h/2;
    }
};
cc.UIInterfaceOrientationLandscapeLeft = -90;
cc.UIInterfaceOrientationLandscapeRight = 90;
cc.UIInterfaceOrientationPortraitUpsideDown = 180;
cc.UIInterfaceOrientationPortrait = 0;
cc.inputManager = {
    _mousePressed: false,
    _isRegisterEvent: false,
    _preTouchPoint: cc.p(0,0),
    _prevMousePoint: cc.p(0,0),
    _preTouchPool: [],
    _preTouchPoolPointer: 0,
    _touches: [],
    _touchesIntegerDict:{},
    _indexBitsUsed: 0,
    _maxTouches: 5,
    _accelEnabled: false,
    _accelInterval: 1/30,
    _accelMinus: 1,
    _accelCurTime: 0,
    _acceleration: null,
    _accelDeviceEvent: null,
    _getUnUsedIndex: function () {
        var temp = this._indexBitsUsed;
        for (var i = 0; i < this._maxTouches; i++) {
            if (!(temp & 0x00000001)) {
                this._indexBitsUsed |= (1 << i);
                return i;
            }
            temp >>= 1;
        }
        return -1;
    },
    _removeUsedIndexBit: function (index) {
        if (index < 0 || index >= this._maxTouches)
            return;
        var temp = 1 << index;
        temp = ~temp;
        this._indexBitsUsed &= temp;
    },
    _glView: null,
    handleTouchesBegin: function (touches) {
        var selTouch, index, curTouch, touchID, handleTouches = [], locTouchIntDict = this._touchesIntegerDict;
        for(var i = 0, len = touches.length; i< len; i ++){
            selTouch = touches[i];
            touchID = selTouch.getID();
            index = locTouchIntDict[touchID];
            if(index == null){
                var unusedIndex = this._getUnUsedIndex();
                if (unusedIndex === -1) {
                    cc.log(cc._LogInfos.inputManager_handleTouchesBegin, unusedIndex);
                    continue;
                }
                curTouch = this._touches[unusedIndex] = new cc.Touch(selTouch._point.x, selTouch._point.y, selTouch.getID());
                curTouch._setPrevPoint(selTouch._prevPoint);
                locTouchIntDict[touchID] = unusedIndex;
                handleTouches.push(curTouch);
            }
        }
        if(handleTouches.length > 0){
            this._glView._convertTouchesWithScale(handleTouches);
            var touchEvent = new cc.EventTouch(handleTouches);
            touchEvent._eventCode = cc.EventTouch.EventCode.BEGAN;
            cc.eventManager.dispatchEvent(touchEvent);
        }
    },
    handleTouchesMove: function(touches){
        var selTouch, index, touchID, handleTouches = [], locTouches = this._touches;
        for(var i = 0, len = touches.length; i< len; i ++){
            selTouch = touches[i];
            touchID = selTouch.getID();
            index = this._touchesIntegerDict[touchID];
            if(index == null){
                continue;
            }
            if(locTouches[index]){
                locTouches[index]._setPoint(selTouch._point);
                locTouches[index]._setPrevPoint(selTouch._prevPoint);
                handleTouches.push(locTouches[index]);
            }
        }
        if(handleTouches.length > 0){
            this._glView._convertTouchesWithScale(handleTouches);
            var touchEvent = new cc.EventTouch(handleTouches);
            touchEvent._eventCode = cc.EventTouch.EventCode.MOVED;
            cc.eventManager.dispatchEvent(touchEvent);
        }
    },
    handleTouchesEnd: function(touches){
        var handleTouches = this.getSetOfTouchesEndOrCancel(touches);
        if(handleTouches.length > 0) {
            this._glView._convertTouchesWithScale(handleTouches);
            var touchEvent = new cc.EventTouch(handleTouches);
            touchEvent._eventCode = cc.EventTouch.EventCode.ENDED;
            cc.eventManager.dispatchEvent(touchEvent);
        }
    },
    handleTouchesCancel: function(touches){
        var handleTouches = this.getSetOfTouchesEndOrCancel(touches);
        if(handleTouches.length > 0) {
            this._glView._convertTouchesWithScale(handleTouches);
            var touchEvent = new cc.EventTouch(handleTouches);
            touchEvent._eventCode = cc.EventTouch.EventCode.CANCELLED;
            cc.eventManager.dispatchEvent(touchEvent);
        }
    },
    getSetOfTouchesEndOrCancel: function(touches) {
        var selTouch, index, touchID, handleTouches = [], locTouches = this._touches, locTouchesIntDict = this._touchesIntegerDict;
        for(var i = 0, len = touches.length; i< len; i ++){
            selTouch = touches[i];
            touchID = selTouch.getID();
            index = locTouchesIntDict[touchID];
            if(index == null){
                continue;
            }
            if(locTouches[index]){
                locTouches[index]._setPoint(selTouch._point);
                locTouches[index]._setPrevPoint(selTouch._prevPoint);
                handleTouches.push(locTouches[index]);
                this._removeUsedIndexBit(index);
                delete locTouchesIntDict[touchID];
            }
        }
        return handleTouches;
    },
    getHTMLElementPosition: function (element) {
        var docElem = document.documentElement;
        var win = window;
        var box = null;
        if (cc.isFunction(element.getBoundingClientRect)) {
            box = element.getBoundingClientRect();
        } else {
            box = {
                left: 0,
                top: 0,
                width: parseInt(element.style.width),
                height: parseInt(element.style.height)
            };
        }
        return {
            left: box.left + win.pageXOffset - docElem.clientLeft,
            top: box.top + win.pageYOffset - docElem.clientTop,
            width: box.width,
            height: box.height
        };
    },
    getPreTouch: function(touch){
        var preTouch = null;
        var locPreTouchPool = this._preTouchPool;
        var id = touch.getID();
        for (var i = locPreTouchPool.length - 1; i >= 0; i--) {
            if (locPreTouchPool[i].getID() === id) {
                preTouch = locPreTouchPool[i];
                break;
            }
        }
        if (!preTouch)
            preTouch = touch;
        return preTouch;
    },
    setPreTouch: function(touch){
        var find = false;
        var locPreTouchPool = this._preTouchPool;
        var id = touch.getID();
        for (var i = locPreTouchPool.length - 1; i >= 0; i--) {
            if (locPreTouchPool[i].getID() === id) {
                locPreTouchPool[i] = touch;
                find = true;
                break;
            }
        }
        if (!find) {
            if (locPreTouchPool.length <= 50) {
                locPreTouchPool.push(touch);
            } else {
                locPreTouchPool[this._preTouchPoolPointer] = touch;
                this._preTouchPoolPointer = (this._preTouchPoolPointer + 1) % 50;
            }
        }
    },
    getTouchByXY: function(tx, ty, pos){
        var locPreTouch = this._preTouchPoint;
        var location = this._glView.convertToLocationInView(tx, ty, pos);
        var touch = new cc.Touch(location.x,  location.y);
        touch._setPrevPoint(locPreTouch.x, locPreTouch.y);
        locPreTouch.x = location.x;
        locPreTouch.y = location.y;
        return touch;
    },
    getMouseEvent: function(location, pos, eventType){
        var locPreMouse = this._prevMousePoint;
        this._glView._convertMouseToLocationInView(location, pos);
        var mouseEvent = new cc.EventMouse(eventType);
        mouseEvent.setLocation(location.x, location.y);
        mouseEvent._setPrevCursor(locPreMouse.x, locPreMouse.y);
        locPreMouse.x = location.x;
        locPreMouse.y = location.y;
        return mouseEvent;
    },
    getPointByEvent: function(event, pos){
        if (event.pageX != null)
            return {x: event.pageX, y: event.pageY};
        pos.left -= document.body.scrollLeft;
        pos.top -= document.body.scrollTop;
        return {x: event.clientX, y: event.clientY};
    },
    getTouchesByEvent: function(event, pos){
        var touchArr = [], locView = this._glView;
        var touch_event, touch, preLocation;
        var locPreTouch = this._preTouchPoint;
        var length = event.changedTouches.length;
        for (var i = 0; i < length; i++) {
            touch_event = event.changedTouches[i];
            if (touch_event) {
                var location;
                if (cc.sys.BROWSER_TYPE_FIREFOX === cc.sys.browserType)
                    location = locView.convertToLocationInView(touch_event.pageX, touch_event.pageY, pos);
                else
                    location = locView.convertToLocationInView(touch_event.clientX, touch_event.clientY, pos);
                if (touch_event.identifier != null) {
                    touch = new cc.Touch(location.x, location.y, touch_event.identifier);
                    preLocation = this.getPreTouch(touch).getLocation();
                    touch._setPrevPoint(preLocation.x, preLocation.y);
                    this.setPreTouch(touch);
                } else {
                    touch = new cc.Touch(location.x, location.y);
                    touch._setPrevPoint(locPreTouch.x, locPreTouch.y);
                }
                locPreTouch.x = location.x;
                locPreTouch.y = location.y;
                touchArr.push(touch);
            }
        }
        return touchArr;
    },
    registerSystemEvent: function(element){
        if(this._isRegisterEvent) return;
        var locView = this._glView = cc.view;
        var selfPointer = this;
        var supportMouse = ('mouse' in cc.sys.capabilities), supportTouches = ('touches' in cc.sys.capabilities);
        var prohibition = false;
        if( cc.sys.isMobile)
            prohibition = true;
        if (supportMouse) {
            window.addEventListener('mousedown', function () {
                selfPointer._mousePressed = true;
            }, false);
            window.addEventListener('mouseup', function (event) {
                if(prohibition) return;
                var savePressed = selfPointer._mousePressed;
                selfPointer._mousePressed = false;
                if(!savePressed)
                    return;
                var pos = selfPointer.getHTMLElementPosition(element);
                var location = selfPointer.getPointByEvent(event, pos);
                if (!cc.rectContainsPoint(new cc.Rect(pos.left, pos.top, pos.width, pos.height), location)){
                    selfPointer.handleTouchesEnd([selfPointer.getTouchByXY(location.x, location.y, pos)]);
                    var mouseEvent = selfPointer.getMouseEvent(location,pos,cc.EventMouse.UP);
                    mouseEvent.setButton(event.button);
                    cc.eventManager.dispatchEvent(mouseEvent);
                }
            }, false);
            element.addEventListener("mousedown", function (event) {
                if(prohibition) return;
                selfPointer._mousePressed = true;
                var pos = selfPointer.getHTMLElementPosition(element);
                var location = selfPointer.getPointByEvent(event, pos);
                selfPointer.handleTouchesBegin([selfPointer.getTouchByXY(location.x, location.y, pos)]);
                var mouseEvent = selfPointer.getMouseEvent(location,pos,cc.EventMouse.DOWN);
                mouseEvent.setButton(event.button);
                cc.eventManager.dispatchEvent(mouseEvent);
                event.stopPropagation();
                event.preventDefault();
                element.focus();
            }, false);
            element.addEventListener("mouseup", function (event) {
                if(prohibition) return;
                selfPointer._mousePressed = false;
                var pos = selfPointer.getHTMLElementPosition(element);
                var location = selfPointer.getPointByEvent(event, pos);
                selfPointer.handleTouchesEnd([selfPointer.getTouchByXY(location.x, location.y, pos)]);
                var mouseEvent = selfPointer.getMouseEvent(location,pos,cc.EventMouse.UP);
                mouseEvent.setButton(event.button);
                cc.eventManager.dispatchEvent(mouseEvent);
                event.stopPropagation();
                event.preventDefault();
            }, false);
            element.addEventListener("mousemove", function (event) {
                if(prohibition) return;
                var pos = selfPointer.getHTMLElementPosition(element);
                var location = selfPointer.getPointByEvent(event, pos);
                selfPointer.handleTouchesMove([selfPointer.getTouchByXY(location.x, location.y, pos)]);
                var mouseEvent = selfPointer.getMouseEvent(location,pos,cc.EventMouse.MOVE);
                if(selfPointer._mousePressed)
                    mouseEvent.setButton(event.button);
                else
                    mouseEvent.setButton(null);
                cc.eventManager.dispatchEvent(mouseEvent);
                event.stopPropagation();
                event.preventDefault();
            }, false);
            element.addEventListener("mousewheel", function (event) {
                var pos = selfPointer.getHTMLElementPosition(element);
                var location = selfPointer.getPointByEvent(event, pos);
                var mouseEvent = selfPointer.getMouseEvent(location,pos,cc.EventMouse.SCROLL);
                mouseEvent.setButton(event.button);
                mouseEvent.setScrollData(0, event.wheelDelta);
                cc.eventManager.dispatchEvent(mouseEvent);
                event.stopPropagation();
                event.preventDefault();
            }, false);
            element.addEventListener("DOMMouseScroll", function(event) {
                var pos = selfPointer.getHTMLElementPosition(element);
                var location = selfPointer.getPointByEvent(event, pos);
                var mouseEvent = selfPointer.getMouseEvent(location,pos,cc.EventMouse.SCROLL);
                mouseEvent.setButton(event.button);
                mouseEvent.setScrollData(0, event.detail * -120);
                cc.eventManager.dispatchEvent(mouseEvent);
                event.stopPropagation();
                event.preventDefault();
            }, false);
        }
        if(window.navigator.msPointerEnabled){
            var _pointerEventsMap = {
                "MSPointerDown"     : selfPointer.handleTouchesBegin,
                "MSPointerMove"     : selfPointer.handleTouchesMove,
                "MSPointerUp"       : selfPointer.handleTouchesEnd,
                "MSPointerCancel"   : selfPointer.handleTouchesCancel
            };
            for(var eventName in _pointerEventsMap){
                (function(_pointerEvent, _touchEvent){
                    element.addEventListener(_pointerEvent, function (event){
                        var pos = selfPointer.getHTMLElementPosition(element);
                        pos.left -= document.documentElement.scrollLeft;
                        pos.top -= document.documentElement.scrollTop;
                        _touchEvent.call(selfPointer, [selfPointer.getTouchByXY(event.clientX, event.clientY, pos)]);
                        event.stopPropagation();
                    }, false);
                })(eventName, _pointerEventsMap[eventName]);
            }
        }
        if(supportTouches) {
            element.addEventListener("touchstart", function (event) {
                if (!event.changedTouches) return;
                var pos = selfPointer.getHTMLElementPosition(element);
                pos.left -= document.body.scrollLeft;
                pos.top -= document.body.scrollTop;
                selfPointer.handleTouchesBegin(selfPointer.getTouchesByEvent(event, pos));
                event.stopPropagation();
                event.preventDefault();
                element.focus();
            }, false);
            element.addEventListener("touchmove", function (event) {
                if (!event.changedTouches) return;
                var pos = selfPointer.getHTMLElementPosition(element);
                pos.left -= document.body.scrollLeft;
                pos.top -= document.body.scrollTop;
                selfPointer.handleTouchesMove(selfPointer.getTouchesByEvent(event, pos));
                event.stopPropagation();
                event.preventDefault();
            }, false);
            element.addEventListener("touchend", function (event) {
                if (!event.changedTouches) return;
                var pos = selfPointer.getHTMLElementPosition(element);
                pos.left -= document.body.scrollLeft;
                pos.top -= document.body.scrollTop;
                selfPointer.handleTouchesEnd(selfPointer.getTouchesByEvent(event, pos));
                event.stopPropagation();
                event.preventDefault();
            }, false);
            element.addEventListener("touchcancel", function (event) {
                if (!event.changedTouches) return;
                var pos = selfPointer.getHTMLElementPosition(element);
                pos.left -= document.body.scrollLeft;
                pos.top -= document.body.scrollTop;
                selfPointer.handleTouchesCancel(selfPointer.getTouchesByEvent(event, pos));
                event.stopPropagation();
                event.preventDefault();
            }, false);
        }
        this._registerKeyboardEvent();
        this._registerAccelerometerEvent();
        this._isRegisterEvent = true;
    },
    _registerKeyboardEvent: function(){},
    _registerAccelerometerEvent: function(){},
    update:function(dt){
        if(this._accelCurTime > this._accelInterval){
            this._accelCurTime -= this._accelInterval;
            cc.eventManager.dispatchEvent(new cc.EventAcceleration(this._acceleration));
        }
        this._accelCurTime += dt;
    }
};
cc.AffineTransform = function (a, b, c, d, tx, ty) {
    this.a = a;
    this.b = b;
    this.c = c;
    this.d = d;
    this.tx = tx;
    this.ty = ty;
};
cc.affineTransformMake = function (a, b, c, d, tx, ty) {
    return {a: a, b: b, c: c, d: d, tx: tx, ty: ty};
};
cc.pointApplyAffineTransform = function (point, transOrY, t) {
    var x, y;
    if (t === undefined) {
        t = transOrY;
        x = point.x;
        y = point.y;
    } else {
        x = point;
        y = transOrY;
    }
    return {x: t.a * x + t.c * y + t.tx, y: t.b * x + t.d * y + t.ty};
};
cc._pointApplyAffineTransform = function (x, y, t) {
    return cc.pointApplyAffineTransform(x, y, t);
};
cc.sizeApplyAffineTransform = function (size, t) {
    return {width: t.a * size.width + t.c * size.height, height: t.b * size.width + t.d * size.height};
};
cc.affineTransformMakeIdentity = function () {
    return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
};
cc.affineTransformIdentity = function () {
    return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
};
cc.rectApplyAffineTransform = function (rect, anAffineTransform) {
    var top = cc.rectGetMinY(rect);
    var left = cc.rectGetMinX(rect);
    var right = cc.rectGetMaxX(rect);
    var bottom = cc.rectGetMaxY(rect);
    var topLeft = cc.pointApplyAffineTransform(left, top, anAffineTransform);
    var topRight = cc.pointApplyAffineTransform(right, top, anAffineTransform);
    var bottomLeft = cc.pointApplyAffineTransform(left, bottom, anAffineTransform);
    var bottomRight = cc.pointApplyAffineTransform(right, bottom, anAffineTransform);
    var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
    var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
    var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
    var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
    return cc.rect(minX, minY, (maxX - minX), (maxY - minY));
};
cc._rectApplyAffineTransformIn = function(rect, anAffineTransform){
    var top = cc.rectGetMinY(rect);
    var left = cc.rectGetMinX(rect);
    var right = cc.rectGetMaxX(rect);
    var bottom = cc.rectGetMaxY(rect);
    var topLeft = cc.pointApplyAffineTransform(left, top, anAffineTransform);
    var topRight = cc.pointApplyAffineTransform(right, top, anAffineTransform);
    var bottomLeft = cc.pointApplyAffineTransform(left, bottom, anAffineTransform);
    var bottomRight = cc.pointApplyAffineTransform(right, bottom, anAffineTransform);
    var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
    var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
    var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
    var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
    rect.x = minX;
    rect.y = minY;
    rect.width = maxX - minX;
    rect.height = maxY - minY;
    return rect;
};
cc.affineTransformTranslate = function (t, tx, ty) {
    return {
        a: t.a,
        b: t.b,
        c: t.c,
        d: t.d,
        tx: t.tx + t.a * tx + t.c * ty,
        ty: t.ty + t.b * tx + t.d * ty
    };
};
cc.affineTransformScale = function (t, sx, sy) {
    return {a: t.a * sx, b: t.b * sx, c: t.c * sy, d: t.d * sy, tx: t.tx, ty: t.ty};
};
cc.affineTransformRotate = function (aTransform, anAngle) {
    var fSin = Math.sin(anAngle);
    var fCos = Math.cos(anAngle);
    return {a: aTransform.a * fCos + aTransform.c * fSin,
        b: aTransform.b * fCos + aTransform.d * fSin,
        c: aTransform.c * fCos - aTransform.a * fSin,
        d: aTransform.d * fCos - aTransform.b * fSin,
        tx: aTransform.tx,
        ty: aTransform.ty};
};
cc.affineTransformConcat = function (t1, t2) {
    return {a: t1.a * t2.a + t1.b * t2.c,
        b: t1.a * t2.b + t1.b * t2.d,
        c: t1.c * t2.a + t1.d * t2.c,
        d: t1.c * t2.b + t1.d * t2.d,
        tx: t1.tx * t2.a + t1.ty * t2.c + t2.tx,
        ty: t1.tx * t2.b + t1.ty * t2.d + t2.ty};
};
cc.affineTransformConcatIn = function (t1, t2) {
    var a = t1.a, b = t1.b, c = t1.c, d = t1.d, tx = t1.tx, ty = t1.ty;
    t1.a = a * t2.a + b * t2.c;
    t1.b = a * t2.b + b * t2.d;
    t1.c = c * t2.a + d * t2.c;
    t1.d = c * t2.b + d * t2.d;
    t1.tx = tx * t2.a + ty * t2.c + t2.tx;
    t1.ty = tx * t2.b + ty * t2.d + t2.ty;
    return t1;
};
cc.affineTransformEqualToTransform = function (t1, t2) {
    return ((t1.a === t2.a) && (t1.b === t2.b) && (t1.c === t2.c) && (t1.d === t2.d) && (t1.tx === t2.tx) && (t1.ty === t2.ty));
};
cc.affineTransformInvert = function (t) {
    var determinant = 1 / (t.a * t.d - t.b * t.c);
    return {a: determinant * t.d, b: -determinant * t.b, c: -determinant * t.c, d: determinant * t.a,
        tx: determinant * (t.c * t.ty - t.d * t.tx), ty: determinant * (t.b * t.tx - t.a * t.ty)};
};
cc.POINT_EPSILON = parseFloat('1.192092896e-07F');
cc.pNeg = function (point) {
    return cc.p(-point.x, -point.y);
};
cc.pAdd = function (v1, v2) {
    return cc.p(v1.x + v2.x, v1.y + v2.y);
};
cc.pSub = function (v1, v2) {
    return cc.p(v1.x - v2.x, v1.y - v2.y);
};
cc.pMult = function (point, floatVar) {
    return cc.p(point.x * floatVar, point.y * floatVar);
};
cc.pMidpoint = function (v1, v2) {
    return cc.pMult(cc.pAdd(v1, v2), 0.5);
};
cc.pDot = function (v1, v2) {
    return v1.x * v2.x + v1.y * v2.y;
};
cc.pCross = function (v1, v2) {
    return v1.x * v2.y - v1.y * v2.x;
};
cc.pPerp = function (point) {
    return cc.p(-point.y, point.x);
};
cc.pRPerp = function (point) {
    return cc.p(point.y, -point.x);
};
cc.pProject = function (v1, v2) {
    return cc.pMult(v2, cc.pDot(v1, v2) / cc.pDot(v2, v2));
};
cc.pRotate = function (v1, v2) {
    return cc.p(v1.x * v2.x - v1.y * v2.y, v1.x * v2.y + v1.y * v2.x);
};
cc.pUnrotate = function (v1, v2) {
    return cc.p(v1.x * v2.x + v1.y * v2.y, v1.y * v2.x - v1.x * v2.y);
};
cc.pLengthSQ = function (v) {
    return cc.pDot(v, v);
};
cc.pDistanceSQ = function(point1, point2){
    return cc.pLengthSQ(cc.pSub(point1,point2));
};
cc.pLength = function (v) {
    return Math.sqrt(cc.pLengthSQ(v));
};
cc.pDistance = function (v1, v2) {
    return cc.pLength(cc.pSub(v1, v2));
};
cc.pNormalize = function (v) {
    var n = cc.pLength(v);
    return n === 0 ? cc.p(v) : cc.pMult(v, 1.0 / n);
};
cc.pForAngle = function (a) {
    return cc.p(Math.cos(a), Math.sin(a));
};
cc.pToAngle = function (v) {
    return Math.atan2(v.y, v.x);
};
cc.clampf = function (value, min_inclusive, max_inclusive) {
    if (min_inclusive > max_inclusive) {
        var temp = min_inclusive;
        min_inclusive = max_inclusive;
        max_inclusive = temp;
    }
    return value < min_inclusive ? min_inclusive : value < max_inclusive ? value : max_inclusive;
};
cc.pClamp = function (p, min_inclusive, max_inclusive) {
    return cc.p(cc.clampf(p.x, min_inclusive.x, max_inclusive.x), cc.clampf(p.y, min_inclusive.y, max_inclusive.y));
};
cc.pFromSize = function (s) {
    return cc.p(s.width, s.height);
};
cc.pCompOp = function (p, opFunc) {
    return cc.p(opFunc(p.x), opFunc(p.y));
};
cc.pLerp = function (a, b, alpha) {
    return cc.pAdd(cc.pMult(a, 1 - alpha), cc.pMult(b, alpha));
};
cc.pFuzzyEqual = function (a, b, variance) {
    if (a.x - variance <= b.x && b.x <= a.x + variance) {
        if (a.y - variance <= b.y && b.y <= a.y + variance)
            return true;
    }
    return false;
};
cc.pCompMult = function (a, b) {
    return cc.p(a.x * b.x, a.y * b.y);
};
cc.pAngleSigned = function (a, b) {
    var a2 = cc.pNormalize(a);
    var b2 = cc.pNormalize(b);
    var angle = Math.atan2(a2.x * b2.y - a2.y * b2.x, cc.pDot(a2, b2));
    if (Math.abs(angle) < cc.POINT_EPSILON)
        return 0.0;
    return angle;
};
cc.pAngle = function (a, b) {
    var angle = Math.acos(cc.pDot(cc.pNormalize(a), cc.pNormalize(b)));
    if (Math.abs(angle) < cc.POINT_EPSILON) return 0.0;
    return angle;
};
cc.pRotateByAngle = function (v, pivot, angle) {
    var r = cc.pSub(v, pivot);
    var cosa = Math.cos(angle), sina = Math.sin(angle);
    var t = r.x;
    r.x = t * cosa - r.y * sina + pivot.x;
    r.y = t * sina + r.y * cosa + pivot.y;
    return r;
};
cc.pLineIntersect = function (A, B, C, D, retP) {
    if ((A.x === B.x && A.y === B.y) || (C.x === D.x && C.y === D.y)) {
        return false;
    }
    var BAx = B.x - A.x;
    var BAy = B.y - A.y;
    var DCx = D.x - C.x;
    var DCy = D.y - C.y;
    var ACx = A.x - C.x;
    var ACy = A.y - C.y;
    var denom = DCy * BAx - DCx * BAy;
    retP.x = DCx * ACy - DCy * ACx;
    retP.y = BAx * ACy - BAy * ACx;
    if (denom === 0) {
        if (retP.x === 0 || retP.y === 0) {
            return true;
        }
        return false;
    }
    retP.x = retP.x / denom;
    retP.y = retP.y / denom;
    return true;
};
cc.pSegmentIntersect = function (A, B, C, D) {
    var retP = cc.p(0, 0);
    if (cc.pLineIntersect(A, B, C, D, retP))
        if (retP.x >= 0.0 && retP.x <= 1.0 && retP.y >= 0.0 && retP.y <= 1.0)
            return true;
    return false;
};
cc.pIntersectPoint = function (A, B, C, D) {
    var retP = cc.p(0, 0);
    if (cc.pLineIntersect(A, B, C, D, retP)) {
        var P = cc.p(0, 0);
        P.x = A.x + retP.x * (B.x - A.x);
        P.y = A.y + retP.x * (B.y - A.y);
        return P;
    }
    return cc.p(0,0);
};
cc.pSameAs = function (A, B) {
    if ((A != null) && (B != null)) {
        return (A.x === B.x && A.y === B.y);
    }
    return false;
};
cc.pZeroIn = function(v) {
    v.x = 0;
    v.y = 0;
};
cc.pIn = function(v1, v2) {
    v1.x = v2.x;
    v1.y = v2.y;
};
cc.pMultIn = function(point, floatVar) {
    point.x *= floatVar;
    point.y *= floatVar;
};
cc.pSubIn = function(v1, v2) {
    v1.x -= v2.x;
    v1.y -= v2.y;
};
cc.pAddIn = function(v1, v2) {
    v1.x += v2.x;
    v1.y += v2.y;
};
cc.pNormalizeIn = function(v) {
    cc.pMultIn(v, 1.0 / Math.sqrt(v.x * v.x + v.y * v.y));
};
cc.Touch = cc.Class.extend({
    _point:null,
    _prevPoint:null,
    _id:0,
    _startPointCaptured: false,
    _startPoint:null,
    ctor:function (x, y, id) {
        this.setTouchInfo(id, x, y);
    },
    getLocation:function () {
        return {x: this._point.x, y: this._point.y};
    },
    getLocationX: function () {
        return this._point.x;
    },
    getLocationY: function () {
        return this._point.y;
    },
    getPreviousLocation:function () {
        return {x: this._prevPoint.x, y: this._prevPoint.y};
    },
    getStartLocation: function() {
        return {x: this._startPoint.x, y: this._startPoint.y};
    },
    getDelta:function () {
        return cc.pSub(this._point, this._prevPoint);
    },
    getLocationInView: function() {
        return {x: this._point.x, y: this._point.y};
    },
    getPreviousLocationInView: function(){
        return {x: this._prevPoint.x, y: this._prevPoint.y};
    },
    getStartLocationInView: function(){
        return {x: this._startPoint.x, y: this._startPoint.y};
    },
    getID:function () {
        return this._id;
    },
    getId:function () {
        cc.log("getId is deprecated. Please use getID instead.");
        return this._id;
    },
    setTouchInfo:function (id, x, y) {
        this._prevPoint = this._point;
        this._point = cc.p(x || 0, y || 0);
        this._id = id;
        if (!this._startPointCaptured) {
            this._startPoint = cc.p(this._point);
            cc.view._convertPointWithScale(this._startPoint);
            this._startPointCaptured = true;
        }
    },
    _setPoint: function(x, y){
        if(y === undefined){
            this._point.x = x.x;
            this._point.y = x.y;
        }else{
            this._point.x = x;
            this._point.y = y;
        }
    },
    _setPrevPoint:function (x, y) {
        if(y === undefined)
            this._prevPoint = cc.p(x.x, x.y);
        else
            this._prevPoint = cc.p(x || 0, y || 0);
    }
});
cc.Event = cc.Class.extend({
    _type: 0,
    _isStopped: false,
    _currentTarget: null,
    _setCurrentTarget: function (target) {
        this._currentTarget = target;
    },
    ctor: function (type) {
        this._type = type;
    },
    getType: function () {
        return this._type;
    },
    stopPropagation: function () {
        this._isStopped = true;
    },
    isStopped: function () {
        return this._isStopped;
    },
    getCurrentTarget: function () {
        return this._currentTarget;
    }
});
cc.Event.TOUCH = 0;
cc.Event.KEYBOARD = 1;
cc.Event.ACCELERATION = 2;
cc.Event.MOUSE = 3;
cc.Event.FOCUS = 4;
cc.Event.CUSTOM = 6;
cc.EventCustom = cc.Event.extend({
    _eventName: null,
    _userData: null,
    ctor: function (eventName) {
        cc.Event.prototype.ctor.call(this, cc.Event.CUSTOM);
        this._eventName = eventName;
    },
    setUserData: function (data) {
        this._userData = data;
    },
    getUserData: function () {
        return this._userData;
    },
    getEventName: function () {
        return this._eventName;
    }
});
cc.EventMouse = cc.Event.extend({
    _eventType: 0,
    _button: 0,
    _x: 0,
    _y: 0,
    _prevX: 0,
    _prevY: 0,
    _scrollX: 0,
    _scrollY: 0,
    ctor: function (eventType) {
        cc.Event.prototype.ctor.call(this, cc.Event.MOUSE);
        this._eventType = eventType;
    },
    setScrollData: function (scrollX, scrollY) {
        this._scrollX = scrollX;
        this._scrollY = scrollY;
    },
    getScrollX: function () {
        return this._scrollX;
    },
    getScrollY: function () {
        return this._scrollY;
    },
    setLocation: function (x, y) {
        this._x = x;
        this._y = y;
    },
    getLocation: function () {
        return {x: this._x, y: this._y};
    },
    getLocationInView: function() {
        return {x: this._x, y: cc.view._designResolutionSize.height - this._y};
    },
    _setPrevCursor: function (x, y) {
        this._prevX = x;
        this._prevY = y;
    },
    getDelta: function () {
        return {x: this._x - this._prevX, y: this._y - this._prevY};
    },
    getDeltaX: function () {
        return this._x - this._prevX;
    },
    getDeltaY: function () {
        return this._y - this._prevY;
    },
    setButton: function (button) {
        this._button = button;
    },
    getButton: function () {
        return this._button;
    },
    getLocationX: function () {
        return this._x;
    },
    getLocationY: function () {
        return this._y;
    }
});
cc.EventMouse.NONE = 0;
cc.EventMouse.DOWN = 1;
cc.EventMouse.UP = 2;
cc.EventMouse.MOVE = 3;
cc.EventMouse.SCROLL = 4;
cc.EventMouse.BUTTON_LEFT = 0;
cc.EventMouse.BUTTON_RIGHT = 2;
cc.EventMouse.BUTTON_MIDDLE = 1;
cc.EventMouse.BUTTON_4 = 3;
cc.EventMouse.BUTTON_5 = 4;
cc.EventMouse.BUTTON_6 = 5;
cc.EventMouse.BUTTON_7 = 6;
cc.EventMouse.BUTTON_8 = 7;
cc.EventTouch = cc.Event.extend({
    _eventCode: 0,
    _touches: null,
    ctor: function (arr) {
        cc.Event.prototype.ctor.call(this, cc.Event.TOUCH);
        this._touches = arr || [];
    },
    getEventCode: function () {
        return this._eventCode;
    },
    getTouches: function () {
        return this._touches;
    },
    _setEventCode: function (eventCode) {
        this._eventCode = eventCode;
    },
    _setTouches: function (touches) {
        this._touches = touches;
    }
});
cc.EventTouch.MAX_TOUCHES = 5;
cc.EventTouch.EventCode = {BEGAN: 0, MOVED: 1, ENDED: 2, CANCELLED: 3};
cc.EventFocus = cc.Event.extend({
    _widgetGetFocus: null,
    _widgetLoseFocus: null,
    ctor: function(widgetLoseFocus, widgetGetFocus){
        cc.Event.prototype.ctor.call(this, cc.Event.FOCUS);
        this._widgetGetFocus = widgetGetFocus;
        this._widgetLoseFocus = widgetLoseFocus;
    }
});
cc.EventListener = cc.Class.extend({
    _onEvent: null,
    _type: 0,
    _listenerID: null,
    _registered: false,
    _fixedPriority: 0,
    _node: null,
    _paused: true,
    _isEnabled: true,
    ctor: function (type, listenerID, callback) {
        this._onEvent = callback;
        this._type = type || 0;
        this._listenerID = listenerID || "";
    },
    _setPaused: function (paused) {
        this._paused = paused;
    },
    _isPaused: function () {
        return this._paused;
    },
    _setRegistered: function (registered) {
        this._registered = registered;
    },
    _isRegistered: function () {
        return this._registered;
    },
    _getType: function () {
        return this._type;
    },
    _getListenerID: function () {
        return this._listenerID;
    },
    _setFixedPriority: function (fixedPriority) {
        this._fixedPriority = fixedPriority;
    },
    _getFixedPriority: function () {
        return this._fixedPriority;
    },
    _setSceneGraphPriority: function (node) {
        this._node = node;
    },
    _getSceneGraphPriority: function () {
        return this._node;
    },
    checkAvailable: function () {
        return this._onEvent !== null;
    },
    clone: function () {
        return null;
    },
    setEnabled: function(enabled){
        this._isEnabled = enabled;
    },
    isEnabled: function(){
        return this._isEnabled;
    },
    retain:function () {
    },
    release:function () {
    }
});
cc.EventListener.UNKNOWN = 0;
cc.EventListener.TOUCH_ONE_BY_ONE = 1;
cc.EventListener.TOUCH_ALL_AT_ONCE = 2;
cc.EventListener.KEYBOARD = 3;
cc.EventListener.MOUSE = 4;
cc.EventListener.ACCELERATION = 6;
cc.EventListener.FOCUS = 7;
cc.EventListener.CUSTOM = 8;
cc._EventListenerCustom = cc.EventListener.extend({
    _onCustomEvent: null,
    ctor: function (listenerId, callback) {
        this._onCustomEvent = callback;
        var selfPointer = this;
        var listener = function (event) {
            if (selfPointer._onCustomEvent !== null)
                selfPointer._onCustomEvent(event);
        };
        cc.EventListener.prototype.ctor.call(this, cc.EventListener.CUSTOM, listenerId, listener);
    },
    checkAvailable: function () {
        return (cc.EventListener.prototype.checkAvailable.call(this) && this._onCustomEvent !== null);
    },
    clone: function () {
        return new cc._EventListenerCustom(this._listenerID, this._onCustomEvent);
    }
});
cc._EventListenerCustom.create = function (eventName, callback) {
    return new cc._EventListenerCustom(eventName, callback);
};
cc._EventListenerMouse = cc.EventListener.extend({
    onMouseDown: null,
    onMouseUp: null,
    onMouseMove: null,
    onMouseScroll: null,
    ctor: function () {
        var selfPointer = this;
        var listener = function (event) {
            var eventType = cc.EventMouse;
            switch (event._eventType) {
                case eventType.DOWN:
                    if (selfPointer.onMouseDown)
                        selfPointer.onMouseDown(event);
                    break;
                case eventType.UP:
                    if (selfPointer.onMouseUp)
                        selfPointer.onMouseUp(event);
                    break;
                case eventType.MOVE:
                    if (selfPointer.onMouseMove)
                        selfPointer.onMouseMove(event);
                    break;
                case eventType.SCROLL:
                    if (selfPointer.onMouseScroll)
                        selfPointer.onMouseScroll(event);
                    break;
                default:
                    break;
            }
        };
        cc.EventListener.prototype.ctor.call(this, cc.EventListener.MOUSE, cc._EventListenerMouse.LISTENER_ID, listener);
    },
    clone: function () {
        var eventListener = new cc._EventListenerMouse();
        eventListener.onMouseDown = this.onMouseDown;
        eventListener.onMouseUp = this.onMouseUp;
        eventListener.onMouseMove = this.onMouseMove;
        eventListener.onMouseScroll = this.onMouseScroll;
        return eventListener;
    },
    checkAvailable: function () {
        return true;
    }
});
cc._EventListenerMouse.LISTENER_ID = "__cc_mouse";
cc._EventListenerMouse.create = function () {
    return new cc._EventListenerMouse();
};
cc._EventListenerTouchOneByOne = cc.EventListener.extend({
    _claimedTouches: null,
    swallowTouches: false,
    onTouchBegan: null,
    onTouchMoved: null,
    onTouchEnded: null,
    onTouchCancelled: null,
    ctor: function () {
        cc.EventListener.prototype.ctor.call(this, cc.EventListener.TOUCH_ONE_BY_ONE, cc._EventListenerTouchOneByOne.LISTENER_ID, null);
        this._claimedTouches = [];
    },
    setSwallowTouches: function (needSwallow) {
        this.swallowTouches = needSwallow;
    },
    isSwallowTouches: function(){
        return this.swallowTouches;
    },
    clone: function () {
        var eventListener = new cc._EventListenerTouchOneByOne();
        eventListener.onTouchBegan = this.onTouchBegan;
        eventListener.onTouchMoved = this.onTouchMoved;
        eventListener.onTouchEnded = this.onTouchEnded;
        eventListener.onTouchCancelled = this.onTouchCancelled;
        eventListener.swallowTouches = this.swallowTouches;
        return eventListener;
    },
    checkAvailable: function () {
        if(!this.onTouchBegan){
            cc.log(cc._LogInfos._EventListenerTouchOneByOne_checkAvailable);
            return false;
        }
        return true;
    }
});
cc._EventListenerTouchOneByOne.LISTENER_ID = "__cc_touch_one_by_one";
cc._EventListenerTouchOneByOne.create = function () {
    return new cc._EventListenerTouchOneByOne();
};
cc._EventListenerTouchAllAtOnce = cc.EventListener.extend({
    onTouchesBegan: null,
    onTouchesMoved: null,
    onTouchesEnded: null,
    onTouchesCancelled: null,
    ctor: function(){
       cc.EventListener.prototype.ctor.call(this, cc.EventListener.TOUCH_ALL_AT_ONCE, cc._EventListenerTouchAllAtOnce.LISTENER_ID, null);
    },
    clone: function(){
        var eventListener = new cc._EventListenerTouchAllAtOnce();
        eventListener.onTouchesBegan = this.onTouchesBegan;
        eventListener.onTouchesMoved = this.onTouchesMoved;
        eventListener.onTouchesEnded = this.onTouchesEnded;
        eventListener.onTouchesCancelled = this.onTouchesCancelled;
        return eventListener;
    },
    checkAvailable: function(){
        if (this.onTouchesBegan === null && this.onTouchesMoved === null
            && this.onTouchesEnded === null && this.onTouchesCancelled === null) {
            cc.log(cc._LogInfos._EventListenerTouchAllAtOnce_checkAvailable);
            return false;
        }
        return true;
    }
});
cc._EventListenerTouchAllAtOnce.LISTENER_ID = "__cc_touch_all_at_once";
cc._EventListenerTouchAllAtOnce.create = function(){
     return new cc._EventListenerTouchAllAtOnce();
};
cc.EventListener.create = function(argObj){
    cc.assert(argObj&&argObj.event, cc._LogInfos.EventListener_create);
    var listenerType = argObj.event;
    delete argObj.event;
    var listener = null;
    if(listenerType === cc.EventListener.TOUCH_ONE_BY_ONE)
        listener = new cc._EventListenerTouchOneByOne();
    else if(listenerType === cc.EventListener.TOUCH_ALL_AT_ONCE)
        listener = new cc._EventListenerTouchAllAtOnce();
    else if(listenerType === cc.EventListener.MOUSE)
        listener = new cc._EventListenerMouse();
    else if(listenerType === cc.EventListener.CUSTOM){
        listener = new cc._EventListenerCustom(argObj.eventName, argObj.callback);
        delete argObj.eventName;
        delete argObj.callback;
    } else if(listenerType === cc.EventListener.KEYBOARD)
        listener = new cc._EventListenerKeyboard();
    else if(listenerType === cc.EventListener.ACCELERATION){
        listener = new cc._EventListenerAcceleration(argObj.callback);
        delete argObj.callback;
    } else if(listenerType === cc.EventListener.FOCUS)
        listener = new cc._EventListenerFocus();
    for(var key in argObj) {
        listener[key] = argObj[key];
    }
    return listener;
};
cc._EventListenerFocus = cc.EventListener.extend({
    clone: function(){
        var listener = new cc._EventListenerFocus();
        listener.onFocusChanged = this.onFocusChanged;
        return listener;
    },
    checkAvailable: function(){
        if(!this.onFocusChanged){
            cc.log("Invalid EventListenerFocus!");
            return false;
        }
        return true;
    },
    onFocusChanged: null,
    ctor: function(){
        var listener = function(event){
            if(this.onFocusChanged)
                this.onFocusChanged(event._widgetLoseFocus, event._widgetGetFocus);
        };
        cc.EventListener.prototype.ctor.call(this, cc.EventListener.FOCUS, cc._EventListenerFocus.LISTENER_ID, listener);
    }
});
cc._EventListenerFocus.LISTENER_ID = "__cc_focus_event";
cc._EventListenerVector = cc.Class.extend({
    _fixedListeners: null,
    _sceneGraphListeners: null,
    gt0Index: 0,
    ctor: function () {
        this._fixedListeners = [];
        this._sceneGraphListeners = [];
    },
    size: function () {
        return this._fixedListeners.length + this._sceneGraphListeners.length;
    },
    empty: function () {
        return (this._fixedListeners.length === 0) && (this._sceneGraphListeners.length === 0);
    },
    push: function (listener) {
        if (listener._getFixedPriority() === 0)
            this._sceneGraphListeners.push(listener);
        else
            this._fixedListeners.push(listener);
    },
    clearSceneGraphListeners: function () {
        this._sceneGraphListeners.length = 0;
    },
    clearFixedListeners: function () {
        this._fixedListeners.length = 0;
    },
    clear: function () {
        this._sceneGraphListeners.length = 0;
        this._fixedListeners.length = 0;
    },
    getFixedPriorityListeners: function () {
        return this._fixedListeners;
    },
    getSceneGraphPriorityListeners: function () {
        return this._sceneGraphListeners;
    }
});
cc.__getListenerID = function (event) {
    var eventType = cc.Event, getType = event.getType();
    if(getType === eventType.ACCELERATION)
        return cc._EventListenerAcceleration.LISTENER_ID;
    if(getType === eventType.CUSTOM)
        return event.getEventName();
    if(getType === eventType.KEYBOARD)
        return cc._EventListenerKeyboard.LISTENER_ID;
    if(getType === eventType.MOUSE)
        return cc._EventListenerMouse.LISTENER_ID;
    if(getType === eventType.FOCUS)
        return cc._EventListenerFocus.LISTENER_ID;
    if(getType === eventType.TOUCH){
        cc.log(cc._LogInfos.__getListenerID);
    }
    return "";
};
cc.eventManager = {
    DIRTY_NONE:0,
    DIRTY_FIXED_PRIORITY:1 <<0,
    DIRTY_SCENE_GRAPH_PRIORITY : 1<< 1,
    DIRTY_ALL: 3,
    _listenersMap: {},
    _priorityDirtyFlagMap: {},
    _nodeListenersMap: {},
    _nodePriorityMap: {},
    _globalZOrderNodeMap: {},
    _toAddedListeners: [],
    _toRemovedListeners: [],
    _dirtyNodes: [],
    _inDispatch: 0,
    _isEnabled: false,
    _nodePriorityIndex: 0,
    _internalCustomListenerIDs:[cc.game.EVENT_HIDE, cc.game.EVENT_SHOW],
    _setDirtyForNode: function (node) {
        if (this._nodeListenersMap[node.__instanceId] != null)
            this._dirtyNodes.push(node);
        var _children = node.getChildren();
        for(var i = 0, len = _children.length; i < len; i++)
            this._setDirtyForNode(_children[i]);
    },
    pauseTarget: function (node, recursive) {
        var listeners = this._nodeListenersMap[node.__instanceId], i, len;
        if (listeners) {
            for ( i = 0, len = listeners.length; i < len; i++)
                listeners[i]._setPaused(true);
        }
        if (recursive === true) {
            var locChildren = node.getChildren();
            for ( i = 0, len = locChildren.length; i< len; i++)
                this.pauseTarget(locChildren[i], true);
        }
    },
    resumeTarget: function (node, recursive) {
        var listeners = this._nodeListenersMap[node.__instanceId], i, len;
        if (listeners){
            for ( i = 0, len = listeners.length; i < len; i++)
                listeners[i]._setPaused(false);
        }
        this._setDirtyForNode(node);
        if (recursive === true) {
            var locChildren = node.getChildren();
            for ( i = 0, len = locChildren.length; i< len; i++)
                this.resumeTarget(locChildren[i], true);
        }
    },
    _addListener: function (listener) {
        if (this._inDispatch === 0)
            this._forceAddEventListener(listener);
        else
            this._toAddedListeners.push(listener);
    },
    _forceAddEventListener: function (listener) {
        var listenerID = listener._getListenerID();
        var listeners = this._listenersMap[listenerID];
        if (!listeners) {
            listeners = new cc._EventListenerVector();
            this._listenersMap[listenerID] = listeners;
        }
        listeners.push(listener);
        if (listener._getFixedPriority() === 0) {
            this._setDirty(listenerID, this.DIRTY_SCENE_GRAPH_PRIORITY);
            var node = listener._getSceneGraphPriority();
            if (node === null)
                cc.log(cc._LogInfos.eventManager__forceAddEventListener);
            this._associateNodeAndEventListener(node, listener);
            if (node.isRunning())
                this.resumeTarget(node);
        } else
            this._setDirty(listenerID, this.DIRTY_FIXED_PRIORITY);
    },
    _getListeners: function (listenerID) {
        return this._listenersMap[listenerID];
    },
    _updateDirtyFlagForSceneGraph: function () {
        if (this._dirtyNodes.length === 0)
            return;
        var locDirtyNodes = this._dirtyNodes, selListeners, selListener, locNodeListenersMap = this._nodeListenersMap;
        for (var i = 0, len = locDirtyNodes.length; i < len; i++) {
            selListeners = locNodeListenersMap[locDirtyNodes[i].__instanceId];
            if (selListeners) {
                for (var j = 0, listenersLen = selListeners.length; j < listenersLen; j++) {
                    selListener = selListeners[j];
                    if (selListener)
                        this._setDirty(selListener._getListenerID(), this.DIRTY_SCENE_GRAPH_PRIORITY);
                }
            }
        }
        this._dirtyNodes.length = 0;
    },
    _removeAllListenersInVector: function (listenerVector) {
        if (!listenerVector)
            return;
        var selListener;
        for (var i = 0; i < listenerVector.length;) {
            selListener = listenerVector[i];
            selListener._setRegistered(false);
            if (selListener._getSceneGraphPriority() != null){
                this._dissociateNodeAndEventListener(selListener._getSceneGraphPriority(), selListener);
                selListener._setSceneGraphPriority(null);
            }
            if (this._inDispatch === 0)
                cc.arrayRemoveObject(listenerVector, selListener);
            else
                ++i;
        }
    },
    _removeListenersForListenerID: function (listenerID) {
        var listeners = this._listenersMap[listenerID], i;
        if (listeners) {
            var fixedPriorityListeners = listeners.getFixedPriorityListeners();
            var sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
            this._removeAllListenersInVector(sceneGraphPriorityListeners);
            this._removeAllListenersInVector(fixedPriorityListeners);
            delete this._priorityDirtyFlagMap[listenerID];
            if (!this._inDispatch) {
                listeners.clear();
                delete this._listenersMap[listenerID];
            }
        }
        var locToAddedListeners = this._toAddedListeners, listener;
        for (i = 0; i < locToAddedListeners.length;) {
            listener = locToAddedListeners[i];
            if (listener && listener._getListenerID() === listenerID)
                cc.arrayRemoveObject(locToAddedListeners, listener);
            else
                ++i;
        }
    },
    _sortEventListeners: function (listenerID) {
        var dirtyFlag = this.DIRTY_NONE,  locFlagMap = this._priorityDirtyFlagMap;
        if (locFlagMap[listenerID])
            dirtyFlag = locFlagMap[listenerID];
        if (dirtyFlag !== this.DIRTY_NONE) {
            locFlagMap[listenerID] = this.DIRTY_NONE;
            if (dirtyFlag & this.DIRTY_FIXED_PRIORITY)
                this._sortListenersOfFixedPriority(listenerID);
            if (dirtyFlag & this.DIRTY_SCENE_GRAPH_PRIORITY){
                var rootNode = cc.director.getRunningScene();
                if(rootNode)
                    this._sortListenersOfSceneGraphPriority(listenerID, rootNode);
                else
                    locFlagMap[listenerID] = this.DIRTY_SCENE_GRAPH_PRIORITY;
            }
        }
    },
    _sortListenersOfSceneGraphPriority: function (listenerID, rootNode) {
        var listeners = this._getListeners(listenerID);
        if (!listeners)
            return;
        var sceneGraphListener = listeners.getSceneGraphPriorityListeners();
        if(!sceneGraphListener || sceneGraphListener.length === 0)
            return;
        this._nodePriorityIndex = 0;
        this._nodePriorityMap = {};
        this._visitTarget(rootNode, true);
        listeners.getSceneGraphPriorityListeners().sort(this._sortEventListenersOfSceneGraphPriorityDes);
    },
    _sortEventListenersOfSceneGraphPriorityDes : function(l1, l2){
        var locNodePriorityMap = cc.eventManager._nodePriorityMap, node1 = l1._getSceneGraphPriority(),
            node2 = l2._getSceneGraphPriority();
        if( !l2 || !node2 || !locNodePriorityMap[node2.__instanceId] )
            return -1;
        else if( !l1 || !node1 || !locNodePriorityMap[node1.__instanceId] )
            return 1;
        return locNodePriorityMap[l2._getSceneGraphPriority().__instanceId] - locNodePriorityMap[l1._getSceneGraphPriority().__instanceId];
    },
    _sortListenersOfFixedPriority: function (listenerID) {
        var listeners = this._listenersMap[listenerID];
        if (!listeners)
            return;
        var fixedListeners = listeners.getFixedPriorityListeners();
        if(!fixedListeners || fixedListeners.length === 0)
            return;
        fixedListeners.sort(this._sortListenersOfFixedPriorityAsc);
        var index = 0;
        for (var len = fixedListeners.length; index < len;) {
            if (fixedListeners[index]._getFixedPriority() >= 0)
                break;
            ++index;
        }
        listeners.gt0Index = index;
    },
    _sortListenersOfFixedPriorityAsc: function (l1, l2) {
        return l1._getFixedPriority() - l2._getFixedPriority();
    },
    _onUpdateListeners: function (listenerID) {
        var listeners = this._listenersMap[listenerID];
        if (!listeners)
            return;
        var fixedPriorityListeners = listeners.getFixedPriorityListeners();
        var sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
        var i, selListener, idx, toRemovedListeners = this._toRemovedListeners;
        if (sceneGraphPriorityListeners) {
            for (i = 0; i < sceneGraphPriorityListeners.length;) {
                selListener = sceneGraphPriorityListeners[i];
                if (!selListener._isRegistered()) {
                    cc.arrayRemoveObject(sceneGraphPriorityListeners, selListener);
                    idx = toRemovedListeners.indexOf(selListener);
                    if(idx !== -1)
                        toRemovedListeners.splice(idx, 1);
                } else
                    ++i;
            }
        }
        if (fixedPriorityListeners) {
            for (i = 0; i < fixedPriorityListeners.length;) {
                selListener = fixedPriorityListeners[i];
                if (!selListener._isRegistered()) {
                    cc.arrayRemoveObject(fixedPriorityListeners, selListener);
                    idx = toRemovedListeners.indexOf(selListener);
                    if(idx !== -1)
                        toRemovedListeners.splice(idx, 1);
                } else
                    ++i;
            }
        }
        if (sceneGraphPriorityListeners && sceneGraphPriorityListeners.length === 0)
            listeners.clearSceneGraphListeners();
        if (fixedPriorityListeners && fixedPriorityListeners.length === 0)
            listeners.clearFixedListeners();
    },
    _updateListeners: function (event) {
        var locInDispatch = this._inDispatch;
        cc.assert(locInDispatch > 0, cc._LogInfos.EventManager__updateListeners);
        if(locInDispatch > 1)
            return;
        if (event.getType() === cc.Event.TOUCH) {
            this._onUpdateListeners(cc._EventListenerTouchOneByOne.LISTENER_ID);
            this._onUpdateListeners(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
        } else
            this._onUpdateListeners(cc.__getListenerID(event));
        cc.assert(locInDispatch === 1, cc._LogInfos.EventManager__updateListeners_2);
        var locListenersMap = this._listenersMap, locPriorityDirtyFlagMap = this._priorityDirtyFlagMap;
        for (var selKey in locListenersMap) {
            if (locListenersMap[selKey].empty()) {
                delete locPriorityDirtyFlagMap[selKey];
                delete locListenersMap[selKey];
            }
        }
        var locToAddedListeners = this._toAddedListeners;
        if (locToAddedListeners.length !== 0) {
            for (var i = 0, len = locToAddedListeners.length; i < len; i++)
                this._forceAddEventListener(locToAddedListeners[i]);
            this._toAddedListeners.length = 0;
        }
        if(this._toRemovedListeners.length !== 0)
            this._cleanToRemovedListeners();
    },
    _cleanToRemovedListeners: function(){
        var toRemovedListeners = this._toRemovedListeners;
        for(var i = 0; i< toRemovedListeners.length; i++){
            var selListener = toRemovedListeners[i];
            var listeners = this._listenersMap[selListener._getListenerID()];
            if(!listeners)
                continue;
            var idx, fixedPriorityListeners = listeners.getFixedPriorityListeners(),
                sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
            if(sceneGraphPriorityListeners){
                idx = sceneGraphPriorityListeners.indexOf(selListener);
                if (idx !== -1) {
                    sceneGraphPriorityListeners.splice(idx, 1);
                }
            }
            if(fixedPriorityListeners){
                idx = fixedPriorityListeners.indexOf(selListener);
                if (idx !== -1) {
                    fixedPriorityListeners.splice(idx, 1);
                }
            }
        }
        toRemovedListeners.length = 0;
    },
    _onTouchEventCallback: function(listener, argsObj){
        if (!listener._isRegistered)
            return false;
        var event = argsObj.event, selTouch = argsObj.selTouch;
        event._setCurrentTarget(listener._node);
        var isClaimed = false, removedIdx;
        var getCode = event.getEventCode(), eventCode = cc.EventTouch.EventCode;
        if (getCode === eventCode.BEGAN) {
            if (listener.onTouchBegan) {
                isClaimed = listener.onTouchBegan(selTouch, event);
                if (isClaimed && listener._registered)
                    listener._claimedTouches.push(selTouch);
            }
        } else if (listener._claimedTouches.length > 0
            && ((removedIdx = listener._claimedTouches.indexOf(selTouch)) !== -1)) {
            isClaimed = true;
            if(getCode === eventCode.MOVED && listener.onTouchMoved){
                listener.onTouchMoved(selTouch, event);
            } else if(getCode === eventCode.ENDED){
                if (listener.onTouchEnded)
                    listener.onTouchEnded(selTouch, event);
                if (listener._registered)
                    listener._claimedTouches.splice(removedIdx, 1);
            } else if(getCode === eventCode.CANCELLED){
                if (listener.onTouchCancelled)
                    listener.onTouchCancelled(selTouch, event);
                if (listener._registered)
                    listener._claimedTouches.splice(removedIdx, 1);
            }
        }
        if (event.isStopped()) {
            cc.eventManager._updateListeners(event);
            return true;
        }
        if (isClaimed && listener._registered && listener.swallowTouches) {
            if (argsObj.needsMutableSet)
                argsObj.touches.splice(selTouch, 1);
            return true;
        }
        return false;
    },
    _dispatchTouchEvent: function (event) {
        this._sortEventListeners(cc._EventListenerTouchOneByOne.LISTENER_ID);
        this._sortEventListeners(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
        var oneByOneListeners = this._getListeners(cc._EventListenerTouchOneByOne.LISTENER_ID);
        var allAtOnceListeners = this._getListeners(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
        if (null === oneByOneListeners && null === allAtOnceListeners)
            return;
        var originalTouches = event.getTouches(), mutableTouches = cc.copyArray(originalTouches);
        var oneByOneArgsObj = {event: event, needsMutableSet: (oneByOneListeners && allAtOnceListeners), touches: mutableTouches, selTouch: null};
        if (oneByOneListeners) {
            for (var i = 0; i < originalTouches.length; i++) {
                oneByOneArgsObj.selTouch = originalTouches[i];
                this._dispatchEventToListeners(oneByOneListeners, this._onTouchEventCallback, oneByOneArgsObj);
                if (event.isStopped())
                    return;
            }
        }
        if (allAtOnceListeners && mutableTouches.length > 0) {
            this._dispatchEventToListeners(allAtOnceListeners, this._onTouchesEventCallback, {event: event, touches: mutableTouches});
            if (event.isStopped())
                return;
        }
        this._updateListeners(event);
    },
    _onTouchesEventCallback: function (listener, callbackParams) {
        if (!listener._registered)
            return false;
        var eventCode = cc.EventTouch.EventCode, event = callbackParams.event, touches = callbackParams.touches, getCode = event.getEventCode();
        event._setCurrentTarget(listener._node);
        if(getCode === eventCode.BEGAN && listener.onTouchesBegan)
            listener.onTouchesBegan(touches, event);
        else if(getCode === eventCode.MOVED && listener.onTouchesMoved)
            listener.onTouchesMoved(touches, event);
        else if(getCode === eventCode.ENDED && listener.onTouchesEnded)
            listener.onTouchesEnded(touches, event);
        else if(getCode === eventCode.CANCELLED && listener.onTouchesCancelled)
            listener.onTouchesCancelled(touches, event);
        if (event.isStopped()) {
            cc.eventManager._updateListeners(event);
            return true;
        }
        return false;
    },
    _associateNodeAndEventListener: function (node, listener) {
        var listeners = this._nodeListenersMap[node.__instanceId];
        if (!listeners) {
            listeners = [];
            this._nodeListenersMap[node.__instanceId] = listeners;
        }
        listeners.push(listener);
    },
    _dissociateNodeAndEventListener: function (node, listener) {
        var listeners = this._nodeListenersMap[node.__instanceId];
        if (listeners) {
            cc.arrayRemoveObject(listeners, listener);
            if (listeners.length === 0)
                delete this._nodeListenersMap[node.__instanceId];
        }
    },
    _dispatchEventToListeners: function (listeners, onEvent, eventOrArgs) {
        var shouldStopPropagation = false;
        var fixedPriorityListeners = listeners.getFixedPriorityListeners();
        var sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
        var i = 0, j, selListener;
        if (fixedPriorityListeners) {
            if (fixedPriorityListeners.length !== 0) {
                for (; i < listeners.gt0Index; ++i) {
                    selListener = fixedPriorityListeners[i];
                    if (selListener.isEnabled() && !selListener._isPaused() && selListener._isRegistered() && onEvent(selListener, eventOrArgs)) {
                        shouldStopPropagation = true;
                        break;
                    }
                }
            }
        }
        if (sceneGraphPriorityListeners && !shouldStopPropagation) {
            for (j = 0; j < sceneGraphPriorityListeners.length; j++) {
                selListener = sceneGraphPriorityListeners[j];
                if (selListener.isEnabled() && !selListener._isPaused() && selListener._isRegistered() && onEvent(selListener, eventOrArgs)) {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
        if (fixedPriorityListeners && !shouldStopPropagation) {
            for (; i < fixedPriorityListeners.length; ++i) {
                selListener = fixedPriorityListeners[i];
                if (selListener.isEnabled() && !selListener._isPaused() && selListener._isRegistered() && onEvent(selListener, eventOrArgs)) {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    },
    _setDirty: function (listenerID, flag) {
        var locDirtyFlagMap = this._priorityDirtyFlagMap;
        if (locDirtyFlagMap[listenerID] == null)
            locDirtyFlagMap[listenerID] = flag;
        else
            locDirtyFlagMap[listenerID] = flag | locDirtyFlagMap[listenerID];
    },
    _visitTarget: function (node, isRootNode) {
        var children = node.getChildren(), i = 0;
        var childrenCount = children.length, locGlobalZOrderNodeMap = this._globalZOrderNodeMap, locNodeListenersMap = this._nodeListenersMap;
        if (childrenCount > 0) {
            var child;
            for (; i < childrenCount; i++) {
                child = children[i];
                if (child && child.getLocalZOrder() < 0)
                    this._visitTarget(child, false);
                else
                    break;
            }
            if (locNodeListenersMap[node.__instanceId] != null) {
                if (!locGlobalZOrderNodeMap[node.getGlobalZOrder()])
                    locGlobalZOrderNodeMap[node.getGlobalZOrder()] = [];
                locGlobalZOrderNodeMap[node.getGlobalZOrder()].push(node.__instanceId);
            }
            for (; i < childrenCount; i++) {
                child = children[i];
                if (child)
                    this._visitTarget(child, false);
            }
        } else {
            if (locNodeListenersMap[node.__instanceId] != null) {
                if (!locGlobalZOrderNodeMap[node.getGlobalZOrder()])
                    locGlobalZOrderNodeMap[node.getGlobalZOrder()] = [];
                locGlobalZOrderNodeMap[node.getGlobalZOrder()].push(node.__instanceId);
            }
        }
        if (isRootNode) {
            var globalZOrders = [];
            for (var selKey in locGlobalZOrderNodeMap)
                globalZOrders.push(selKey);
            globalZOrders.sort(this._sortNumberAsc);
            var zOrdersLen = globalZOrders.length, selZOrders, j, locNodePriorityMap = this._nodePriorityMap;
            for (i = 0; i < zOrdersLen; i++) {
                selZOrders = locGlobalZOrderNodeMap[globalZOrders[i]];
                for (j = 0; j < selZOrders.length; j++)
                    locNodePriorityMap[selZOrders[j]] = ++this._nodePriorityIndex;
            }
            this._globalZOrderNodeMap = {};
        }
    },
    _sortNumberAsc : function (a, b) {
        return a - b;
    },
    addListener: function (listener, nodeOrPriority) {
        cc.assert(listener && nodeOrPriority, cc._LogInfos.eventManager_addListener_2);
        if(!(listener instanceof cc.EventListener)){
            cc.assert(!cc.isNumber(nodeOrPriority), cc._LogInfos.eventManager_addListener_3);
            listener = cc.EventListener.create(listener);
        } else {
            if(listener._isRegistered()){
                cc.log(cc._LogInfos.eventManager_addListener_4);
                return;
            }
        }
        if (!listener.checkAvailable())
            return;
        if (cc.isNumber(nodeOrPriority)) {
            if (nodeOrPriority === 0) {
                cc.log(cc._LogInfos.eventManager_addListener);
                return;
            }
            listener._setSceneGraphPriority(null);
            listener._setFixedPriority(nodeOrPriority);
            listener._setRegistered(true);
            listener._setPaused(false);
            this._addListener(listener);
        } else {
            listener._setSceneGraphPriority(nodeOrPriority);
            listener._setFixedPriority(0);
            listener._setRegistered(true);
            this._addListener(listener);
        }
        return listener;
    },
    addCustomListener: function (eventName, callback) {
        var listener = new cc._EventListenerCustom(eventName, callback);
        this.addListener(listener, 1);
        return listener;
    },
    removeListener: function (listener) {
        if (listener == null)
            return;
        var isFound, locListener = this._listenersMap;
        for (var selKey in locListener) {
            var listeners = locListener[selKey];
            var fixedPriorityListeners = listeners.getFixedPriorityListeners(), sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
            isFound = this._removeListenerInVector(sceneGraphPriorityListeners, listener);
            if (isFound){
               this._setDirty(listener._getListenerID(), this.DIRTY_SCENE_GRAPH_PRIORITY);
            }else{
                isFound = this._removeListenerInVector(fixedPriorityListeners, listener);
                if (isFound)
                    this._setDirty(listener._getListenerID(), this.DIRTY_FIXED_PRIORITY);
            }
            if (listeners.empty()) {
                delete this._priorityDirtyFlagMap[listener._getListenerID()];
                delete locListener[selKey];
            }
            if (isFound)
                break;
        }
        if (!isFound) {
            var locToAddedListeners = this._toAddedListeners;
            for (var i = 0, len = locToAddedListeners.length; i < len; i++) {
                var selListener = locToAddedListeners[i];
                if (selListener === listener) {
                    cc.arrayRemoveObject(locToAddedListeners, selListener);
                    selListener._setRegistered(false);
                    break;
                }
            }
        }
    },
    _removeListenerInCallback: function(listeners, callback){
        if (listeners == null)
            return false;
        for (var i = 0, len = listeners.length; i < len; i++) {
            var selListener = listeners[i];
            if (selListener._onCustomEvent === callback || selListener._onEvent === callback) {
                selListener._setRegistered(false);
                if (selListener._getSceneGraphPriority() != null){
                    this._dissociateNodeAndEventListener(selListener._getSceneGraphPriority(), selListener);
                    selListener._setSceneGraphPriority(null);
                }
                if (this._inDispatch === 0)
                    cc.arrayRemoveObject(listeners, selListener);
                return true;
            }
        }
        return false;
    },
    _removeListenerInVector : function(listeners, listener){
        if (listeners == null)
            return false;
        for (var i = 0, len = listeners.length; i < len; i++) {
            var selListener = listeners[i];
            if (selListener === listener) {
                selListener._setRegistered(false);
                if (selListener._getSceneGraphPriority() != null){
                    this._dissociateNodeAndEventListener(selListener._getSceneGraphPriority(), selListener);
                    selListener._setSceneGraphPriority(null);
                }
                if (this._inDispatch === 0)
                    cc.arrayRemoveObject(listeners, selListener);
                else
                    this._toRemovedListeners.push(selListener);
                return true;
            }
        }
        return false;
    },
    removeListeners: function (listenerType, recursive) {
        var _t = this;
        if (listenerType instanceof cc.Node) {
            delete _t._nodePriorityMap[listenerType.__instanceId];
            cc.arrayRemoveObject(_t._dirtyNodes, listenerType);
            var listeners = _t._nodeListenersMap[listenerType.__instanceId], i;
            if (listeners) {
                var listenersCopy = cc.copyArray(listeners);
                for (i = 0; i < listenersCopy.length; i++)
                    _t.removeListener(listenersCopy[i]);
                listenersCopy.length = 0;
            }
            var locToAddedListeners = _t._toAddedListeners;
            for (i = 0; i < locToAddedListeners.length; ) {
                var listener = locToAddedListeners[i];
                if (listener._getSceneGraphPriority() === listenerType) {
                    listener._setSceneGraphPriority(null);
                    listener._setRegistered(false);
                    locToAddedListeners.splice(i, 1);
                } else
                    ++i;
            }
            if (recursive === true) {
                var locChildren = listenerType.getChildren(), len;
                for (i = 0, len = locChildren.length; i< len; i++)
                    _t.removeListeners(locChildren[i], true);
            }
        } else {
            if (listenerType === cc.EventListener.TOUCH_ONE_BY_ONE)
                _t._removeListenersForListenerID(cc._EventListenerTouchOneByOne.LISTENER_ID);
            else if (listenerType === cc.EventListener.TOUCH_ALL_AT_ONCE)
                _t._removeListenersForListenerID(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
            else if (listenerType === cc.EventListener.MOUSE)
                _t._removeListenersForListenerID(cc._EventListenerMouse.LISTENER_ID);
            else if (listenerType === cc.EventListener.ACCELERATION)
                _t._removeListenersForListenerID(cc._EventListenerAcceleration.LISTENER_ID);
            else if (listenerType === cc.EventListener.KEYBOARD)
                _t._removeListenersForListenerID(cc._EventListenerKeyboard.LISTENER_ID);
            else
                cc.log(cc._LogInfos.eventManager_removeListeners);
        }
    },
    removeCustomListeners: function (customEventName) {
        this._removeListenersForListenerID(customEventName);
    },
    removeAllListeners: function () {
        var locListeners = this._listenersMap, locInternalCustomEventIDs = this._internalCustomListenerIDs;
        for (var selKey in locListeners){
            if(locInternalCustomEventIDs.indexOf(selKey) === -1)
                this._removeListenersForListenerID(selKey);
        }
    },
    setPriority: function (listener, fixedPriority) {
        if (listener == null)
            return;
        var locListeners = this._listenersMap;
        for (var selKey in locListeners) {
            var selListeners = locListeners[selKey];
            var fixedPriorityListeners = selListeners.getFixedPriorityListeners();
            if (fixedPriorityListeners) {
                var found = fixedPriorityListeners.indexOf(listener);
                if (found !== -1) {
                    if(listener._getSceneGraphPriority() != null)
                        cc.log(cc._LogInfos.eventManager_setPriority);
                    if (listener._getFixedPriority() !== fixedPriority) {
                        listener._setFixedPriority(fixedPriority);
                        this._setDirty(listener._getListenerID(), this.DIRTY_FIXED_PRIORITY);
                    }
                    return;
                }
            }
        }
    },
    setEnabled: function (enabled) {
        this._isEnabled = enabled;
    },
    isEnabled: function () {
        return this._isEnabled;
    },
    dispatchEvent: function (event) {
        if (!this._isEnabled)
            return;
        this._updateDirtyFlagForSceneGraph();
        this._inDispatch++;
        if(!event || !event.getType)
            throw new Error("event is undefined");
        if (event.getType() === cc.Event.TOUCH) {
            this._dispatchTouchEvent(event);
            this._inDispatch--;
            return;
        }
        var listenerID = cc.__getListenerID(event);
        this._sortEventListeners(listenerID);
        var selListeners = this._listenersMap[listenerID];
        if (selListeners != null)
            this._dispatchEventToListeners(selListeners, this._onListenerCallback, event);
        this._updateListeners(event);
        this._inDispatch--;
    },
    _onListenerCallback: function(listener, event){
        event._setCurrentTarget(listener._getSceneGraphPriority());
        listener._onEvent(event);
        return event.isStopped();
    },
    dispatchCustomEvent: function (eventName, optionalUserData) {
        var ev = new cc.EventCustom(eventName);
        ev.setUserData(optionalUserData);
        this.dispatchEvent(ev);
    }
};
cc._tmp.PrototypeCCNode = function () {
    var _p = cc.Node.prototype;
    cc.defineGetterSetter(_p, "x", _p.getPositionX, _p.setPositionX);
    cc.defineGetterSetter(_p, "y", _p.getPositionY, _p.setPositionY);
    _p.width;
    cc.defineGetterSetter(_p, "width", _p._getWidth, _p._setWidth);
    _p.height;
    cc.defineGetterSetter(_p, "height", _p._getHeight, _p._setHeight);
    _p.anchorX;
    cc.defineGetterSetter(_p, "anchorX", _p._getAnchorX, _p._setAnchorX);
    _p.anchorY;
    cc.defineGetterSetter(_p, "anchorY", _p._getAnchorY, _p._setAnchorY);
    _p.skewX;
    cc.defineGetterSetter(_p, "skewX", _p.getSkewX, _p.setSkewX);
    _p.skewY;
    cc.defineGetterSetter(_p, "skewY", _p.getSkewY, _p.setSkewY);
    _p.zIndex;
    cc.defineGetterSetter(_p, "zIndex", _p.getLocalZOrder, _p.setLocalZOrder);
    _p.vertexZ;
    cc.defineGetterSetter(_p, "vertexZ", _p.getVertexZ, _p.setVertexZ);
    _p.rotation;
    cc.defineGetterSetter(_p, "rotation", _p.getRotation, _p.setRotation);
    _p.rotationX;
    cc.defineGetterSetter(_p, "rotationX", _p.getRotationX, _p.setRotationX);
    _p.rotationY;
    cc.defineGetterSetter(_p, "rotationY", _p.getRotationY, _p.setRotationY);
    _p.scale;
    cc.defineGetterSetter(_p, "scale", _p.getScale, _p.setScale);
    _p.scaleX;
    cc.defineGetterSetter(_p, "scaleX", _p.getScaleX, _p.setScaleX);
    _p.scaleY;
    cc.defineGetterSetter(_p, "scaleY", _p.getScaleY, _p.setScaleY);
    _p.children;
    cc.defineGetterSetter(_p, "children", _p.getChildren);
    _p.childrenCount;
    cc.defineGetterSetter(_p, "childrenCount", _p.getChildrenCount);
    _p.parent;
    cc.defineGetterSetter(_p, "parent", _p.getParent, _p.setParent);
    _p.visible;
    cc.defineGetterSetter(_p, "visible", _p.isVisible, _p.setVisible);
    _p.running;
    cc.defineGetterSetter(_p, "running", _p.isRunning);
    _p.ignoreAnchor;
    cc.defineGetterSetter(_p, "ignoreAnchor", _p.isIgnoreAnchorPointForPosition, _p.ignoreAnchorPointForPosition);
    _p.tag;
    _p.userData;
    _p.userObject;
    _p.arrivalOrder;
    _p.actionManager;
    cc.defineGetterSetter(_p, "actionManager", _p.getActionManager, _p.setActionManager);
    _p.scheduler;
    cc.defineGetterSetter(_p, "scheduler", _p.getScheduler, _p.setScheduler);
    _p.shaderProgram;
    cc.defineGetterSetter(_p, "shaderProgram", _p.getShaderProgram, _p.setShaderProgram);
    _p.opacity;
    cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
    _p.opacityModifyRGB;
    cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB);
    _p.cascadeOpacity;
    cc.defineGetterSetter(_p, "cascadeOpacity", _p.isCascadeOpacityEnabled, _p.setCascadeOpacityEnabled);
    _p.color;
    cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
    _p.cascadeColor;
    cc.defineGetterSetter(_p, "cascadeColor", _p.isCascadeColorEnabled, _p.setCascadeColorEnabled);
};
cc.NODE_TAG_INVALID = -1;
cc.s_globalOrderOfArrival = 1;
cc.Node = cc.Class.extend({
    _localZOrder: 0,
    _globalZOrder: 0,
    _vertexZ: 0.0,
    _customZ: NaN,
    _rotationX: 0,
    _rotationY: 0.0,
    _scaleX: 1.0,
    _scaleY: 1.0,
    _position: null,
    _normalizedPosition:null,
    _usingNormalizedPosition: false,
    _normalizedPositionDirty: false,
    _skewX: 0.0,
    _skewY: 0.0,
    _children: null,
    _visible: true,
    _anchorPoint: null,
    _contentSize: null,
    _running: false,
    _parent: null,
    _ignoreAnchorPointForPosition: false,
    tag: cc.NODE_TAG_INVALID,
    userData: null,
    userObject: null,
    _reorderChildDirty: false,
    _shaderProgram: null,
    arrivalOrder: 0,
    _actionManager: null,
    _scheduler: null,
    _eventDispatcher: null,
    _additionalTransformDirty: false,
    _additionalTransform: null,
    _componentContainer: null,
    _isTransitionFinished: false,
    _className: "Node",
    _showNode: false,
    _name: "",
    _realOpacity: 255,
    _realColor: null,
    _cascadeColorEnabled: false,
    _cascadeOpacityEnabled: false,
    _renderCmd:null,
    ctor: function(){
        this._initNode();
        this._initRendererCmd();
    },
    _initNode: function () {
        var _t = this;
        _t._anchorPoint = cc.p(0, 0);
        _t._contentSize = cc.size(0, 0);
        _t._position = cc.p(0, 0);
        _t._normalizedPosition = cc.p(0,0);
        _t._children = [];
        var director = cc.director;
        _t._actionManager = director.getActionManager();
        _t._scheduler = director.getScheduler();
        _t._additionalTransform = cc.affineTransformMakeIdentity();
        if (cc.ComponentContainer) {
            _t._componentContainer = new cc.ComponentContainer(_t);
        }
        this._realOpacity = 255;
        this._realColor = cc.color(255, 255, 255, 255);
        this._cascadeColorEnabled = false;
        this._cascadeOpacityEnabled = false;
    },
    init: function () {
        return true;
    },
    _arrayMakeObjectsPerformSelector: function (array, callbackType) {
        if (!array || array.length === 0)
            return;
        var i, len = array.length, node;
        var nodeCallbackType = cc.Node._stateCallbackType;
        switch (callbackType) {
            case nodeCallbackType.onEnter:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.onEnter();
                }
                break;
            case nodeCallbackType.onExit:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.onExit();
                }
                break;
            case nodeCallbackType.onEnterTransitionDidFinish:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.onEnterTransitionDidFinish();
                }
                break;
            case nodeCallbackType.cleanup:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.cleanup();
                }
                break;
            case nodeCallbackType.updateTransform:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.updateTransform();
                }
                break;
            case nodeCallbackType.onExitTransitionDidStart:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.onExitTransitionDidStart();
                }
                break;
            case nodeCallbackType.sortAllChildren:
                for (i = 0; i < len; i++) {
                    node = array[i];
                    if (node)
                        node.sortAllChildren();
                }
                break;
            default :
                cc.assert(0, cc._LogInfos.Node__arrayMakeObjectsPerformSelector);
                break;
        }
    },
    attr: function (attrs) {
        for (var key in attrs) {
            this[key] = attrs[key];
        }
    },
    getSkewX: function () {
        return this._skewX;
    },
    setSkewX: function (newSkewX) {
        this._skewX = newSkewX;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getSkewY: function () {
        return this._skewY;
    },
    setSkewY: function (newSkewY) {
        this._skewY = newSkewY;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    setLocalZOrder: function (localZOrder) {
        this._localZOrder = localZOrder;
        if (this._parent)
            this._parent.reorderChild(this, localZOrder);
        cc.eventManager._setDirtyForNode(this);
    },
    _setLocalZOrder: function (localZOrder) {
        this._localZOrder = localZOrder;
    },
    getLocalZOrder: function () {
        return this._localZOrder;
    },
    getZOrder: function () {
        cc.log(cc._LogInfos.Node_getZOrder);
        return this.getLocalZOrder();
    },
    setZOrder: function (z) {
        cc.log(cc._LogInfos.Node_setZOrder);
        this.setLocalZOrder(z);
    },
    setGlobalZOrder: function (globalZOrder) {
        if (this._globalZOrder !== globalZOrder) {
            this._globalZOrder = globalZOrder;
            cc.eventManager._setDirtyForNode(this);
        }
    },
    getGlobalZOrder: function () {
        return this._globalZOrder;
    },
    getVertexZ: function () {
        return this._vertexZ;
    },
    setVertexZ: function (Var) {
        this._customZ = this._vertexZ = Var;
    },
    getRotation: function () {
        if (this._rotationX !== this._rotationY)
            cc.log(cc._LogInfos.Node_getRotation);
        return this._rotationX;
    },
    setRotation: function (newRotation) {
        this._rotationX = this._rotationY = newRotation;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getRotationX: function () {
        return this._rotationX;
    },
    setRotationX: function (rotationX) {
        this._rotationX = rotationX;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getRotationY: function () {
        return this._rotationY;
    },
    setRotationY: function (rotationY) {
        this._rotationY = rotationY;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getScale: function () {
        if (this._scaleX !== this._scaleY)
            cc.log(cc._LogInfos.Node_getScale);
        return this._scaleX;
    },
    setScale: function (scale, scaleY) {
        this._scaleX = scale;
        this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getScaleX: function () {
        return this._scaleX;
    },
    setScaleX: function (newScaleX) {
        this._scaleX = newScaleX;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getScaleY: function () {
        return this._scaleY;
    },
    setScaleY: function (newScaleY) {
        this._scaleY = newScaleY;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    setPosition: function (newPosOrxValue, yValue) {
        var locPosition = this._position;
        if (yValue === undefined) {
            if(locPosition.x === newPosOrxValue.x && locPosition.y === newPosOrxValue.y)
                return;
            locPosition.x = newPosOrxValue.x;
            locPosition.y = newPosOrxValue.y;
        } else {
            if(locPosition.x === newPosOrxValue && locPosition.y === yValue)
                return;
            locPosition.x = newPosOrxValue;
            locPosition.y = yValue;
        }
        this._usingNormalizedPosition = false;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    setNormalizedPosition: function(posOrX, y){
        var locPosition = this._normalizedPosition;
        if (y === undefined) {
            locPosition.x = posOrX.x;
            locPosition.y = posOrX.y;
        } else {
            locPosition.x = posOrX;
            locPosition.y = y;
        }
        this._normalizedPositionDirty = this._usingNormalizedPosition = true;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getPosition: function () {
        return cc.p(this._position);
    },
    getNormalizedPosition: function(){
        return cc.p(this._normalizedPosition);
    },
    getPositionX: function () {
        return this._position.x;
    },
    setPositionX: function (x) {
        this._position.x = x;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getPositionY: function () {
        return  this._position.y;
    },
    setPositionY: function (y) {
        this._position.y = y;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getChildrenCount: function () {
        return this._children.length;
    },
    getChildren: function () {
        return this._children;
    },
    isVisible: function () {
        return this._visible;
    },
    setVisible: function (visible) {
        if(this._visible !== visible){
            this._visible = visible;
            this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
            cc.renderer.childrenOrderDirty = true;
        }
    },
    getAnchorPoint: function () {
        return cc.p(this._anchorPoint);
    },
    setAnchorPoint: function (point, y) {
        var locAnchorPoint = this._anchorPoint;
        if (y === undefined) {
            if ((point.x === locAnchorPoint.x) && (point.y === locAnchorPoint.y))
                return;
            locAnchorPoint.x = point.x;
            locAnchorPoint.y = point.y;
        } else {
            if ((point === locAnchorPoint.x) && (y === locAnchorPoint.y))
                return;
            locAnchorPoint.x = point;
            locAnchorPoint.y = y;
        }
        this._renderCmd._updateAnchorPointInPoint();
    },
    _getAnchorX: function () {
        return this._anchorPoint.x;
    },
    _setAnchorX: function (x) {
        if (this._anchorPoint.x === x) return;
        this._anchorPoint.x = x;
        this._renderCmd._updateAnchorPointInPoint();
    },
    _getAnchorY: function () {
        return this._anchorPoint.y;
    },
    _setAnchorY: function (y) {
        if (this._anchorPoint.y === y) return;
        this._anchorPoint.y = y;
        this._renderCmd._updateAnchorPointInPoint();
    },
    getAnchorPointInPoints: function () {
        return this._renderCmd.getAnchorPointInPoints();
    },
    _getWidth: function () {
        return this._contentSize.width;
    },
    _setWidth: function (width) {
        this._contentSize.width = width;
        this._renderCmd._updateAnchorPointInPoint();
    },
    _getHeight: function () {
        return this._contentSize.height;
    },
    _setHeight: function (height) {
        this._contentSize.height = height;
        this._renderCmd._updateAnchorPointInPoint();
    },
    getContentSize: function () {
        return cc.size(this._contentSize);
    },
    setContentSize: function (size, height) {
        var locContentSize = this._contentSize;
        if (height === undefined) {
            if ((size.width === locContentSize.width) && (size.height === locContentSize.height))
                return;
            locContentSize.width = size.width;
            locContentSize.height = size.height;
        } else {
            if ((size === locContentSize.width) && (height === locContentSize.height))
                return;
            locContentSize.width = size;
            locContentSize.height = height;
        }
        this._renderCmd._updateAnchorPointInPoint();
    },
    isRunning: function () {
        return this._running;
    },
    getParent: function () {
        return this._parent;
    },
    setParent: function (parent) {
        this._parent = parent;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    isIgnoreAnchorPointForPosition: function () {
        return this._ignoreAnchorPointForPosition;
    },
    ignoreAnchorPointForPosition: function (newValue) {
        if (newValue !== this._ignoreAnchorPointForPosition) {
            this._ignoreAnchorPointForPosition = newValue;
            this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        }
    },
    getTag: function () {
        return this.tag;
    },
    setTag: function (tag) {
        this.tag = tag;
    },
    setName: function(name){
         this._name = name;
    },
    getName: function(){
        return this._name;
    },
    getUserData: function () {
        return this.userData;
    },
    setUserData: function (Var) {
        this.userData = Var;
    },
    getUserObject: function () {
        return this.userObject;
    },
    setUserObject: function (newValue) {
        if (this.userObject !== newValue)
            this.userObject = newValue;
    },
    getOrderOfArrival: function () {
        return this.arrivalOrder;
    },
    setOrderOfArrival: function (Var) {
        this.arrivalOrder = Var;
    },
    getActionManager: function () {
        if (!this._actionManager)
            this._actionManager = cc.director.getActionManager();
        return this._actionManager;
    },
    setActionManager: function (actionManager) {
        if (this._actionManager !== actionManager) {
            this.stopAllActions();
            this._actionManager = actionManager;
        }
    },
    getScheduler: function () {
        if (!this._scheduler)
            this._scheduler = cc.director.getScheduler();
        return this._scheduler;
    },
    setScheduler: function (scheduler) {
        if (this._scheduler !== scheduler) {
            this.unscheduleAllCallbacks();
            this._scheduler = scheduler;
        }
    },
    boundingBox: function(){
        cc.log(cc._LogInfos.Node_boundingBox);
        return this.getBoundingBox();
    },
    getBoundingBox: function () {
        var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
        return cc._rectApplyAffineTransformIn(rect, this.getNodeToParentTransform());
    },
    cleanup: function () {
        this.stopAllActions();
        this.unscheduleAllCallbacks();
        cc.eventManager.removeListeners(this);
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.cleanup);
    },
    getChildByTag: function (aTag) {
        var __children = this._children;
        if (__children !== null) {
            for (var i = 0; i < __children.length; i++) {
                var node = __children[i];
                if (node && node.tag === aTag)
                    return node;
            }
        }
        return null;
    },
    getChildByName: function(name){
        if(!name){
            cc.log("Invalid name");
            return null;
        }
        var locChildren = this._children;
        for(var i = 0, len = locChildren.length; i < len; i++){
           if(locChildren[i]._name === name)
            return locChildren[i];
        }
        return null;
    },
    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");
        this._addChildHelper(child, localZOrder, tag, name, setTag);
    },
    _addChildHelper: function(child, localZOrder, tag, name, setTag){
        if(!this._children)
            this._children = [];
        this._insertChild(child, localZOrder);
        if(setTag)
            child.setTag(tag);
        else
            child.setName(name);
        child.setParent(this);
        child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
        if( this._running ){
            child.onEnter();
            if (this._isTransitionFinished)
                child.onEnterTransitionDidFinish();
        }
        child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        if (this._cascadeColorEnabled)
            child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
        if (this._cascadeOpacityEnabled)
            child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    },
    removeFromParent: function (cleanup) {
        if (this._parent) {
            if (cleanup === undefined)
                cleanup = true;
            this._parent.removeChild(this, cleanup);
        }
    },
    removeFromParentAndCleanup: function (cleanup) {
        cc.log(cc._LogInfos.Node_removeFromParentAndCleanup);
        this.removeFromParent(cleanup);
    },
    removeChild: function (child, cleanup) {
        if (this._children.length === 0)
            return;
        if (cleanup === undefined)
            cleanup = true;
        if (this._children.indexOf(child) > -1)
            this._detachChild(child, cleanup);
        cc.renderer.childrenOrderDirty = true;
    },
    removeChildByTag: function (tag, cleanup) {
        if (tag === cc.NODE_TAG_INVALID)
            cc.log(cc._LogInfos.Node_removeChildByTag);
        var child = this.getChildByTag(tag);
        if (!child)
            cc.log(cc._LogInfos.Node_removeChildByTag_2, tag);
        else
            this.removeChild(child, cleanup);
    },
    removeAllChildrenWithCleanup: function (cleanup) {
        this.removeAllChildren(cleanup);
    },
    removeAllChildren: function (cleanup) {
        var __children = this._children;
        if (__children !== null) {
            if (cleanup === undefined)
                cleanup = true;
            for (var i = 0; i < __children.length; i++) {
                var node = __children[i];
                if (node) {
                    if (this._running) {
                        node.onExitTransitionDidStart();
                        node.onExit();
                    }
                    if (cleanup)
                        node.cleanup();
                    node.parent = null;
                    node._renderCmd.detachFromParent();
                }
            }
            this._children.length = 0;
            cc.renderer.childrenOrderDirty = true;
        }
    },
    _detachChild: function (child, doCleanup) {
        if (this._running) {
            child.onExitTransitionDidStart();
            child.onExit();
        }
        if (doCleanup)
            child.cleanup();
        child.parent = null;
        child._renderCmd.detachFromParent();
        cc.arrayRemoveObject(this._children, child);
    },
    _insertChild: function (child, z) {
        cc.renderer.childrenOrderDirty = this._reorderChildDirty = true;
        this._children.push(child);
        child._setLocalZOrder(z);
    },
    setNodeDirty: function(){
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    reorderChild: function (child, zOrder) {
        cc.assert(child, cc._LogInfos.Node_reorderChild);
        cc.renderer.childrenOrderDirty = this._reorderChildDirty = true;
        child.arrivalOrder = cc.s_globalOrderOfArrival;
        cc.s_globalOrderOfArrival++;
        child._setLocalZOrder(zOrder);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.orderDirty);
    },
    sortAllChildren: function () {
        if (this._reorderChildDirty) {
            var _children = this._children;
            var len = _children.length, i, j, tmp;
            for(i=1; i<len; i++){
                tmp = _children[i];
                j = i - 1;
                while(j >= 0){
                    if(tmp._localZOrder < _children[j]._localZOrder){
                        _children[j+1] = _children[j];
                    }else if(tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder){
                        _children[j+1] = _children[j];
                    }else{
                        break;
                    }
                    j--;
                }
                _children[j+1] = tmp;
            }
            this._reorderChildDirty = false;
        }
    },
    draw: function (ctx) {
    },
    transformAncestors: function () {
        if (this._parent !== null) {
            this._parent.transformAncestors();
            this._parent.transform();
        }
    },
    onEnter: function () {
        this._isTransitionFinished = false;
        this._running = true;//should be running before resumeSchedule
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onEnter);
        this.resume();
    },
    onEnterTransitionDidFinish: function () {
        this._isTransitionFinished = true;
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onEnterTransitionDidFinish);
    },
    onExitTransitionDidStart: function () {
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onExitTransitionDidStart);
    },
    onExit: function () {
        this._running = false;
        this.pause();
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.onExit);
        this.removeAllComponents();
    },
    runAction: function (action) {
        cc.assert(action, cc._LogInfos.Node_runAction);
        this.actionManager.addAction(action, this, !this._running);
        return action;
    },
    stopAllActions: function () {
        this.actionManager && this.actionManager.removeAllActionsFromTarget(this);
    },
    stopAction: function (action) {
        this.actionManager.removeAction(action);
    },
    stopActionByTag: function (tag) {
        if (tag === cc.ACTION_TAG_INVALID) {
            cc.log(cc._LogInfos.Node_stopActionByTag);
            return;
        }
        this.actionManager.removeActionByTag(tag, this);
    },
    getActionByTag: function (tag) {
        if (tag === cc.ACTION_TAG_INVALID) {
            cc.log(cc._LogInfos.Node_getActionByTag);
            return null;
        }
        return this.actionManager.getActionByTag(tag, this);
    },
    getNumberOfRunningActions: function () {
        return this.actionManager.numberOfRunningActionsInTarget(this);
    },
    scheduleUpdate: function () {
        this.scheduleUpdateWithPriority(0);
    },
    scheduleUpdateWithPriority: function (priority) {
        this.scheduler.scheduleUpdate(this, priority, !this._running);
    },
    unscheduleUpdate: function () {
        this.scheduler.unscheduleUpdate(this);
    },
    schedule: function (callback, interval, repeat, delay, key) {
        var len = arguments.length;
        if(typeof callback === "function"){
            if(len === 1){
                interval = 0;
                repeat = cc.REPEAT_FOREVER;
                delay = 0;
                key = this.__instanceId;
            }else if(len === 2){
                if(typeof interval === "number"){
                    repeat = cc.REPEAT_FOREVER;
                    delay = 0;
                    key = this.__instanceId;
                }else{
                    key = interval;
                    interval = 0;
                    repeat = cc.REPEAT_FOREVER;
                    delay = 0;
                }
            }else if(len === 3){
                if(typeof repeat === "string"){
                    key = repeat;
                    repeat = cc.REPEAT_FOREVER;
                }else{
                    key = this.__instanceId;
                }
                delay = 0;
            }else if(len === 4){
                key = this.__instanceId;
            }
        }else{
            if(len === 1){
                interval = 0;
                repeat = cc.REPEAT_FOREVER;
                delay = 0;
            }else if(len === 2){
                repeat = cc.REPEAT_FOREVER;
                delay = 0;
            }
        }
        cc.assert(callback, cc._LogInfos.Node_schedule);
        cc.assert(interval >= 0, cc._LogInfos.Node_schedule_2);
        interval = interval || 0;
        repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
        delay = delay || 0;
        this.scheduler.schedule(callback, this, interval, repeat, delay, !this._running, key);
    },
    scheduleOnce: function (callback, delay, key) {
        if(key === undefined)
            key = this.__instanceId;
        this.schedule(callback, 0, 0, delay, key);
    },
    unschedule: function (callback_fn) {
        if (!callback_fn)
            return;
        this.scheduler.unschedule(callback_fn, this);
    },
    unscheduleAllCallbacks: function () {
        this.scheduler.unscheduleAllForTarget(this);
    },
    resumeSchedulerAndActions: function () {
        cc.log(cc._LogInfos.Node_resumeSchedulerAndActions);
        this.resume();
    },
    resume: function () {
        this.scheduler.resumeTarget(this);
        this.actionManager && this.actionManager.resumeTarget(this);
        cc.eventManager.resumeTarget(this);
    },
    pauseSchedulerAndActions: function () {
        cc.log(cc._LogInfos.Node_pauseSchedulerAndActions);
        this.pause();
    },
    pause: function () {
        this.scheduler.pauseTarget(this);
        this.actionManager && this.actionManager.pauseTarget(this);
        cc.eventManager.pauseTarget(this);
    },
    setAdditionalTransform: function (additionalTransform) {
        if(additionalTransform === undefined)
            return this._additionalTransformDirty = false;
        this._additionalTransform = additionalTransform;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._additionalTransformDirty = true;
    },
    getParentToNodeTransform: function () {
       return this._renderCmd.getParentToNodeTransform();
    },
    parentToNodeTransform: function () {
        return this.getParentToNodeTransform();
    },
    getNodeToWorldTransform: function () {
        var t = this.getNodeToParentTransform();
        for (var p = this._parent; p !== null; p = p.parent)
            t = cc.affineTransformConcat(t, p.getNodeToParentTransform());
        return t;
    },
    nodeToWorldTransform: function(){
        return this.getNodeToWorldTransform();
    },
    getWorldToNodeTransform: function () {
        return cc.affineTransformInvert(this.getNodeToWorldTransform());
    },
    worldToNodeTransform: function () {
        return this.getWorldToNodeTransform();
    },
    convertToNodeSpace: function (worldPoint) {
        return cc.pointApplyAffineTransform(worldPoint, this.getWorldToNodeTransform());
    },
    convertToWorldSpace: function (nodePoint) {
        nodePoint = nodePoint || cc.p(0,0);
        return cc.pointApplyAffineTransform(nodePoint, this.getNodeToWorldTransform());
    },
    convertToNodeSpaceAR: function (worldPoint) {
        return cc.pSub(this.convertToNodeSpace(worldPoint), this._renderCmd.getAnchorPointInPoints());
    },
    convertToWorldSpaceAR: function (nodePoint) {
        nodePoint = nodePoint || cc.p(0,0);
        var pt = cc.pAdd(nodePoint, this._renderCmd.getAnchorPointInPoints());
        return this.convertToWorldSpace(pt);
    },
    _convertToWindowSpace: function (nodePoint) {
        var worldPoint = this.convertToWorldSpace(nodePoint);
        return cc.director.convertToUI(worldPoint);
    },
    convertTouchToNodeSpace: function (touch) {
        var point = touch.getLocation();
        return this.convertToNodeSpace(point);
    },
    convertTouchToNodeSpaceAR: function (touch) {
        var point = cc.director.convertToGL(touch.getLocation());
        return this.convertToNodeSpaceAR(point);
    },
    update: function (dt) {
        if (this._componentContainer && !this._componentContainer.isEmpty())
            this._componentContainer.visit(dt);
    },
    updateTransform: function () {
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.updateTransform);
    },
    retain: function () {
    },
    release: function () {
    },
    getComponent: function (name) {
        if(this._componentContainer)
            return this._componentContainer.getComponent(name);
        return null;
    },
    addComponent: function (component) {
        if(this._componentContainer)
            this._componentContainer.add(component);
    },
    removeComponent: function (component) {
        if(this._componentContainer)
            return this._componentContainer.remove(component);
        return false;
    },
    removeAllComponents: function () {
        if(this._componentContainer)
            this._componentContainer.removeAll();
    },
    grid: null,
    visit: function(parentCmd){
        this._renderCmd.visit(parentCmd);
    },
    transform: function(parentCmd, recursive){
        this._renderCmd.transform(parentCmd, recursive);
    },
    nodeToParentTransform: function(){
        return this.getNodeToParentTransform();
    },
    getNodeToParentTransform: function(ancestor){
        var t = this._renderCmd.getNodeToParentTransform();
        if(ancestor){
            var T = {a: t.a, b: t.b, c: t.c, d: t.d, tx: t.tx, ty: t.ty};
            for(var p = this._parent;  p != null && p != ancestor ; p = p.getParent()){
                cc.affineTransformConcatIn(T, p.getNodeToParentTransform());
            }
            return T;
        }else{
            return t;
        }
    },
    getNodeToParentAffineTransform: function(ancestor){
        return this.getNodeToParentTransform(ancestor);
    },
    getCamera: function () {
        return null;
    },
    getGrid: function () {
        return this.grid;
    },
    setGrid: function (grid) {
        this.grid = grid;
    },
    getShaderProgram: function () {
        return this._renderCmd.getShaderProgram();
    },
    setShaderProgram: function (newShaderProgram) {
        this._renderCmd.setShaderProgram(newShaderProgram);
    },
    getGLServerState: function () {
        return 0;
    },
    setGLServerState: function (state) {
    },
    getBoundingBoxToWorld: function () {
        var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
        var trans = this.getNodeToWorldTransform();
        rect = cc.rectApplyAffineTransform(rect, trans);
        if (!this._children)
            return rect;
        var locChildren = this._children;
        for (var i = 0; i < locChildren.length; i++) {
            var child = locChildren[i];
            if (child && child._visible) {
                var childRect = child._getBoundingBoxToCurrentNode(trans);
                if (childRect)
                    rect = cc.rectUnion(rect, childRect);
            }
        }
        return rect;
    },
    _getBoundingBoxToCurrentNode: function (parentTransform) {
        var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
        var trans = (parentTransform === undefined) ? this.getNodeToParentTransform() : cc.affineTransformConcat(this.getNodeToParentTransform(), parentTransform);
        rect = cc.rectApplyAffineTransform(rect, trans);
        if (!this._children)
            return rect;
        var locChildren = this._children;
        for (var i = 0; i < locChildren.length; i++) {
            var child = locChildren[i];
            if (child && child._visible) {
                var childRect = child._getBoundingBoxToCurrentNode(trans);
                if (childRect)
                    rect = cc.rectUnion(rect, childRect);
            }
        }
        return rect;
    },
    getOpacity: function () {
        return this._realOpacity;
    },
    getDisplayedOpacity: function () {
        return this._renderCmd.getDisplayedOpacity();
    },
    setOpacity: function (opacity) {
        this._realOpacity = opacity;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    },
    updateDisplayedOpacity: function (parentOpacity) {
        this._renderCmd._updateDisplayOpacity(parentOpacity);
    },
    isCascadeOpacityEnabled: function () {
        return this._cascadeOpacityEnabled;
    },
    setCascadeOpacityEnabled: function (cascadeOpacityEnabled) {
        if (this._cascadeOpacityEnabled === cascadeOpacityEnabled)
            return;
        this._cascadeOpacityEnabled = cascadeOpacityEnabled;
        this._renderCmd.setCascadeOpacityEnabledDirty();
    },
    getColor: function () {
        var locRealColor = this._realColor;
        return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
    },
    getDisplayedColor: function () {
        return this._renderCmd.getDisplayedColor();
    },
    setColor: function (color) {
        var locRealColor = this._realColor;
        locRealColor.r = color.r;
        locRealColor.g = color.g;
        locRealColor.b = color.b;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
    },
    updateDisplayedColor: function (parentColor) {
        this._renderCmd._updateDisplayColor(parentColor);
    },
    isCascadeColorEnabled: function () {
        return this._cascadeColorEnabled;
    },
    setCascadeColorEnabled: function (cascadeColorEnabled) {
        if (this._cascadeColorEnabled === cascadeColorEnabled)
            return;
        this._cascadeColorEnabled = cascadeColorEnabled;
        this._renderCmd.setCascadeColorEnabledDirty();
    },
    setOpacityModifyRGB: function (opacityValue) {
    },
    isOpacityModifyRGB: function () {
        return false;
    },
    _initRendererCmd: function(){
        this._renderCmd = cc.renderer.getRenderCmd(this);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.Node.CanvasRenderCmd(this);
        else
            return new cc.Node.WebGLRenderCmd(this);
    },
    enumerateChildren: function(name, callback){
        cc.assert(name && name.length != 0, "Invalid name");
        cc.assert(callback != null, "Invalid callback function");
        var length = name.length;
        var subStrStartPos = 0;
        var subStrlength = length;
        var searchRecursively = false;
        if(length > 2 && name[0] === "/" && name[1] === "/"){
            searchRecursively = true;
            subStrStartPos = 2;
            subStrlength -= 2;
        }
        var searchFromParent = false;
        if(length > 3 && name[length-3] === "/" && name[length-2] === "." && name[length-1] === "."){
            searchFromParent = true;
            subStrlength -= 3;
        }
        var newName = name.substr(subStrStartPos, subStrlength);
        if(searchFromParent)
            newName = "[[:alnum:]]+/" + newName;
        if(searchRecursively)
            this.doEnumerateRecursive(this, newName, callback);
        else
            this.doEnumerate(newName, callback);
    },
    doEnumerateRecursive: function(node, name, callback){
        var ret = false;
        if(node.doEnumerate(name,callback)){
            ret = true;
        }else{
            var child,
                children = node.getChildren(),
                length = children.length;
            for (var i=0; i<length; i++) {
                child = children[i];
                if (this.doEnumerateRecursive(child, name, callback)) {
                    ret = true;
                    break;
                }
            }
        }
    },
    doEnumerate: function(name, callback){
        var pos = name.indexOf('/');
        var searchName = name;
        var needRecursive = false;
        if (pos !== -1){
            searchName = name.substr(0, pos);
            needRecursive = true;
        }
        var ret = false;
        var child,
            children = this._children,
            length = children.length;
        for (var i=0; i<length; i++){
            child = children[i];
            if (child._name.indexOf(searchName) !== -1){
                if (!needRecursive){
                    if (callback(child)){
                        ret = true;
                        break;
                    }
                }else{
                    ret = child.doEnumerate(name, callback);
                    if (ret)
                        break;
                }
            }
        }
        return ret;
    }
});
cc.Node.create = function () {
    return new cc.Node();
};
cc.Node._stateCallbackType = {onEnter: 1, onExit: 2, cleanup: 3, onEnterTransitionDidFinish: 4, updateTransform: 5, onExitTransitionDidStart: 6, sortAllChildren: 7};
cc.assert(cc.isFunction(cc._tmp.PrototypeCCNode), cc._LogInfos.MissingFile, "BaseNodesPropertyDefine.js");
cc._tmp.PrototypeCCNode();
delete cc._tmp.PrototypeCCNode;
cc.CustomRenderCmd = function (target, func) {
    this._needDraw = true;
    this._target = target;
    this._callback = func;
    this.rendering = function (ctx, scaleX, scaleY) {
        if (!this._callback)
            return;
        this._callback.call(this._target, ctx, scaleX, scaleY);
    };
    this.needDraw = function () {
        return this._needDraw;
    };
};
cc.Node._dirtyFlags = {
    transformDirty: 1 << 0, visibleDirty: 1 << 1, colorDirty: 1 << 2, opacityDirty: 1 << 3, cacheDirty: 1 << 4,
    orderDirty: 1 << 5, textDirty: 1 << 6, gradientDirty: 1 << 7, textureDirty: 1 << 8,
    contentDirty: 1 << 9,
    COUNT: 10,
    all: (1 << 10) - 1
};
cc.Node.RenderCmd = function (renderable) {
    this._dirtyFlag = 1;
    this._savedDirtyFlag = true;
    this._node = renderable;
    this._needDraw = false;
    this._anchorPointInPoints = new cc.Point(0, 0);
    this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
    this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
    this._inverse = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
    this._displayedOpacity = 255;
    this._displayedColor = cc.color(255, 255, 255, 255);
    this._cascadeColorEnabledDirty = false;
    this._cascadeOpacityEnabledDirty = false;
    this._curLevel = -1;
};
cc.Node.RenderCmd.prototype = {
    constructor: cc.Node.RenderCmd,
    needDraw: function () {
        return this._needDraw;
    },
    getAnchorPointInPoints: function () {
        return cc.p(this._anchorPointInPoints);
    },
    getDisplayedColor: function () {
        var tmpColor = this._displayedColor;
        return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
    },
    getDisplayedOpacity: function () {
        return this._displayedOpacity;
    },
    setCascadeColorEnabledDirty: function () {
        this._cascadeColorEnabledDirty = true;
        this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
    },
    setCascadeOpacityEnabledDirty: function () {
        this._cascadeOpacityEnabledDirty = true;
        this.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    },
    getParentToNodeTransform: function () {
        if (this._dirtyFlag & cc.Node._dirtyFlags.transformDirty)
            this._inverse = cc.affineTransformInvert(this.getNodeToParentTransform());
        return this._inverse;
    },
    detachFromParent: function () {
    },
    _updateAnchorPointInPoint: function () {
        var locAPP = this._anchorPointInPoints, locSize = this._node._contentSize, locAnchorPoint = this._node._anchorPoint;
        locAPP.x = locSize.width * locAnchorPoint.x;
        locAPP.y = locSize.height * locAnchorPoint.y;
        this.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    setDirtyFlag: function (dirtyFlag) {
        if (this._dirtyFlag === 0 && dirtyFlag !== 0)
            cc.renderer.pushDirtyNode(this);
        this._dirtyFlag |= dirtyFlag;
    },
    getParentRenderCmd: function () {
        if (this._node && this._node._parent && this._node._parent._renderCmd)
            return this._node._parent._renderCmd;
        return null;
    },
    transform: function (parentCmd, recursive) {
        var node = this._node,
            pt = parentCmd ? parentCmd._worldTransform : null,
            t = this._transform,
            wt = this._worldTransform;
        if (node._usingNormalizedPosition && node._parent) {
            var conSize = node._parent._contentSize;
            node._position.x = node._normalizedPosition.x * conSize.width;
            node._position.y = node._normalizedPosition.y * conSize.height;
            node._normalizedPositionDirty = false;
        }
        var hasRotation = node._rotationX || node._rotationY;
        var hasSkew = node._skewX || node._skewY;
        var sx = node._scaleX, sy = node._scaleY;
        var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y;
        var a = 1, b = 0, c = 0, d = 1;
        if (hasRotation || hasSkew) {
            t.tx = node._position.x;
            t.ty = node._position.y;
            if (hasRotation) {
                var rotationRadiansX = node._rotationX * 0.017453292519943295;
                c = Math.sin(rotationRadiansX);
                d = Math.cos(rotationRadiansX);
                if (node._rotationY === node._rotationX) {
                    a = d;
                    b = -c;
                }
                else {
                    var rotationRadiansY = node._rotationY * 0.017453292519943295;
                    a = Math.cos(rotationRadiansY);
                    b = -Math.sin(rotationRadiansY);
                }
            }
            t.a = a *= sx;
            t.b = b *= sx;
            t.c = c *= sy;
            t.d = d *= sy;
            if (hasSkew) {
                var skx = Math.tan(node._skewX * Math.PI / 180);
                var sky = Math.tan(node._skewY * Math.PI / 180);
                if (skx === Infinity)
                    skx = 99999999;
                if (sky === Infinity)
                    sky = 99999999;
                t.a = a + c * sky;
                t.b = b + d * sky;
                t.c = c + a * skx;
                t.d = d + b * skx;
            }
            if (appX || appY) {
                t.tx -= t.a * appX + t.c * appY;
                t.ty -= t.b * appX + t.d * appY;
                if (node._ignoreAnchorPointForPosition) {
                    t.tx += appX;
                    t.ty += appY;
                }
            }
            if (pt) {
                wt.a = t.a * pt.a + t.b * pt.c;
                wt.b = t.a * pt.b + t.b * pt.d;
                wt.c = t.c * pt.a + t.d * pt.c;
                wt.d = t.c * pt.b + t.d * pt.d;
                wt.tx = pt.a * t.tx + pt.c * t.ty + pt.tx;
                wt.ty = pt.d * t.ty + pt.ty + pt.b * t.tx;
            } else {
                wt.a = t.a;
                wt.b = t.b;
                wt.c = t.c;
                wt.d = t.d;
                wt.tx = t.tx;
                wt.ty = t.ty;
            }
        }
        else {
            t.a = sx;
            t.b = 0;
            t.c = 0;
            t.d = sy;
            t.tx = node._position.x;
            t.ty = node._position.y;
            if (appX || appY) {
                t.tx -= t.a * appX;
                t.ty -= t.d * appY;
                if (node._ignoreAnchorPointForPosition) {
                    t.tx += appX;
                    t.ty += appY;
                }
            }
            if (pt) {
                wt.a = t.a * pt.a + t.b * pt.c;
                wt.b = t.a * pt.b + t.b * pt.d;
                wt.c = t.c * pt.a + t.d * pt.c;
                wt.d = t.c * pt.b + t.d * pt.d;
                wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
                wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
            } else {
                wt.a = t.a;
                wt.b = t.b;
                wt.c = t.c;
                wt.d = t.d;
                wt.tx = t.tx;
                wt.ty = t.ty;
            }
        }
        if (node._additionalTransformDirty) {
            this._transform = cc.affineTransformConcat(t, node._additionalTransform);
        }
        this._updateCurrentRegions && this._updateCurrentRegions();
        this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble);
        if (recursive) {
            var locChildren = this._node._children;
            if (!locChildren || locChildren.length === 0)
                return;
            var i, len;
            for (i = 0, len = locChildren.length; i < len; i++) {
                locChildren[i]._renderCmd.transform(this, recursive);
            }
        }
        this._cacheDirty = true;
    },
    getNodeToParentTransform: function () {
        if (this._dirtyFlag & cc.Node._dirtyFlags.transformDirty) {
            this.transform();
        }
        return this._transform;
    },
    visit: function (parentCmd) {
        var node = this._node, renderer = cc.renderer;
        if (!node._visible)
            return;
        parentCmd = parentCmd || this.getParentRenderCmd();
        if (parentCmd)
            this._curLevel = parentCmd._curLevel + 1;
        if (isNaN(node._customZ)) {
            node._vertexZ = renderer.assignedZ;
            renderer.assignedZ += renderer.assignedZStep;
        }
        this._syncStatus(parentCmd);
        this.visitChildren();
    },
    _updateDisplayColor: function (parentColor) {
        var node = this._node;
        var locDispColor = this._displayedColor, locRealColor = node._realColor;
        var i, len, selChildren, item;
        this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
        if (this._cascadeColorEnabledDirty && !node._cascadeColorEnabled) {
            locDispColor.r = locRealColor.r;
            locDispColor.g = locRealColor.g;
            locDispColor.b = locRealColor.b;
            var whiteColor = new cc.Color(255, 255, 255, 255);
            selChildren = node._children;
            for (i = 0, len = selChildren.length; i < len; i++) {
                item = selChildren[i];
                if (item && item._renderCmd)
                    item._renderCmd._updateDisplayColor(whiteColor);
            }
            this._cascadeColorEnabledDirty = false;
        } else {
            if (parentColor === undefined) {
                var locParent = node._parent;
                if (locParent && locParent._cascadeColorEnabled)
                    parentColor = locParent.getDisplayedColor();
                else
                    parentColor = cc.color.WHITE;
            }
            locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
            locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
            locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
            if (node._cascadeColorEnabled) {
                selChildren = node._children;
                for (i = 0, len = selChildren.length; i < len; i++) {
                    item = selChildren[i];
                    if (item && item._renderCmd) {
                        item._renderCmd._updateDisplayColor(locDispColor);
                        item._renderCmd._updateColor();
                    }
                }
            }
        }
        this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.colorDirty ^ this._dirtyFlag;
    },
    _updateDisplayOpacity: function (parentOpacity) {
        var node = this._node;
        var i, len, selChildren, item;
        this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
        if (this._cascadeOpacityEnabledDirty && !node._cascadeOpacityEnabled) {
            this._displayedOpacity = node._realOpacity;
            selChildren = node._children;
            for (i = 0, len = selChildren.length; i < len; i++) {
                item = selChildren[i];
                if (item && item._renderCmd)
                    item._renderCmd._updateDisplayOpacity(255);
            }
            this._cascadeOpacityEnabledDirty = false;
        } else {
            if (parentOpacity === undefined) {
                var locParent = node._parent;
                parentOpacity = 255;
                if (locParent && locParent._cascadeOpacityEnabled)
                    parentOpacity = locParent.getDisplayedOpacity();
            }
            this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
            if (node._cascadeOpacityEnabled) {
                selChildren = node._children;
                for (i = 0, len = selChildren.length; i < len; i++) {
                    item = selChildren[i];
                    if (item && item._renderCmd) {
                        item._renderCmd._updateDisplayOpacity(this._displayedOpacity);
                        item._renderCmd._updateColor();
                    }
                }
            }
        }
        this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.opacityDirty ^ this._dirtyFlag;
    },
    _syncDisplayColor: function (parentColor) {
        var node = this._node, locDispColor = this._displayedColor, locRealColor = node._realColor;
        if (parentColor === undefined) {
            var locParent = node._parent;
            if (locParent && locParent._cascadeColorEnabled)
                parentColor = locParent.getDisplayedColor();
            else
                parentColor = cc.color.WHITE;
        }
        locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
        locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
        locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
    },
    _syncDisplayOpacity: function (parentOpacity) {
        var node = this._node;
        if (parentOpacity === undefined) {
            var locParent = node._parent;
            parentOpacity = 255;
            if (locParent && locParent._cascadeOpacityEnabled)
                parentOpacity = locParent.getDisplayedOpacity();
        }
        this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
    },
    _updateColor: function () {
    },
    updateStatus: function () {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        var colorDirty = locFlag & flags.colorDirty,
            opacityDirty = locFlag & flags.opacityDirty;
        this._savedDirtyFlag = this._savedDirtyFlag || locFlag;
        if (colorDirty)
            this._updateDisplayColor();
        if (opacityDirty)
            this._updateDisplayOpacity();
        if (colorDirty || opacityDirty)
            this._updateColor();
        if (locFlag & flags.transformDirty) {
            this.transform(this.getParentRenderCmd(), true);
            this._dirtyFlag = this._dirtyFlag & flags.transformDirty ^ this._dirtyFlag;
        }
        if (locFlag & flags.orderDirty)
            this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
    },
    _syncStatus: function (parentCmd) {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag, parentNode = null;
        if (parentCmd) {
            parentNode = parentCmd._node;
            this._savedDirtyFlag = this._savedDirtyFlag || parentCmd._savedDirtyFlag || locFlag;
        }
        else {
            this._savedDirtyFlag = this._savedDirtyFlag || locFlag;
        }
        if (parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & flags.colorDirty))
            locFlag |= flags.colorDirty;
        if (parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & flags.opacityDirty))
            locFlag |= flags.opacityDirty;
        if (parentCmd && (parentCmd._dirtyFlag & flags.transformDirty))
            locFlag |= flags.transformDirty;
        var colorDirty = locFlag & flags.colorDirty,
            opacityDirty = locFlag & flags.opacityDirty;
        this._dirtyFlag = locFlag;
        if (colorDirty)
            this._syncDisplayColor();
        if (opacityDirty)
            this._syncDisplayOpacity();
        if (colorDirty || opacityDirty)
            this._updateColor();
        if (locFlag & flags.transformDirty)
            this.transform(parentCmd);
        if (locFlag & flags.orderDirty)
            this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
    },
    visitChildren: function () {
        var renderer = cc.renderer;
        var node = this._node;
        var i, children = node._children, child;
        var len = children.length;
        if (len > 0) {
            node.sortAllChildren();
            for (i = 0; i < len; i++) {
                child = children[i];
                if (child._localZOrder < 0) {
                    child._renderCmd.visit(this);
                }
                else {
                    break;
                }
            }
            renderer.pushRenderCommand(this);
            for (; i < len; i++) {
                children[i]._renderCmd.visit(this);
            }
        } else {
            renderer.pushRenderCommand(this);
        }
        this._dirtyFlag = 0;
    }
};
cc.Node.RenderCmd.prototype.originVisit = cc.Node.RenderCmd.prototype.visit;
cc.Node.RenderCmd.prototype.originTransform = cc.Node.RenderCmd.prototype.transform;
(function () {
    cc.Node.CanvasRenderCmd = function (renderable) {
        cc.Node.RenderCmd.call(this, renderable);
        this._cachedParent = null;
        this._cacheDirty = false;
        this._currentRegion = new cc.Region();
        this._oldRegion = new cc.Region();
        this._regionFlag = 0;
        this._canUseDirtyRegion = false;
    };
    cc.Node.CanvasRenderCmd.RegionStatus = {
        NotDirty: 0,
        Dirty: 1,
        DirtyDouble: 2
    };
    var proto = cc.Node.CanvasRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype);
    proto.constructor = cc.Node.CanvasRenderCmd;
    proto._notifyRegionStatus = function (status) {
        if (this._needDraw && this._regionFlag < status) {
            this._regionFlag = status;
        }
    };
    var localBB = new cc.Rect();
    proto.getLocalBB = function () {
        var node = this._node;
        localBB.x = localBB.y = 0;
        localBB.width = node._contentSize.width;
        localBB.height = node._contentSize.height;
        return localBB;
    };
    proto._updateCurrentRegions = function () {
        var temp = this._currentRegion;
        this._currentRegion = this._oldRegion;
        this._oldRegion = temp;
        if (cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble === this._regionFlag && (!this._currentRegion.isEmpty())) {
            this._oldRegion.union(this._currentRegion);
        }
        this._currentRegion.updateRegion(this.getLocalBB(), this._worldTransform);
    };
    proto.setDirtyFlag = function (dirtyFlag, child) {
        cc.Node.RenderCmd.prototype.setDirtyFlag.call(this, dirtyFlag, child);
        this._setCacheDirty(child);
        if (this._cachedParent)
            this._cachedParent.setDirtyFlag(dirtyFlag, true);
    };
    proto._setCacheDirty = function () {
        if (this._cacheDirty === false) {
            this._cacheDirty = true;
            var cachedP = this._cachedParent;
            cachedP && cachedP !== this && cachedP._setNodeDirtyForCache && cachedP._setNodeDirtyForCache();
        }
    };
    proto._setCachedParent = function (cachedParent) {
        if (this._cachedParent === cachedParent)
            return;
        this._cachedParent = cachedParent;
        var children = this._node._children;
        for (var i = 0, len = children.length; i < len; i++)
            children[i]._renderCmd._setCachedParent(cachedParent);
    };
    proto.detachFromParent = function () {
        this._cachedParent = null;
        var selChildren = this._node._children, item;
        for (var i = 0, len = selChildren.length; i < len; i++) {
            item = selChildren[i];
            if (item && item._renderCmd)
                item._renderCmd.detachFromParent();
        }
    };
    proto.setShaderProgram = function (shaderProgram) {
    };
    proto.getShaderProgram = function () {
        return null;
    };
    cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc = function (blendFunc) {
        if (!blendFunc)
            return "source-over";
        else {
            if (( blendFunc.src === cc.SRC_ALPHA && blendFunc.dst === cc.ONE) || (blendFunc.src === cc.ONE && blendFunc.dst === cc.ONE))
                return "lighter";
            else if (blendFunc.src === cc.ZERO && blendFunc.dst === cc.SRC_ALPHA)
                return "destination-in";
            else if (blendFunc.src === cc.ZERO && blendFunc.dst === cc.ONE_MINUS_SRC_ALPHA)
                return "destination-out";
            else
                return "source-over";
        }
    };
})();
cc._tmp.PrototypeTexture2D = function () {
    var _c = cc.Texture2D;
    _c.PVRImagesHavePremultipliedAlpha = function (haveAlphaPremultiplied) {
        cc.PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied;
    };
    _c.PIXEL_FORMAT_RGBA8888 = 2;
    _c.PIXEL_FORMAT_RGB888 = 3;
    _c.PIXEL_FORMAT_RGB565 = 4;
    _c.PIXEL_FORMAT_A8 = 5;
    _c.PIXEL_FORMAT_I8 = 6;
    _c.PIXEL_FORMAT_AI88 = 7;
    _c.PIXEL_FORMAT_RGBA4444 = 8;
    _c.PIXEL_FORMAT_RGB5A1 = 7;
    _c.PIXEL_FORMAT_PVRTC4 = 9;
    _c.PIXEL_FORMAT_PVRTC2 = 10;
    _c.PIXEL_FORMAT_DEFAULT = _c.PIXEL_FORMAT_RGBA8888;
    _c.defaultPixelFormat = _c.PIXEL_FORMAT_DEFAULT;
    var _M = cc.Texture2D._M = {};
    _M[_c.PIXEL_FORMAT_RGBA8888] = "RGBA8888";
    _M[_c.PIXEL_FORMAT_RGB888] = "RGB888";
    _M[_c.PIXEL_FORMAT_RGB565] = "RGB565";
    _M[_c.PIXEL_FORMAT_A8] = "A8";
    _M[_c.PIXEL_FORMAT_I8] = "I8";
    _M[_c.PIXEL_FORMAT_AI88] = "AI88";
    _M[_c.PIXEL_FORMAT_RGBA4444] = "RGBA4444";
    _M[_c.PIXEL_FORMAT_RGB5A1] = "RGB5A1";
    _M[_c.PIXEL_FORMAT_PVRTC4] = "PVRTC4";
    _M[_c.PIXEL_FORMAT_PVRTC2] = "PVRTC2";
    var _B = cc.Texture2D._B = {};
    _B[_c.PIXEL_FORMAT_RGBA8888] = 32;
    _B[_c.PIXEL_FORMAT_RGB888] = 24;
    _B[_c.PIXEL_FORMAT_RGB565] = 16;
    _B[_c.PIXEL_FORMAT_A8] = 8;
    _B[_c.PIXEL_FORMAT_I8] = 8;
    _B[_c.PIXEL_FORMAT_AI88] = 16;
    _B[_c.PIXEL_FORMAT_RGBA4444] = 16;
    _B[_c.PIXEL_FORMAT_RGB5A1] = 16;
    _B[_c.PIXEL_FORMAT_PVRTC4] = 4;
    _B[_c.PIXEL_FORMAT_PVRTC2] = 3;
    var _p = cc.Texture2D.prototype;
    _p.name;
    cc.defineGetterSetter(_p, "name", _p.getName);
    _p.pixelFormat;
    cc.defineGetterSetter(_p, "pixelFormat", _p.getPixelFormat);
    _p.pixelsWidth;
    cc.defineGetterSetter(_p, "pixelsWidth", _p.getPixelsWide);
    _p.pixelsHeight;
    cc.defineGetterSetter(_p, "pixelsHeight", _p.getPixelsHigh);
    _p.width;
    cc.defineGetterSetter(_p, "width", _p._getWidth);
    _p.height;
    cc.defineGetterSetter(_p, "height", _p._getHeight);
};
cc._tmp.PrototypeTextureAtlas = function () {
    var _p = cc.TextureAtlas.prototype;
    _p.totalQuads;
    cc.defineGetterSetter(_p, "totalQuads", _p.getTotalQuads);
    _p.capacity;
    cc.defineGetterSetter(_p, "capacity", _p.getCapacity);
    _p.quads;
    cc.defineGetterSetter(_p, "quads", _p.getQuads, _p.setQuads);
};
cc._tmp.WebGLTexture2D = function () {
    cc.Texture2D = cc.Class.extend({
        _pVRHaveAlphaPremultiplied: true,
        _pixelFormat: null,
        _pixelsWide: 0,
        _pixelsHigh: 0,
        _name: "",
        _contentSize: null,
        maxS: 0,
        maxT: 0,
        _hasPremultipliedAlpha: false,
        _hasMipmaps: false,
        shaderProgram: null,
        _textureLoaded: false,
        _htmlElementObj: null,
        _webTextureObj: null,
        url: null,
        ctor: function () {
            this._contentSize = cc.size(0, 0);
            this._pixelFormat = cc.Texture2D.defaultPixelFormat;
        },
        releaseTexture: function () {
            if (this._webTextureObj)
                cc._renderContext.deleteTexture(this._webTextureObj);
            cc.loader.release(this.url);
        },
        getPixelFormat: function () {
            return this._pixelFormat;
        },
        getPixelsWide: function () {
            return this._pixelsWide;
        },
        getPixelsHigh: function () {
            return this._pixelsHigh;
        },
        getName: function () {
            return this._webTextureObj;
        },
        getContentSize: function () {
            return cc.size(this._contentSize.width / cc.contentScaleFactor(), this._contentSize.height / cc.contentScaleFactor());
        },
        _getWidth: function () {
            return this._contentSize.width / cc.contentScaleFactor();
        },
        _getHeight: function () {
            return this._contentSize.height / cc.contentScaleFactor();
        },
        getContentSizeInPixels: function () {
            return this._contentSize;
        },
        getMaxS: function () {
            return this.maxS;
        },
        setMaxS: function (maxS) {
            this.maxS = maxS;
        },
        getMaxT: function () {
            return this.maxT;
        },
        setMaxT: function (maxT) {
            this.maxT = maxT;
        },
        getShaderProgram: function () {
            return this.shaderProgram;
        },
        setShaderProgram: function (shaderProgram) {
            this.shaderProgram = shaderProgram;
        },
        hasPremultipliedAlpha: function () {
            return this._hasPremultipliedAlpha;
        },
        hasMipmaps: function () {
            return this._hasMipmaps;
        },
        description: function () {
            var _t = this;
            return "<cc.Texture2D | Name = " + _t._name + " | Dimensions = " + _t._pixelsWide + " x " + _t._pixelsHigh
                + " | Coordinates = (" + _t.maxS + ", " + _t.maxT + ")>";
        },
        releaseData: function (data) {
            data = null;
        },
        keepData: function (data, length) {
            return data;
        },
        initWithData: function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
            var self = this, tex2d = cc.Texture2D;
            var gl = cc._renderContext;
            var format = gl.RGBA, type = gl.UNSIGNED_BYTE;
            var bitsPerPixel = cc.Texture2D._B[pixelFormat];
            var bytesPerRow = pixelsWide * bitsPerPixel / 8;
            if (bytesPerRow % 8 === 0) {
                gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8);
            } else if (bytesPerRow % 4 === 0) {
                gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
            } else if (bytesPerRow % 2 === 0) {
                gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
            } else {
                gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
            }
            self._webTextureObj = gl.createTexture();
            cc.glBindTexture2D(self);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            switch (pixelFormat) {
                case tex2d.PIXEL_FORMAT_RGBA8888:
                    format = gl.RGBA;
                    break;
                case tex2d.PIXEL_FORMAT_RGB888:
                    format = gl.RGB;
                    break;
                case tex2d.PIXEL_FORMAT_RGBA4444:
                    type = gl.UNSIGNED_SHORT_4_4_4_4;
                    break;
                case tex2d.PIXEL_FORMAT_RGB5A1:
                    type = gl.UNSIGNED_SHORT_5_5_5_1;
                    break;
                case tex2d.PIXEL_FORMAT_RGB565:
                    type = gl.UNSIGNED_SHORT_5_6_5;
                    break;
                case tex2d.PIXEL_FORMAT_AI88:
                    format = gl.LUMINANCE_ALPHA;
                    break;
                case tex2d.PIXEL_FORMAT_A8:
                    format = gl.ALPHA;
                    break;
                case tex2d.PIXEL_FORMAT_I8:
                    format = gl.LUMINANCE;
                    break;
                default:
                    cc.assert(0, cc._LogInfos.Texture2D_initWithData);
            }
            gl.texImage2D(gl.TEXTURE_2D, 0, format, pixelsWide, pixelsHigh, 0, format, type, data);
            self._contentSize.width = contentSize.width;
            self._contentSize.height = contentSize.height;
            self._pixelsWide = pixelsWide;
            self._pixelsHigh = pixelsHigh;
            self._pixelFormat = pixelFormat;
            self.maxS = contentSize.width / pixelsWide;
            self.maxT = contentSize.height / pixelsHigh;
            self._hasPremultipliedAlpha = false;
            self._hasMipmaps = false;
            self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
            self._textureLoaded = true;
            return true;
        },
        drawAtPoint: function (point) {
            var self = this;
            var coordinates = [
                0.0, self.maxT,
                self.maxS, self.maxT,
                0.0, 0.0,
                self.maxS, 0.0 ],
                gl = cc._renderContext;
            var width = self._pixelsWide * self.maxS,
                height = self._pixelsHigh * self.maxT;
            var vertices = [
                point.x, point.y, 0.0,
                width + point.x, point.y, 0.0,
                point.x, height + point.y, 0.0,
                width + point.x, height + point.y, 0.0 ];
            self._shaderProgram.use();
            self._shaderProgram.setUniformsForBuiltins();
            cc.glBindTexture2D(self);
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        },
        drawInRect: function (rect) {
            var self = this;
            var coordinates = [
                0.0, self.maxT,
                self.maxS, self.maxT,
                0.0, 0.0,
                self.maxS, 0.0];
            var vertices = [    rect.x, rect.y,
                rect.x + rect.width, rect.y,
                rect.x, rect.y + rect.height,
                rect.x + rect.width, rect.y + rect.height         ];
            self._shaderProgram.use();
            self._shaderProgram.setUniformsForBuiltins();
            cc.glBindTexture2D(self);
            var gl = cc._renderContext;
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        },
        initWithImage: function (uiImage) {
            if (uiImage == null) {
                cc.log(cc._LogInfos.Texture2D_initWithImage);
                return false;
            }
            var imageWidth = uiImage.getWidth();
            var imageHeight = uiImage.getHeight();
            var maxTextureSize = cc.configuration.getMaxTextureSize();
            if (imageWidth > maxTextureSize || imageHeight > maxTextureSize) {
                cc.log(cc._LogInfos.Texture2D_initWithImage_2, imageWidth, imageHeight, maxTextureSize, maxTextureSize);
                return false;
            }
            this._textureLoaded = true;
            return this._initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight);
        },
        initWithElement: function (element) {
            if (!element)
                return;
            this._webTextureObj = cc._renderContext.createTexture();
            this._htmlElementObj = element;
            this._textureLoaded = true;
            this._hasPremultipliedAlpha = true;
        },
        getHtmlElementObj: function () {
            return this._htmlElementObj;
        },
        isLoaded: function () {
            return this._textureLoaded;
        },
        handleLoadedTexture: function (premultiplied) {
            var self = this;
            premultiplied =
              (premultiplied !== undefined)
                ? premultiplied
                : self._hasPremultipliedAlpha;
            if (!cc.game._rendererInitialized)
                return;
            if (!self._htmlElementObj) {
                var img = cc.loader.getRes(self.url);
                if (!img) return;
                self.initWithElement(img);
            }
            if (!self._htmlElementObj.width || !self._htmlElementObj.height)
                return;
            var gl = cc._renderContext;
            cc.glBindTexture2D(self);
            gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
            if(premultiplied)
                gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self._htmlElementObj);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
            cc.glBindTexture2D(null);
            if(premultiplied)
                gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);
            var pixelsWide = self._htmlElementObj.width;
            var pixelsHigh = self._htmlElementObj.height;
            self._pixelsWide = self._contentSize.width = pixelsWide;
            self._pixelsHigh = self._contentSize.height = pixelsHigh;
            self._pixelFormat = cc.Texture2D.PIXEL_FORMAT_RGBA8888;
            self.maxS = 1;
            self.maxT = 1;
            self._hasPremultipliedAlpha = premultiplied;
            self._hasMipmaps = false;
            self.dispatchEvent("load");
        },
        initWithString: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
            cc.log(cc._LogInfos.Texture2D_initWithString);
            return null;
        },
        initWithETCFile: function (file) {
            cc.log(cc._LogInfos.Texture2D_initWithETCFile_2);
            return false;
        },
        initWithPVRFile: function (file) {
            cc.log(cc._LogInfos.Texture2D_initWithPVRFile_2);
            return false;
        },
        initWithPVRTCData: function (data, level, bpp, hasAlpha, length, pixelFormat) {
            cc.log(cc._LogInfos.Texture2D_initWithPVRTCData_2);
            return false;
        },
        setTexParameters: function (texParams, magFilter, wrapS, wrapT) {
            var _t = this;
            var gl = cc._renderContext;
            if(magFilter !== undefined)
                texParams = {minFilter: texParams, magFilter: magFilter, wrapS: wrapS, wrapT: wrapT};
            cc.assert((_t._pixelsWide === cc.NextPOT(_t._pixelsWide) && _t._pixelsHigh === cc.NextPOT(_t._pixelsHigh)) ||
                (texParams.wrapS === gl.CLAMP_TO_EDGE && texParams.wrapT === gl.CLAMP_TO_EDGE),
                "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures");
            cc.glBindTexture2D(_t);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT);
        },
        setAntiAliasTexParameters: function () {
            var gl = cc._renderContext;
            cc.glBindTexture2D(this);
            if (!this._hasMipmaps)
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            else
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        },
        setAliasTexParameters: function () {
            var gl = cc._renderContext;
            cc.glBindTexture2D(this);
            if (!this._hasMipmaps)
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
            else
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        },
        generateMipmap: function () {
            var _t = this;
            cc.assert(_t._pixelsWide === cc.NextPOT(_t._pixelsWide) && _t._pixelsHigh === cc.NextPOT(_t._pixelsHigh), "Mimpap texture only works in POT textures");
            cc.glBindTexture2D(_t);
            cc._renderContext.generateMipmap(cc._renderContext.TEXTURE_2D);
            _t._hasMipmaps = true;
        },
        stringForFormat: function () {
            return cc.Texture2D._M[this._pixelFormat];
        },
        bitsPerPixelForFormat: function (format) {//TODO I want to delete the format argument, use this._pixelFormat
            format = format || this._pixelFormat;
            var value = cc.Texture2D._B[format];
            if (value != null) return value;
            cc.log(cc._LogInfos.Texture2D_bitsPerPixelForFormat, format);
            return -1;
        },
        _initPremultipliedATextureWithImage: function (uiImage, width, height) {
            var tex2d = cc.Texture2D;
            var tempData = uiImage.getData();
            var inPixel32 = null;
            var inPixel8 = null;
            var outPixel16 = null;
            var hasAlpha = uiImage.hasAlpha();
            var imageSize = cc.size(uiImage.getWidth(), uiImage.getHeight());
            var pixelFormat = tex2d.defaultPixelFormat;
            var bpp = uiImage.getBitsPerComponent();
            var i;
            if (!hasAlpha) {
                if (bpp >= 8) {
                    pixelFormat = tex2d.PIXEL_FORMAT_RGB888;
                } else {
                    cc.log(cc._LogInfos.Texture2D__initPremultipliedATextureWithImage);
                    pixelFormat = tex2d.PIXEL_FORMAT_RGB565;
                }
            }
            var length = width * height;
            if (pixelFormat === tex2d.PIXEL_FORMAT_RGB565) {
                if (hasAlpha) {
                    tempData = new Uint16Array(width * height);
                    inPixel32 = uiImage.getData();
                    for (i = 0; i < length; ++i) {
                        tempData[i] =
                            ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) |
                                ((((inPixel32[i] >> 8) & 0xFF) >> 2) << 5) |
                                ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 0);
                    }
                } else {
                    tempData = new Uint16Array(width * height);
                    inPixel8 = uiImage.getData();
                    for (i = 0; i < length; ++i) {
                        tempData[i] =
                            (((inPixel8[i] & 0xFF) >> 3) << 11) |
                                (((inPixel8[i] & 0xFF) >> 2) << 5) |
                                (((inPixel8[i] & 0xFF) >> 3) << 0);
                    }
                }
            } else if (pixelFormat === tex2d.PIXEL_FORMAT_RGBA4444) {
                tempData = new Uint16Array(width * height);
                inPixel32 = uiImage.getData();
                for (i = 0; i < length; ++i) {
                    tempData[i] =
                        ((((inPixel32[i] >> 0) & 0xFF) >> 4) << 12) |
                            ((((inPixel32[i] >> 8) & 0xFF) >> 4) << 8) |
                            ((((inPixel32[i] >> 16) & 0xFF) >> 4) << 4) |
                            ((((inPixel32[i] >> 24) & 0xFF) >> 4) << 0);
                }
            } else if (pixelFormat === tex2d.PIXEL_FORMAT_RGB5A1) {
                tempData = new Uint16Array(width * height);
                inPixel32 = uiImage.getData();
                for (i = 0; i < length; ++i) {
                    tempData[i] =
                        ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) |
                            ((((inPixel32[i] >> 8) & 0xFF) >> 3) << 6) |
                            ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 1) |
                            ((((inPixel32[i] >> 24) & 0xFF) >> 7) << 0);
                }
            } else if (pixelFormat === tex2d.PIXEL_FORMAT_A8) {
                tempData = new Uint8Array(width * height);
                inPixel32 = uiImage.getData();
                for (i = 0; i < length; ++i) {
                    tempData[i] = (inPixel32 >> 24) & 0xFF;
                }
            }
            if (hasAlpha && pixelFormat === tex2d.PIXEL_FORMAT_RGB888) {
                inPixel32 = uiImage.getData();
                tempData = new Uint8Array(width * height * 3);
                for (i = 0; i < length; ++i) {
                    tempData[i * 3] = (inPixel32 >> 0) & 0xFF;
                    tempData[i * 3 + 1] = (inPixel32 >> 8) & 0xFF;
                    tempData[i * 3 + 2] = (inPixel32 >> 16) & 0xFF;
                }
            }
            this.initWithData(tempData, pixelFormat, width, height, imageSize);
            if (tempData != uiImage.getData())
                tempData = null;
            this._hasPremultipliedAlpha = uiImage.isPremultipliedAlpha();
            return true;
        },
        addLoadedEventListener: function (callback, target) {
            this.addEventListener("load", callback, target);
        },
        removeLoadedEventListener: function (target) {
            this.removeEventTarget("load", target);
        }
    });
};
cc._tmp.WebGLTextureAtlas = function () {
    var _p = cc.TextureAtlas.prototype;
    _p._setupVBO = function () {
        var _t = this;
        var gl = cc._renderContext;
        _t._buffersVBO[0] = gl.createBuffer();
        _t._buffersVBO[1] = gl.createBuffer();
        _t._quadsWebBuffer = gl.createBuffer();
        _t._mapBuffers();
    };
    _p._mapBuffers = function () {
        var _t = this;
        var gl = cc._renderContext;
        gl.bindBuffer(gl.ARRAY_BUFFER, _t._quadsWebBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, _t._quadsArrayBuffer, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _t._buffersVBO[1]);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, _t._indices, gl.STATIC_DRAW);
    };
    _p.drawNumberOfQuads = function (n, start) {
        var _t = this;
        start = start || 0;
        if (0 === n || !_t.texture || !_t.texture.isLoaded())
            return;
        var gl = cc._renderContext;
        cc.glBindTexture2D(_t.texture);
        gl.bindBuffer(gl.ARRAY_BUFFER, _t._quadsWebBuffer);
        if (_t.dirty){
            gl.bufferData(gl.ARRAY_BUFFER, _t._quadsArrayBuffer, gl.DYNAMIC_DRAW);
            _t.dirty = false;
        }
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _t._buffersVBO[1]);
        if (cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP)
            gl.drawElements(gl.TRIANGLE_STRIP, n * 6, gl.UNSIGNED_SHORT, start * 6 * _t._indices.BYTES_PER_ELEMENT);
        else
            gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, start * 6 * _t._indices.BYTES_PER_ELEMENT);
        cc.g_NumberOfDraws++;
    };
};
cc._tmp.WebGLTextureCache = function () {
    var _p = cc.textureCache;
    _p.handleLoadedTexture = function (url) {
        var locTexs = this._textures, tex, ext;
        if (!cc.game._rendererInitialized) {
            locTexs = this._loadedTexturesBefore;
        }
        tex = locTexs[url];
        if (!tex) {
            tex = locTexs[url] = new cc.Texture2D();
            tex.url = url;
        }
        ext = cc.path.extname(url);
        if (ext === ".png") {
            tex.handleLoadedTexture(true);
        }
        else {
            tex.handleLoadedTexture();
        }
    };
    _p.addImage = function (url, cb, target) {
        cc.assert(url, cc._LogInfos.Texture2D_addImage_2);
        var locTexs = this._textures;
        if (!cc.game._rendererInitialized) {
            locTexs = this._loadedTexturesBefore;
        }
        var tex = locTexs[url] || locTexs[cc.loader._getAliase(url)];
        if (tex) {
            if(tex.isLoaded()) {
                cb && cb.call(target, tex);
                return tex;
            }
            else
            {
                tex.addEventListener("load", function(){
                   cb && cb.call(target, tex);
                }, target);
                return tex;
            }
        }
        tex = locTexs[url] = new cc.Texture2D();
        tex.url = url;
        var basePath = cc.loader.getBasePath ? cc.loader.getBasePath() : cc.loader.resPath;
        cc.loader.loadImg(cc.path.join(basePath || "", url), function (err, img) {
            if (err)
                return cb && cb.call(target, err);
            if (!cc.loader.cache[url]) {
                cc.loader.cache[url] = img;
            }
            cc.textureCache.handleLoadedTexture(url);
            var texResult = locTexs[url];
            cb && cb.call(target, texResult);
        });
        return tex;
    };
    _p.addImageAsync = _p.addImage;
    _p = null;
};
cc.ALIGN_CENTER = 0x33;
cc.ALIGN_TOP = 0x13;
cc.ALIGN_TOP_RIGHT = 0x12;
cc.ALIGN_RIGHT = 0x32;
cc.ALIGN_BOTTOM_RIGHT = 0x22;
cc.ALIGN_BOTTOM = 0x23;
cc.ALIGN_BOTTOM_LEFT = 0x21;
cc.ALIGN_LEFT = 0x31;
cc.ALIGN_TOP_LEFT = 0x11;
cc.PVRHaveAlphaPremultiplied_ = false;
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if(cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
        var proto = {
            _contentSize: null,
            _textureLoaded: false,
            _htmlElementObj: null,
            url: null,
            _pattern: null,
            ctor: function () {
                this._contentSize = cc.size(0, 0);
                this._textureLoaded = false;
                this._htmlElementObj = null;
                this._pattern = "";
            },
            getPixelsWide: function () {
                return this._contentSize.width;
            },
            getPixelsHigh: function () {
                return this._contentSize.height;
            },
            getContentSize: function () {
                var locScaleFactor = cc.contentScaleFactor();
                return cc.size(this._contentSize.width / locScaleFactor, this._contentSize.height / locScaleFactor);
            },
            _getWidth: function () {
                return this._contentSize.width / cc.contentScaleFactor();
            },
            _getHeight: function () {
                return this._contentSize.height / cc.contentScaleFactor();
            },
            getContentSizeInPixels: function () {
                return this._contentSize;
            },
            initWithElement: function (element) {
                if (!element)
                    return;
                this._htmlElementObj = element;
                this._contentSize.width = element.width;
                this._contentSize.height = element.height;
                this._textureLoaded = true;
            },
            getHtmlElementObj: function () {
                return this._htmlElementObj;
            },
            isLoaded: function () {
                return this._textureLoaded;
            },
            handleLoadedTexture: function () {
                var self = this;
                if (self._textureLoaded) return;
                if (!self._htmlElementObj) {
                    var img = cc.loader.getRes(self.url);
                    if (!img) return;
                    self.initWithElement(img);
                }
                var locElement = self._htmlElementObj;
                self._contentSize.width = locElement.width;
                self._contentSize.height = locElement.height;
                self.dispatchEvent("load");
            },
            description: function () {
                return "<cc.Texture2D | width = " + this._contentSize.width + " height " + this._contentSize.height + ">";
            },
            initWithData: function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
                return false;
            },
            initWithImage: function (uiImage) {
                return false;
            },
            initWithString: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
                return false;
            },
            releaseTexture: function () {
                cc.loader.release(this.url);
            },
            getName: function () {
                return null;
            },
            getMaxS: function () {
                return 1;
            },
            setMaxS: function (maxS) {
            },
            getMaxT: function () {
                return 1;
            },
            setMaxT: function (maxT) {
            },
            getPixelFormat: function () {
                return null;
            },
            getShaderProgram: function () {
                return null;
            },
            setShaderProgram: function (shaderProgram) {
            },
            hasPremultipliedAlpha: function () {
                return false;
            },
            hasMipmaps: function () {
                return false;
            },
            releaseData: function (data) {
                data = null;
            },
            keepData: function (data, length) {
                return data;
            },
            drawAtPoint: function (point) {
            },
            drawInRect: function (rect) {
            },
            initWithETCFile: function (file) {
                cc.log(cc._LogInfos.Texture2D_initWithETCFile);
                return false;
            },
            initWithPVRFile: function (file) {
                cc.log(cc._LogInfos.Texture2D_initWithPVRFile);
                return false;
            },
            initWithPVRTCData: function (data, level, bpp, hasAlpha, length, pixelFormat) {
                cc.log(cc._LogInfos.Texture2D_initWithPVRTCData);
                return false;
            },
            setTexParameters: function (texParams, magFilter, wrapS, wrapT) {
                if(magFilter !== undefined)
                    texParams = {minFilter: texParams, magFilter: magFilter, wrapS: wrapS, wrapT: wrapT};
                if(texParams.wrapS === cc.REPEAT && texParams.wrapT === cc.REPEAT){
                    this._pattern = "repeat";
                    return;
                }
                if(texParams.wrapS === cc.REPEAT ){
                    this._pattern = "repeat-x";
                    return;
                }
                if(texParams.wrapT === cc.REPEAT){
                    this._pattern = "repeat-y";
                    return;
                }
                this._pattern = "";
            },
            setAntiAliasTexParameters: function () {
            },
            setAliasTexParameters: function () {
            },
            generateMipmap: function () {
            },
            stringForFormat: function () {
                return "";
            },
            bitsPerPixelForFormat: function (format) {
                return -1;
            },
            addLoadedEventListener: function (callback, target) {
                this.addEventListener("load", callback, target);
            },
            removeLoadedEventListener: function (target) {
                this.removeEventTarget("load", target);
            },
            _generateColorTexture: function(){},
            _generateTextureCacheForColor: function(){
                if (this.channelCache)
                    return this.channelCache;
                var textureCache = [
                    document.createElement("canvas"),
                    document.createElement("canvas"),
                    document.createElement("canvas"),
                    document.createElement("canvas")
                ];
                renderToCache(this._htmlElementObj, textureCache);
                return this.channelCache = textureCache;
            },
            _grayElementObj: null,
            _backupElement: null,
            _isGray: false,
            _switchToGray: function(toGray){
                if(!this._textureLoaded || this._isGray === toGray)
                    return;
                this._isGray = toGray;
                if(this._isGray){
                    this._backupElement = this._htmlElementObj;
                    if(!this._grayElementObj)
                        this._grayElementObj = cc.Texture2D._generateGrayTexture(this._htmlElementObj);
                    this._htmlElementObj = this._grayElementObj;
                } else {
                    if(this._backupElement !== null)
                        this._htmlElementObj = this._backupElement;
                }
            }
        };
        var renderToCache = function(image, cache){
            var w = image.width;
            var h = image.height;
            cache[0].width = w;
            cache[0].height = h;
            cache[1].width = w;
            cache[1].height = h;
            cache[2].width = w;
            cache[2].height = h;
            cache[3].width = w;
            cache[3].height = h;
            var cacheCtx = cache[3].getContext("2d");
            cacheCtx.drawImage(image, 0, 0);
            var pixels = cacheCtx.getImageData(0, 0, w, h).data;
            var ctx;
            for (var rgbI = 0; rgbI < 4; rgbI++) {
                ctx = cache[rgbI].getContext("2d");
                var to = ctx.getImageData(0, 0, w, h);
                var data = to.data;
                for (var i = 0; i < pixels.length; i += 4) {
                    data[i  ] = (rgbI === 0) ? pixels[i  ] : 0;
                    data[i + 1] = (rgbI === 1) ? pixels[i + 1] : 0;
                    data[i + 2] = (rgbI === 2) ? pixels[i + 2] : 0;
                    data[i + 3] = pixels[i + 3];
                }
                ctx.putImageData(to, 0, 0);
            }
            image.onload = null;
        };
        if(cc.sys._supportCanvasNewBlendModes){
            proto._generateColorTexture = function(r, g, b, rect, canvas){
                var onlyCanvas = false;
                if(canvas)
                    onlyCanvas = true;
                else
                    canvas = document.createElement("canvas");
                var textureImage = this._htmlElementObj;
                if(!rect)
                    rect = cc.rect(0, 0, textureImage.width, textureImage.height);
                canvas.width = rect.width;
                canvas.height = rect.height;
                var context = canvas.getContext("2d");
                context.globalCompositeOperation = "source-over";
                context.fillStyle = "rgb(" + (r|0) + "," + (g|0) + "," + (b|0) + ")";
                context.fillRect(0, 0, rect.width, rect.height);
                context.globalCompositeOperation = "multiply";
                context.drawImage(
                    textureImage,
                    rect.x, rect.y, rect.width, rect.height,
                    0, 0, rect.width, rect.height
                );
                context.globalCompositeOperation = "destination-atop";
                context.drawImage(
                    textureImage,
                    rect.x, rect.y, rect.width, rect.height,
                    0, 0, rect.width, rect.height
                );
                if(onlyCanvas)
                    return canvas;
                var newTexture = new cc.Texture2D();
                newTexture.initWithElement(canvas);
                newTexture.handleLoadedTexture();
                return newTexture;
            };
        }else{
            proto._generateColorTexture = function(r, g, b, rect, canvas){
                var onlyCanvas = false;
                if(canvas)
                    onlyCanvas = true;
                else
                    canvas = document.createElement("canvas");
                var textureImage = this._htmlElementObj;
                if(!rect)
                    rect = cc.rect(0, 0, textureImage.width, textureImage.height);
                var x, y, w, h;
                x = rect.x; y = rect.y; w = rect.width; h = rect.height;
                if(!w || !h)
                    return;
                canvas.width = w;
                canvas.height = h;
                var context = canvas.getContext("2d");
                var tintedImgCache = cc.textureCache.getTextureColors(this);
                context.globalCompositeOperation = 'lighter';
                context.drawImage(
                    tintedImgCache[3],
                    x, y, w, h,
                    0, 0, w, h
                );
                if (r > 0) {
                    context.globalAlpha = r / 255;
                    context.drawImage(
                        tintedImgCache[0],
                        x, y, w, h,
                        0, 0, w, h
                    );
                }
                if (g > 0) {
                    context.globalAlpha = g / 255;
                    context.drawImage(
                        tintedImgCache[1],
                        x, y, w, h,
                        0, 0, w, h
                    );
                }
                if (b > 0) {
                    context.globalAlpha = b / 255;
                    context.drawImage(
                        tintedImgCache[2],
                        x, y, w, h,
                        0, 0, w, h
                    );
                }
                if(onlyCanvas)
                    return canvas;
                var newTexture = new cc.Texture2D();
                newTexture.initWithElement(canvas);
                newTexture.handleLoadedTexture();
                return newTexture;
            };
        }
        cc.Texture2D = cc.Class.extend(proto);
        cc.Texture2D._generateGrayTexture = function(texture, rect, renderCanvas){
            if (texture === null)
                return null;
            renderCanvas = renderCanvas || document.createElement("canvas");
            rect = rect || cc.rect(0, 0, texture.width, texture.height);
            renderCanvas.width = rect.width;
            renderCanvas.height = rect.height;
            var context = renderCanvas.getContext("2d");
            context.drawImage(texture, rect.x, rect.y, rect.width, rect.height, 0, 0, rect.width, rect.height);
            var imgData = context.getImageData(0, 0, rect.width, rect.height);
            var data = imgData.data;
            for (var i = 0, len = data.length; i < len; i += 4) {
                data[i] = data[i + 1] = data[i + 2] = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2];
            }
            context.putImageData(imgData, 0, 0);
            return renderCanvas;
        };
    } else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        cc.assert(cc.isFunction(cc._tmp.WebGLTexture2D), cc._LogInfos.MissingFile, "TexturesWebGL.js");
        cc._tmp.WebGLTexture2D();
        delete cc._tmp.WebGLTexture2D;
    }
    cc.EventHelper.prototype.apply(cc.Texture2D.prototype);
    cc.assert(cc.isFunction(cc._tmp.PrototypeTexture2D), cc._LogInfos.MissingFile, "TexturesPropertyDefine.js");
    cc._tmp.PrototypeTexture2D();
    delete cc._tmp.PrototypeTexture2D;
});
cc.textureCache = {
    _textures: {},
    _textureColorsCache: {},
    _textureKeySeq: (0 | Math.random() * 1000),
    _loadedTexturesBefore: {},
    _initializingRenderer: function () {
        var selPath;
        var locLoadedTexturesBefore = this._loadedTexturesBefore, locTextures = this._textures;
        for (selPath in locLoadedTexturesBefore) {
            var tex2d = locLoadedTexturesBefore[selPath];
            tex2d.handleLoadedTexture();
            locTextures[selPath] = tex2d;
        }
        this._loadedTexturesBefore = {};
    },
    addPVRTCImage: function (filename) {
        cc.log(cc._LogInfos.textureCache_addPVRTCImage);
    },
    addETCImage: function (filename) {
        cc.log(cc._LogInfos.textureCache_addETCImage);
    },
    description: function () {
        return "<TextureCache | Number of textures = " + this._textures.length + ">";
    },
    textureForKey: function (textureKeyName) {
        cc.log(cc._LogInfos.textureCache_textureForKey);
        return this.getTextureForKey(textureKeyName);
    },
    getTextureForKey: function(textureKeyName){
        return this._textures[textureKeyName] || this._textures[cc.loader._getAliase(textureKeyName)];
    },
    getKeyByTexture: function (texture) {
        for (var key in this._textures) {
            if (this._textures[key] === texture) {
                return key;
            }
        }
        return null;
    },
    _generalTextureKey: function (id) {
        return "_textureKey_" + id;
    },
    getTextureColors: function (texture) {
        var image = texture._htmlElementObj;
        var key = this.getKeyByTexture(image);
        if (!key) {
            if (image instanceof HTMLImageElement)
                key = image.src;
            else
                key = this._generalTextureKey(texture.__instanceId);
        }
        if (!this._textureColorsCache[key])
            this._textureColorsCache[key] = texture._generateTextureCacheForColor();
        return this._textureColorsCache[key];
    },
    addPVRImage: function (path) {
        cc.log(cc._LogInfos.textureCache_addPVRImage);
    },
    removeAllTextures: function () {
        var locTextures = this._textures;
        for (var selKey in locTextures) {
            if (locTextures[selKey])
                locTextures[selKey].releaseTexture();
        }
        this._textures = {};
    },
    removeTexture: function (texture) {
        if (!texture)
            return;
        var locTextures = this._textures;
        for (var selKey in locTextures) {
            if (locTextures[selKey] === texture) {
                locTextures[selKey].releaseTexture();
                delete(locTextures[selKey]);
            }
        }
    },
    removeTextureForKey: function (textureKeyName) {
        if (textureKeyName == null)
            return;
        if (this._textures[textureKeyName])
            delete(this._textures[textureKeyName]);
    },
    cacheImage: function (path, texture) {
        if (texture instanceof  cc.Texture2D) {
            this._textures[path] = texture;
            return;
        }
        var texture2d = new cc.Texture2D();
        texture2d.initWithElement(texture);
        texture2d.handleLoadedTexture();
        this._textures[path] = texture2d;
    },
    addUIImage: function (image, key) {
        cc.assert(image, cc._LogInfos.textureCache_addUIImage_2);
        if (key) {
            if (this._textures[key])
                return this._textures[key];
        }
        var texture = new cc.Texture2D();
        texture.initWithImage(image);
        if (key != null)
            this._textures[key] = texture;
        else
            cc.log(cc._LogInfos.textureCache_addUIImage);
        return texture;
    },
    dumpCachedTextureInfo: function () {
        var count = 0;
        var totalBytes = 0, locTextures = this._textures;
        for (var key in locTextures) {
            var selTexture = locTextures[key];
            count++;
            if (selTexture.getHtmlElementObj() instanceof  HTMLImageElement)
                cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo, key, selTexture.getHtmlElementObj().src, selTexture.pixelsWidth, selTexture.pixelsHeight);
            else {
                cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selTexture.pixelsWidth, selTexture.pixelsHeight);
            }
            totalBytes += selTexture.pixelsWidth * selTexture.pixelsHeight * 4;
        }
        var locTextureColorsCache = this._textureColorsCache;
        for (key in locTextureColorsCache) {
            var selCanvasColorsArr = locTextureColorsCache[key];
            for (var selCanvasKey in selCanvasColorsArr) {
                var selCanvas = selCanvasColorsArr[selCanvasKey];
                count++;
                cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selCanvas.width, selCanvas.height);
                totalBytes += selCanvas.width * selCanvas.height * 4;
            }
        }
        cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_3, count, totalBytes / 1024, (totalBytes / (1024.0 * 1024.0)).toFixed(2));
    },
    _clear: function () {
        this._textures = {};
        this._textureColorsCache = {};
        this._textureKeySeq = (0 | Math.random() * 1000);
        this._loadedTexturesBefore = {};
    }
};
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
        var _p = cc.textureCache;
        _p.handleLoadedTexture = function (url) {
            var locTexs = this._textures;
            var tex = locTexs[url];
            if (!tex) {
                tex = locTexs[url] = new cc.Texture2D();
                tex.url = url;
            }
            tex.handleLoadedTexture();
        };
        _p.addImage = function (url, cb, target) {
            cc.assert(url, cc._LogInfos.Texture2D_addImage);
            var locTexs = this._textures;
            var tex = locTexs[url] || locTexs[cc.loader._getAliase(url)];
            if (tex) {
                if(tex.isLoaded()) {
                    cb && cb.call(target, tex);
                    return tex;
                }
                else
                {
                    tex.addEventListener("load", function(){
                        cb && cb.call(target, tex);
                    }, target);
                    return tex;
                }
            }
            tex = locTexs[url] = new cc.Texture2D();
            tex.url = url;
            var basePath = cc.loader.getBasePath ? cc.loader.getBasePath() : cc.loader.resPath;
            cc.loader.loadImg(cc.path.join(basePath || "", url), function (err, img) {
                if (err)
                    return cb && cb.call(target, err);
                if (!cc.loader.cache[url]) {
                    cc.loader.cache[url] = img;
                }
                cc.textureCache.handleLoadedTexture(url);
                var texResult = locTexs[url];
                cb && cb.call(target, texResult);
            });
            return tex;
        };
        _p.addImageAsync = _p.addImage;
        _p = null;
    } else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        cc.assert(cc.isFunction(cc._tmp.WebGLTextureCache), cc._LogInfos.MissingFile, "TexturesWebGL.js");
        cc._tmp.WebGLTextureCache();
        delete cc._tmp.WebGLTextureCache;
    }
});
cc.Scene = cc.Node.extend({
    _className:"Scene",
    ctor:function () {
        cc.Node.prototype.ctor.call(this);
        this._ignoreAnchorPointForPosition = true;
        this.setAnchorPoint(0.5, 0.5);
        this.setContentSize(cc.director.getWinSize());
    }
});
cc.Scene.create = function () {
    return new cc.Scene();
};
cc.LoaderScene = cc.Scene.extend({
    _interval : null,
    _label : null,
    _className:"LoaderScene",
    cb: null,
    target: null,
    init : function(){
        var self = this;
        var logoWidth = 160;
        var logoHeight = 200;
        var bgLayer = self._bgLayer = new cc.LayerColor(cc.color(32, 32, 32, 255));
        self.addChild(bgLayer, 0);
        var fontSize = 24, lblHeight =  -logoHeight / 2 + 100;
        if(cc._loaderImage){
            cc.loader.loadImg(cc._loaderImage, {isCrossOrigin : false }, function(err, img){
                logoWidth = img.width;
                logoHeight = img.height;
                self._initStage(img, cc.visibleRect.center);
            });
            fontSize = 14;
            lblHeight = -logoHeight / 2 - 10;
        }
        var label = self._label = new cc.LabelTTF("Loading... 0%", "Arial", fontSize);
        label.setPosition(cc.pAdd(cc.visibleRect.center, cc.p(0, lblHeight)));
        label.setColor(cc.color(180, 180, 180));
        bgLayer.addChild(this._label, 10);
        return true;
    },
    _initStage: function (img, centerPos) {
        var self = this;
        var texture2d = self._texture2d = new cc.Texture2D();
        texture2d.initWithElement(img);
        texture2d.handleLoadedTexture();
        var logo = self._logo = new cc.Sprite(texture2d);
        logo.setScale(cc.contentScaleFactor());
        logo.x = centerPos.x;
        logo.y = centerPos.y;
        self._bgLayer.addChild(logo, 10);
    },
    onEnter: function () {
        var self = this;
        cc.Node.prototype.onEnter.call(self);
        self.schedule(self._startLoading, 0.3);
    },
    onExit: function () {
        cc.Node.prototype.onExit.call(this);
        var tmpStr = "Loading... 0%";
        this._label.setString(tmpStr);
    },
    initWithResources: function (resources, cb, target) {
        if(cc.isString(resources))
            resources = [resources];
        this.resources = resources || [];
        this.cb = cb;
        this.target = target;
    },
    _startLoading: function () {
        var self = this;
        self.unschedule(self._startLoading);
        var res = self.resources;
        cc.loader.load(res,
            function (result, count, loadedCount) {
                var percent = (loadedCount / count * 100) | 0;
                percent = Math.min(percent, 100);
                self._label.setString("Loading... " + percent + "%");
            }, function () {
                if (self.cb)
                    self.cb.call(self.target);
            });
    },
    _updateTransform: function(){
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._bgLayer._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._label._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._logo._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    }
});
cc.LoaderScene.preload = function(resources, cb, target){
    var _cc = cc;
    if(!_cc.loaderScene) {
        _cc.loaderScene = new cc.LoaderScene();
        _cc.loaderScene.init();
        cc.eventManager.addCustomListener(cc.Director.EVENT_PROJECTION_CHANGED, function(){
            _cc.loaderScene._updateTransform();
        });
    }
    _cc.loaderScene.initWithResources(resources, cb, target);
    cc.director.runScene(_cc.loaderScene);
    return _cc.loaderScene;
};
cc.Layer = cc.Node.extend({
    _className: "Layer",
    ctor: function () {
        cc.Node.prototype.ctor.call(this);
        this._ignoreAnchorPointForPosition = true;
        this.setAnchorPoint(0.5, 0.5);
        this.setContentSize(cc.winSize);
    },
    init: function(){
        var _t = this;
        _t._ignoreAnchorPointForPosition = true;
        _t.setAnchorPoint(0.5, 0.5);
        _t.setContentSize(cc.winSize);
        _t._cascadeColorEnabled = false;
        _t._cascadeOpacityEnabled = false;
        return true;
    },
    bake: function(){
        this._renderCmd.bake();
    },
    unbake: function(){
        this._renderCmd.unbake();
    },
    isBaked: function(){
        return this._renderCmd._isBaked;
    },
    addChild: function(child, localZOrder, tag){
        cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
        this._renderCmd._bakeForAddChild(child);
    },
    _createRenderCmd: function(){
        if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.Layer.CanvasRenderCmd(this);
        else
            return new cc.Layer.WebGLRenderCmd(this);
    }
});
cc.Layer.create = function () {
    return new cc.Layer();
};
cc.LayerColor = cc.Layer.extend({
    _blendFunc: null,
    _className: "LayerColor",
    getBlendFunc: function () {
        return this._blendFunc;
    },
    changeWidthAndHeight: function (w, h) {
        this.width = w;
        this.height = h;
    },
    changeWidth: function (w) {
        this.width = w;
    },
    changeHeight: function (h) {
        this.height = h;
    },
    setOpacityModifyRGB: function (value) {
    },
    isOpacityModifyRGB: function () {
        return false;
    },
    ctor: function(color, width, height){
        cc.Layer.prototype.ctor.call(this);
        this._blendFunc = cc.BlendFunc._alphaNonPremultiplied();
        cc.LayerColor.prototype.init.call(this, color, width, height);
    },
    init: function (color, width, height) {
        var winSize = cc.director.getWinSize();
        color = color || cc.color(0, 0, 0, 255);
        width = width === undefined ? winSize.width : width;
        height = height === undefined ? winSize.height : height;
        var locRealColor = this._realColor;
        locRealColor.r = color.r;
        locRealColor.g = color.g;
        locRealColor.b = color.b;
        this._realOpacity = color.a;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty);
        cc.LayerColor.prototype.setContentSize.call(this, width, height);
        return true;
    },
    setBlendFunc: function (src, dst) {
        var locBlendFunc = this._blendFunc;
        if (dst === undefined) {
            locBlendFunc.src = src.src;
            locBlendFunc.dst = src.dst;
        } else {
            locBlendFunc.src = src;
            locBlendFunc.dst = dst;
        }
        this._renderCmd.updateBlendFunc(locBlendFunc);
    },
    _createRenderCmd: function(){
        if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.LayerColor.CanvasRenderCmd(this);
        else
            return new cc.LayerColor.WebGLRenderCmd(this);
    }
});
cc.LayerColor.create = function (color, width, height) {
    return new cc.LayerColor(color, width, height);
};
(function(){
    var proto = cc.LayerColor.prototype;
    cc.defineGetterSetter(proto, "width", proto._getWidth, proto._setWidth);
    cc.defineGetterSetter(proto, "height", proto._getHeight, proto._setHeight);
})();
cc.LayerGradient = cc.LayerColor.extend({
    _endColor: null,
    _startOpacity: 255,
    _endOpacity: 255,
    _alongVector: null,
    _compressedInterpolation: false,
    _className: "LayerGradient",
    _colorStops: [],
    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);
    },
    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;
        var locEndColor = _t._endColor;
        _t._startOpacity = start.a;
        locEndColor.r = end.r;
        locEndColor.g = end.g;
        locEndColor.b = end.b;
        _t._endOpacity = end.a;
        _t._alongVector = v;
        _t._compressedInterpolation = true;
        cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255));
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty|cc.Node._dirtyFlags.gradientDirty);
        return true;
    },
    setContentSize: function (size, height) {
        cc.LayerColor.prototype.setContentSize.call(this, size, height);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
    },
    _setWidth: function (width) {
        cc.LayerColor.prototype._setWidth.call(this, width);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
    },
    _setHeight: function (height) {
        cc.LayerColor.prototype._setHeight.call(this, height);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
    },
    getStartColor: function () {
        return cc.color(this._realColor);
    },
    setStartColor: function (color) {
        this.color = color;
        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;
        }
    },
    setEndColor: function (color) {
        var locColor = this._endColor;
        locColor.r = color.r;
        locColor.g = color.g;
        locColor.b = color.b;
        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);
    },
    getEndColor: function () {
        return cc.color(this._endColor);
    },
    setStartOpacity: function (o) {
        this._startOpacity = o;
        var stops = this._colorStops;
        if(stops && stops.length > 0)
            stops[0].color.a = o;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    },
    getStartOpacity: function () {
        return this._startOpacity;
    },
    setEndOpacity: function (o) {
        this._endOpacity = o;
        var stops = this._colorStops;
        if(stops && stops.length > 0)
            stops[stops.length -1].color.a = o;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    },
    getEndOpacity: function () {
        return this._endOpacity;
    },
    setVector: function (Var) {
        this._alongVector.x = Var.x;
        this._alongVector.y = Var.y;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
    },
    getVector: function () {
        return cc.p(this._alongVector.x, this._alongVector.y);
    },
    isCompressedInterpolation: function () {
        return this._compressedInterpolation;
    },
    setCompressedInterpolation: function (compress) {
        this._compressedInterpolation = compress;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
    },
    getColorStops: function(){
        return this._colorStops;
    },
    setColorStops: function(colorStops){
        this._colorStops = colorStops;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty|cc.Node._dirtyFlags.opacityDirty|cc.Node._dirtyFlags.gradientDirty);
    },
    _createRenderCmd: function(){
        if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.LayerGradient.CanvasRenderCmd(this);
        else
            return new cc.LayerGradient.WebGLRenderCmd(this);
    }
});
cc.LayerGradient.create = function (start, end, v, stops) {
    return new cc.LayerGradient(start, end, v, stops);
};
(function(){
    var proto = cc.LayerGradient.prototype;
    proto.startColor;
    cc.defineGetterSetter(proto, "startColor", proto.getStartColor, proto.setStartColor);
    proto.endColor;
    cc.defineGetterSetter(proto, "endColor", proto.getEndColor, proto.setEndColor);
    proto.startOpacity;
    cc.defineGetterSetter(proto, "startOpacity", proto.getStartOpacity, proto.setStartOpacity);
    proto.endOpacity;
    cc.defineGetterSetter(proto, "endOpacity", proto.getEndOpacity, proto.setEndOpacity);
    proto.vector;
    cc.defineGetterSetter(proto, "vector", proto.getVector, proto.setVector);
    proto.colorStops;
    cc.defineGetterSetter(proto, "colorStops", proto.getColorStops, proto.setColorStops);
})();
cc.LayerMultiplex = cc.Layer.extend({
    _enabledLayer: 0,
    _layers: null,
    _className: "LayerMultiplex",
    ctor: function (layers) {
        cc.Layer.prototype.ctor.call(this);
        if (layers instanceof Array)
            cc.LayerMultiplex.prototype.initWithLayers.call(this, layers);
        else
            cc.LayerMultiplex.prototype.initWithLayers.call(this, Array.prototype.slice.call(arguments));
    },
    initWithLayers: function (layers) {
        if ((layers.length > 0) && (layers[layers.length - 1] == null))
            cc.log(cc._LogInfos.LayerMultiplex_initWithLayers);
        this._layers = layers;
        this._enabledLayer = 0;
        this.addChild(this._layers[this._enabledLayer]);
        return true;
    },
    switchTo: function (n) {
        if (n >= this._layers.length) {
            cc.log(cc._LogInfos.LayerMultiplex_switchTo);
            return;
        }
        this.removeChild(this._layers[this._enabledLayer], true);
        this._enabledLayer = n;
        this.addChild(this._layers[n]);
    },
    switchToAndReleaseMe: function (n) {
        if (n >= this._layers.length) {
            cc.log(cc._LogInfos.LayerMultiplex_switchToAndReleaseMe);
            return;
        }
        this.removeChild(this._layers[this._enabledLayer], true);
        this._layers[this._enabledLayer] = null;
        this._enabledLayer = n;
        this.addChild(this._layers[n]);
    },
    addLayer: function (layer) {
        if (!layer) {
            cc.log(cc._LogInfos.LayerMultiplex_addLayer);
            return;
        }
        this._layers.push(layer);
    }
});
cc.LayerMultiplex.create = function () {
    return new cc.LayerMultiplex(Array.prototype.slice.call(arguments));
};
(function(){
    cc.Layer.CanvasRenderCmd = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._isBaked = false;
        this._bakeSprite = null;
        this._canUseDirtyRegion = true;
        this._updateCache = 2;
    };
    var proto = cc.Layer.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.Layer.CanvasRenderCmd;
    proto._setCacheDirty = function(child){
        if(child && this._updateCache === 0)
            this._updateCache = 2;
        if (this._cacheDirty === false) {
            this._cacheDirty = true;
            var cachedP = this._cachedParent;
            cachedP && cachedP !== this && cachedP._setNodeDirtyForCache && cachedP._setNodeDirtyForCache();
        }
    };
    proto.updateStatus = function () {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.orderDirty) {
            this._cacheDirty = true;
            if(this._updateCache === 0)
                this._updateCache = 2;
            this._dirtyFlag = locFlag & flags.orderDirty ^ locFlag;
        }
        cc.Node.RenderCmd.prototype.updateStatus.call(this);
    };
    proto._syncStatus = function (parentCmd) {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.orderDirty) {
            this._cacheDirty = true;
            if(this._updateCache === 0)
                this._updateCache = 2;
            this._dirtyFlag = locFlag & flags.orderDirty ^ locFlag;
        }
        cc.Node.RenderCmd.prototype._syncStatus.call(this, parentCmd);
    };
    proto.transform = function (parentCmd, recursive) {
        var wt = this._worldTransform;
        var a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty;
        cc.Node.CanvasRenderCmd.prototype.transform.call(this, parentCmd, recursive);
        if(( wt.a !== a || wt.b !== b || wt.c !== c || wt.d !== d ) && this._updateCache === 0)
            this._updateCache = 2;
    };
    proto.bake = function(){
        if (!this._isBaked) {
            this._needDraw = true;
            cc.renderer.childrenOrderDirty = true;
            this._isBaked = this._cacheDirty = true;
            if(this._updateCache === 0)
                this._updateCache = 2;
            var children = this._node._children;
            for(var i = 0, len = children.length; i < len; i++)
                children[i]._renderCmd._setCachedParent(this);
            if (!this._bakeSprite) {
                this._bakeSprite = new cc.BakeSprite();
                this._bakeSprite.setAnchorPoint(0,0);
            }
        }
    };
    proto.unbake = function(){
        if (this._isBaked) {
            cc.renderer.childrenOrderDirty = true;
            this._needDraw = false;
            this._isBaked = false;
            this._cacheDirty = true;
            if(this._updateCache === 0)
                this._updateCache = 2;
            var children = this._node._children;
            for(var i = 0, len = children.length; i < len; i++)
                children[i]._renderCmd._setCachedParent(null);
        }
    };
    proto.isBaked = function(){
        return this._isBaked;
    };
    proto.rendering = function(){
        if(this._cacheDirty){
            var node = this._node;
            var children = node._children, locBakeSprite = this._bakeSprite;
            this.transform(this.getParentRenderCmd(), true);
            var boundingBox = this._getBoundingBoxForBake();
            boundingBox.width = 0|(boundingBox.width+0.5);
            boundingBox.height = 0|(boundingBox.height+0.5);
            var bakeContext = locBakeSprite.getCacheContext();
            var ctx = bakeContext.getContext();
            locBakeSprite.setPosition(boundingBox.x, boundingBox.y);
            if(this._updateCache > 0){
                locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height);
                bakeContext.setOffset(0 - boundingBox.x, ctx.canvas.height - boundingBox.height + boundingBox.y );
                node.sortAllChildren();
                cc.renderer._turnToCacheMode(this.__instanceId);
                for (var i = 0, len = children.length; i < len; i++) {
                    children[i].visit(this);
                }
                cc.renderer._renderingToCacheCanvas(bakeContext, this.__instanceId);
                locBakeSprite.transform();
                this._updateCache--;
            }
            this._cacheDirty = false;
        }
    };
    proto.visit = function(parentCmd){
        if(!this._isBaked){
            this.originVisit(parentCmd);
            return;
        }
        var node = this._node, children = node._children;
        var len = children.length;
        if (!node._visible || len === 0)
            return;
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this);
        this._bakeSprite.visit(this);
        this._dirtyFlag = 0;
    };
    proto._bakeForAddChild = function(child){
        if(child._parent === this._node && this._isBaked)
            child._renderCmd._setCachedParent(this);
    };
    proto._getBoundingBoxForBake = function(){
        var rect = null, node = this._node;
        if (!node._children || node._children.length === 0)
            return cc.rect(0, 0, 10, 10);
        var trans = node.getNodeToWorldTransform();
        var locChildren = node._children;
        for (var i = 0, len = locChildren.length; i < len; i++) {
            var child = locChildren[i];
            if (child && child._visible) {
                if(rect){
                    var childRect = child._getBoundingBoxToCurrentNode(trans);
                    if (childRect)
                        rect = cc.rectUnion(rect, childRect);
                }else{
                    rect = child._getBoundingBoxToCurrentNode(trans);
                }
            }
        }
        return rect;
    };
})();
(function(){
    cc.LayerColor.CanvasRenderCmd = function(renderable){
        cc.Layer.CanvasRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._blendFuncStr = "source-over";
        this._bakeRenderCmd = new cc.CustomRenderCmd(this, this._bakeRendering);
    };
    var proto = cc.LayerColor.CanvasRenderCmd.prototype = Object.create(cc.Layer.CanvasRenderCmd.prototype);
    proto.constructor = cc.LayerColor.CanvasRenderCmd;
    proto.unbake = function(){
        cc.Layer.CanvasRenderCmd.prototype.unbake.call(this);
        this._needDraw = true;
    };
    proto.rendering = function (ctx, scaleX, scaleY) {
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext(),
            node = this._node,
            curColor = this._displayedColor,
            opacity = this._displayedOpacity / 255,
            locWidth = node._contentSize.width,
            locHeight = node._contentSize.height;
        if (opacity === 0)
            return;
        wrapper.setCompositeOperation(this._blendFuncStr);
        wrapper.setGlobalAlpha(opacity);
        wrapper.setFillStyle("rgba(" + (0 | curColor.r) + "," + (0 | curColor.g) + ","
            + (0 | curColor.b) + ", 1)");
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        context.fillRect(0, 0, locWidth , -locHeight );
        cc.g_NumberOfDraws++;
    };
    proto.updateBlendFunc = function(blendFunc){
        this._blendFuncStr = cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc(blendFunc);
    };
    proto._updateSquareVertices =
    proto._updateSquareVerticesWidth =
    proto._updateSquareVerticesHeight = function(){};
    proto._bakeRendering = function(){
        if(this._cacheDirty){
            var node = this._node;
            var locBakeSprite = this._bakeSprite, children = node._children;
            var len = children.length, i;
            this.transform(this.getParentRenderCmd(), true);
            var boundingBox = this._getBoundingBoxForBake();
            boundingBox.width = 0|(boundingBox.width+0.5);
            boundingBox.height = 0|(boundingBox.height+0.5);
            var bakeContext = locBakeSprite.getCacheContext();
            var ctx = bakeContext.getContext();
            locBakeSprite.setPosition(boundingBox.x, boundingBox.y);
            if(this._updateCache > 0) {
                ctx.fillStyle = bakeContext._currentFillStyle;
                locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height);
                bakeContext.setOffset(0 - boundingBox.x, ctx.canvas.height - boundingBox.height + boundingBox.y );
                var child;
                cc.renderer._turnToCacheMode(this.__instanceId);
                if (len > 0) {
                    node.sortAllChildren();
                    for (i = 0; i < len; i++) {
                        child = children[i];
                        if (child._localZOrder < 0)
                            child._renderCmd.visit(this);
                        else
                            break;
                    }
                    cc.renderer.pushRenderCommand(this);
                    for (; i < len; i++) {
                        children[i]._renderCmd.visit(this);
                    }
                } else
                    cc.renderer.pushRenderCommand(this);
                cc.renderer._renderingToCacheCanvas(bakeContext, this.__instanceId);
                locBakeSprite.transform();
                this._updateCache--;
            }
            this._cacheDirty = false;
        }
    };
    proto.visit = function(parentCmd){
        if(!this._isBaked){
            this.originVisit();
            return;
        }
        var node = this._node;
        if (!node._visible)
            return;
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this._bakeRenderCmd);
        this._bakeSprite._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._bakeSprite.visit(this);
        this._dirtyFlag = 0;
    };
    proto._getBoundingBoxForBake = function(){
        var node = this._node;
        var rect = cc.rect(0, 0, node._contentSize.width, node._contentSize.height);
        var trans = node.getNodeToWorldTransform();
        rect = cc.rectApplyAffineTransform(rect, node.getNodeToWorldTransform());
        if (!node._children || node._children.length === 0)
            return rect;
        var locChildren = node._children;
        for (var i = 0; i < locChildren.length; i++) {
            var child = locChildren[i];
            if (child && child._visible) {
                var childRect = child._getBoundingBoxToCurrentNode(trans);
                rect = cc.rectUnion(rect, childRect);
            }
        }
        return rect;
    };
})();
(function(){
    cc.LayerGradient.CanvasRenderCmd = function(renderable){
        cc.LayerColor.CanvasRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._startPoint = cc.p(0, 0);
        this._endPoint = cc.p(0, 0);
        this._startStopStr = null;
        this._endStopStr = null;
    };
    var proto = cc.LayerGradient.CanvasRenderCmd.prototype = Object.create(cc.LayerColor.CanvasRenderCmd.prototype);
    proto.constructor = cc.LayerGradient.CanvasRenderCmd;
    proto.rendering = function (ctx, scaleX, scaleY) {
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext(),
            node = this._node,
            opacity = this._displayedOpacity / 255;
        if (opacity === 0)
            return;
        var locWidth = node._contentSize.width, locHeight = node._contentSize.height;
        wrapper.setCompositeOperation(this._blendFuncStr);
        wrapper.setGlobalAlpha(opacity);
        var gradient = context.createLinearGradient(this._startPoint.x, this._startPoint.y, this._endPoint.x, this._endPoint.y);
        if(node._colorStops){
             for(var i=0; i < node._colorStops.length; i++) {
                 var stop = node._colorStops[i];
                 gradient.addColorStop(stop.p, this._colorStopsStr[i]);
             }
        }else{
            gradient.addColorStop(0, this._startStopStr);
            gradient.addColorStop(1, this._endStopStr);
        }
        wrapper.setFillStyle(gradient);
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        context.fillRect(0, 0, locWidth , -locHeight );
        cc.g_NumberOfDraws++;
    };
    proto.updateStatus = function () {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.gradientDirty) {
            this._dirtyFlag |= flags.colorDirty;
            this._dirtyFlag = locFlag & flags.gradientDirty ^ locFlag;
        }
        cc.Node.RenderCmd.prototype.updateStatus.call(this);
    };
    proto._syncStatus = function (parentCmd) {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.gradientDirty) {
            this._dirtyFlag |= flags.colorDirty;
            this._dirtyFlag = locFlag & flags.gradientDirty ^ locFlag;
        }
        cc.Node.RenderCmd.prototype._syncStatus.call(this, parentCmd);
    };
    proto._updateColor = function() {
        var node = this._node;
        var contentSize = node._contentSize;
        var tWidth = contentSize.width * 0.5, tHeight = contentSize.height * 0.5;
        var angle = cc.pAngleSigned(cc.p(0, -1), node._alongVector);
        var p1 = cc.pRotateByAngle(cc.p(0, -1), cc.p(0,0), angle);
        var factor = Math.min(Math.abs(1 / p1.x), Math.abs(1/ p1.y));
        this._startPoint.x = tWidth * (-p1.x * factor) + tWidth;
        this._startPoint.y = tHeight * (p1.y * factor) - tHeight;
        this._endPoint.x = tWidth * (p1.x * factor) + tWidth;
        this._endPoint.y = tHeight * (-p1.y * factor) - tHeight;
        var locStartColor = this._displayedColor, locEndColor = node._endColor;
        var startOpacity = node._startOpacity/255, endOpacity = node._endOpacity/255;
        this._startStopStr = "rgba(" + Math.round(locStartColor.r) + "," + Math.round(locStartColor.g) + ","
            + Math.round(locStartColor.b) + "," + startOpacity.toFixed(4) + ")";
        this._endStopStr = "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + ","
            + Math.round(locEndColor.b) + "," + endOpacity.toFixed(4) + ")";
        if( node._colorStops){
            this._startOpacity = 0;
            this._endOpacity = 0;
            this._colorStopsStr = [];
            for(var i =0; i < node._colorStops.length; i++){
                var stopColor = node._colorStops[i].color;
                var stopOpacity = stopColor.a == null ? 1 : stopColor.a / 255;
                this._colorStopsStr.push("rgba(" + Math.round(stopColor.r) + "," + Math.round(stopColor.g) + ","
                    + Math.round(stopColor.b) + "," + stopOpacity.toFixed(4) + ")");
            }
        }
    };
})();
cc._tmp.PrototypeSprite = function () {
    var _p = cc.Sprite.prototype;
    cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB, _p.setOpacityModifyRGB);
    cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
    cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
    _p.dirty;
    _p.flippedX;
    cc.defineGetterSetter(_p, "flippedX", _p.isFlippedX, _p.setFlippedX);
    _p.flippedY;
    cc.defineGetterSetter(_p, "flippedY", _p.isFlippedY, _p.setFlippedY);
    _p.offsetX;
    cc.defineGetterSetter(_p, "offsetX", _p._getOffsetX);
    _p.offsetY;
    cc.defineGetterSetter(_p, "offsetY", _p._getOffsetY);
    _p.atlasIndex;
    _p.texture;
    cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
    _p.textureRectRotated;
    cc.defineGetterSetter(_p, "textureRectRotated", _p.isTextureRectRotated);
    _p.textureAtlas;
    _p.batchNode;
    cc.defineGetterSetter(_p, "batchNode", _p.getBatchNode, _p.setBatchNode);
    _p.quad;
    cc.defineGetterSetter(_p, "quad", _p.getQuad);
};
cc.Sprite = cc.Node.extend({
    dirty:false,
    atlasIndex:0,
    textureAtlas:null,
    _batchNode:null,
    _recursiveDirty:null,
    _hasChildren:null,
    _shouldBeHidden:false,
    _transformToBatch:null,
    _blendFunc:null,
    _texture:null,
    _rect:null,
    _rectRotated:false,
    _offsetPosition:null,
    _unflippedOffsetPositionFromCenter:null,
    _opacityModifyRGB:false,
    _flippedX:false,
    _flippedY:false,
    _textureLoaded:false,
    _className:"Sprite",
    ctor: function (fileName, rect, rotated) {
        var self = this;
        cc.Node.prototype.ctor.call(self);
        this.setAnchorPoint(0.5, 0.5);
        self._loader = new cc.Sprite.LoadManager();
        self._shouldBeHidden = false;
        self._offsetPosition = cc.p(0, 0);
        self._unflippedOffsetPositionFromCenter = cc.p(0, 0);
        self._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
        self._rect = cc.rect(0, 0, 0, 0);
        self._softInit(fileName, rect, rotated);
    },
    textureLoaded:function(){
        return this._textureLoaded;
    },
    addLoadedEventListener:function(callback, target){
        this.addEventListener("load", callback, target);
    },
    isDirty:function () {
        return this.dirty;
    },
    setDirty:function (bDirty) {
        this.dirty = bDirty;
    },
    isTextureRectRotated:function () {
        return this._rectRotated;
    },
    getAtlasIndex:function () {
        return this.atlasIndex;
    },
    setAtlasIndex:function (atlasIndex) {
        this.atlasIndex = atlasIndex;
    },
    getTextureRect:function () {
        return cc.rect(this._rect);
    },
    getTextureAtlas:function () {
        return this.textureAtlas;
    },
    setTextureAtlas:function (textureAtlas) {
        this.textureAtlas = textureAtlas;
    },
    getOffsetPosition:function () {
        return cc.p(this._offsetPosition);
    },
    _getOffsetX: function () {
        return this._offsetPosition.x;
    },
    _getOffsetY: function () {
        return this._offsetPosition.y;
    },
    getBlendFunc:function () {
        return this._blendFunc;
    },
    initWithSpriteFrame:function (spriteFrame) {
        cc.assert(spriteFrame, cc._LogInfos.Sprite_initWithSpriteFrame);
        return this.setSpriteFrame(spriteFrame);
    },
    initWithSpriteFrameName:function (spriteFrameName) {
        cc.assert(spriteFrameName, cc._LogInfos.Sprite_initWithSpriteFrameName);
        var frame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
        cc.assert(frame, spriteFrameName + cc._LogInfos.Sprite_initWithSpriteFrameName1);
        return this.initWithSpriteFrame(frame);
    },
    useBatchNode:function (batchNode) {
        this.textureAtlas = batchNode.getTextureAtlas();
        this._batchNode = batchNode;
    },
    setVertexRect:function (rect) {
        var locRect = this._rect;
        locRect.x = rect.x;
        locRect.y = rect.y;
        locRect.width = rect.width;
        locRect.height = rect.height;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    sortAllChildren:function () {
        if (this._reorderChildDirty) {
            var _children = this._children;
            cc.Node.prototype.sortAllChildren.call(this);
            if (this._batchNode) {
                this._arrayMakeObjectsPerformSelector(_children, cc.Node._stateCallbackType.sortAllChildren);
            }
            this._reorderChildDirty = false;
        }
    },
    reorderChild:function (child, zOrder) {
        cc.assert(child, cc._LogInfos.Sprite_reorderChild_2);
        if(this._children.indexOf(child) === -1){
            cc.log(cc._LogInfos.Sprite_reorderChild);
            return;
        }
        if (zOrder === child.zIndex)
            return;
        if (this._batchNode && !this._reorderChildDirty) {
            this._setReorderChildDirtyRecursively();
            this._batchNode.reorderBatch(true);
        }
        cc.Node.prototype.reorderChild.call(this, child, zOrder);
    },
    removeChild:function (child, cleanup) {
        if (this._batchNode)
            this._batchNode.removeSpriteFromAtlas(child);
        cc.Node.prototype.removeChild.call(this, child, cleanup);
    },
    setVisible:function (visible) {
        cc.Node.prototype.setVisible.call(this, visible);
        this._renderCmd.setDirtyRecursively(true);
    },
    removeAllChildren:function (cleanup) {
        var locChildren = this._children, locBatchNode = this._batchNode;
        if (locBatchNode && locChildren != null) {
            for (var i = 0, len = locChildren.length; i < len; i++)
                locBatchNode.removeSpriteFromAtlas(locChildren[i]);
        }
        cc.Node.prototype.removeAllChildren.call(this, cleanup);
        this._hasChildren = false;
    },
    ignoreAnchorPointForPosition:function (relative) {
        if(this._batchNode){
            cc.log(cc._LogInfos.Sprite_ignoreAnchorPointForPosition);
            return;
        }
        cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative);
    },
    setFlippedX:function (flippedX) {
        if (this._flippedX !== flippedX) {
            this._flippedX = flippedX;
            this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
            this.setNodeDirty(true);
        }
    },
    setFlippedY:function (flippedY) {
        if (this._flippedY !== flippedY) {
            this._flippedY = flippedY;
            this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
            this.setNodeDirty(true);
        }
    },
    isFlippedX:function () {
        return this._flippedX;
    },
    isFlippedY:function () {
        return this._flippedY;
    },
    setOpacityModifyRGB: function (modify) {
        if (this._opacityModifyRGB !== modify) {
            this._opacityModifyRGB = modify;
            this._renderCmd._setColorDirty();
        }
    },
    isOpacityModifyRGB:function () {
        return this._opacityModifyRGB;
    },
    setDisplayFrameWithAnimationName:function (animationName, frameIndex) {
        cc.assert(animationName, cc._LogInfos.Sprite_setDisplayFrameWithAnimationName_3);
        var cache = cc.animationCache.getAnimation(animationName);
        if(!cache){
            cc.log(cc._LogInfos.Sprite_setDisplayFrameWithAnimationName);
            return;
        }
        var animFrame = cache.getFrames()[frameIndex];
        if(!animFrame){
            cc.log(cc._LogInfos.Sprite_setDisplayFrameWithAnimationName_2);
            return;
        }
        this.setSpriteFrame(animFrame.getSpriteFrame());
    },
    getBatchNode:function () {
        return this._batchNode;
    },
    _setReorderChildDirtyRecursively:function () {
        if (!this._reorderChildDirty) {
            this._reorderChildDirty = true;
            var pNode = this._parent;
            while (pNode && pNode !== this._batchNode) {
                pNode._setReorderChildDirtyRecursively();
                pNode = pNode.parent;
            }
        }
    },
    getTexture:function () {
        return this._texture;
    },
    _softInit: function (fileName, rect, rotated) {
        if (fileName === undefined)
            cc.Sprite.prototype.init.call(this);
        else if (cc.isString(fileName)) {
            if (fileName[0] === "#") {
                var frameName = fileName.substr(1, fileName.length - 1);
                var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
                if (spriteFrame)
                    this.initWithSpriteFrame(spriteFrame);
                else
                    cc.log("%s does not exist", fileName);
            } else {
                cc.Sprite.prototype.init.call(this, fileName, rect);
            }
        } else if (typeof fileName === "object") {
            if (fileName instanceof cc.Texture2D) {
                this.initWithTexture(fileName, rect, rotated);
            } else if (fileName instanceof cc.SpriteFrame) {
                this.initWithSpriteFrame(fileName);
            } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) {
                var texture2d = new cc.Texture2D();
                texture2d.initWithElement(fileName);
                texture2d.handleLoadedTexture();
                this.initWithTexture(texture2d);
            }
        }
    },
    getQuad:function () {
        return null;
    },
    setBlendFunc: function (src, dst) {
        var locBlendFunc = this._blendFunc;
        if (dst === undefined) {
            locBlendFunc.src = src.src;
            locBlendFunc.dst = src.dst;
        } else {
            locBlendFunc.src = src;
            locBlendFunc.dst = dst;
        }
        this._renderCmd.updateBlendFunc(locBlendFunc);
    },
    init: function () {
        var _t = this;
        if (arguments.length > 0)
            return _t.initWithFile(arguments[0], arguments[1]);
        cc.Node.prototype.init.call(_t);
        _t.dirty = _t._recursiveDirty = false;
        _t._blendFunc.src = cc.BLEND_SRC;
        _t._blendFunc.dst = cc.BLEND_DST;
        _t.texture = null;
        _t._flippedX = _t._flippedY = false;
        _t.anchorX = 0.5;
        _t.anchorY = 0.5;
        _t._offsetPosition.x = 0;
        _t._offsetPosition.y = 0;
        _t._hasChildren = false;
        _t.setTextureRect(cc.rect(0, 0, 0, 0), false, cc.size(0, 0));
        return true;
    },
    initWithFile:function (filename, rect) {
        cc.assert(filename, cc._LogInfos.Sprite_initWithFile);
        var tex = cc.textureCache.getTextureForKey(filename);
        if (!tex) {
            tex = cc.textureCache.addImage(filename);
        }
        if (!tex.isLoaded()) {
            this._loader.clear();
            this._loader.once(tex, function () {
                this.initWithFile(filename, rect);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        if (!rect) {
            var size = tex.getContentSize();
            rect = cc.rect(0, 0, size.width, size.height);
        }
        return this.initWithTexture(tex, rect);
    },
    initWithTexture: function (texture, rect, rotated, counterclockwise) {
        var _t = this;
        cc.assert(arguments.length !== 0, cc._LogInfos.CCSpriteBatchNode_initWithTexture);
        this._loader.clear();
        _t._textureLoaded = texture.isLoaded();
        if (!_t._textureLoaded) {
            this._loader.once(texture, function () {
                this.initWithTexture(texture, rect, rotated, counterclockwise);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        rotated = rotated || false;
        texture = this._renderCmd._handleTextureForRotatedTexture(texture, rect, rotated, counterclockwise);
        if (!cc.Node.prototype.init.call(_t))
            return false;
        _t._batchNode = null;
        _t._recursiveDirty = false;
        _t.dirty = false;
        _t._opacityModifyRGB = true;
        _t._blendFunc.src = cc.BLEND_SRC;
        _t._blendFunc.dst = cc.BLEND_DST;
        _t._flippedX = _t._flippedY = false;
        _t._offsetPosition.x = 0;
        _t._offsetPosition.y = 0;
        _t._hasChildren = false;
        _t._rectRotated = rotated;
        if (rect) {
            _t._rect.x = rect.x;
            _t._rect.y = rect.y;
            _t._rect.width = rect.width;
            _t._rect.height = rect.height;
        }
        if (!rect)
            rect = cc.rect(0, 0, texture.width, texture.height);
        this._renderCmd._checkTextureBoundary(texture, rect, rotated);
        _t.setTexture(texture);
        _t.setTextureRect(rect, rotated);
        _t.setBatchNode(null);
        return true;
    },
    setTextureRect: function (rect, rotated, untrimmedSize, needConvert) {
        var _t = this;
        _t._rectRotated = rotated || false;
        _t.setContentSize(untrimmedSize || rect);
        _t.setVertexRect(rect);
        _t._renderCmd._setTextureCoords(rect, needConvert);
        var relativeOffsetX = _t._unflippedOffsetPositionFromCenter.x, relativeOffsetY = _t._unflippedOffsetPositionFromCenter.y;
        if (_t._flippedX)
            relativeOffsetX = -relativeOffsetX;
        if (_t._flippedY)
            relativeOffsetY = -relativeOffsetY;
        var locRect = _t._rect;
        _t._offsetPosition.x = relativeOffsetX + (_t._contentSize.width - locRect.width) / 2;
        _t._offsetPosition.y = relativeOffsetY + (_t._contentSize.height - locRect.height) / 2;
    },
    addChild: function (child, localZOrder, tag) {
        cc.assert(child, cc._LogInfos.CCSpriteBatchNode_addChild_2);
        if (localZOrder == null)
            localZOrder = child._localZOrder;
        if (tag == null)
            tag = child.tag;
        if(this._renderCmd._setBatchNodeForAddChild(child)){
            cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
            this._hasChildren = true;
        }
    },
    setSpriteFrame: function (newFrame) {
        var _t = this;
        if(cc.isString(newFrame)){
            newFrame = cc.spriteFrameCache.getSpriteFrame(newFrame);
            cc.assert(newFrame, cc._LogInfos.Sprite_setSpriteFrame)
        }
        this._loader.clear();
        this.setNodeDirty(true);
        var pNewTexture = newFrame.getTexture();
        _t._textureLoaded = newFrame.textureLoaded();
        this._loader.clear();
        if (!_t._textureLoaded) {
            this._loader.once(pNewTexture, function () {
                this.setSpriteFrame(newFrame);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        var frameOffset = newFrame.getOffset();
        _t._unflippedOffsetPositionFromCenter.x = frameOffset.x;
        _t._unflippedOffsetPositionFromCenter.y = frameOffset.y;
        if (pNewTexture !== _t._texture) {
            this._renderCmd._setTexture(pNewTexture);
            _t.setColor(_t._realColor);
        }
        _t.setTextureRect(newFrame.getRect(), newFrame.isRotated(), newFrame.getOriginalSize());
    },
    setDisplayFrame: function(newFrame){
        cc.log(cc._LogInfos.Sprite_setDisplayFrame);
        this.setSpriteFrame(newFrame);
    },
    isFrameDisplayed: function(frame){
        return this._renderCmd.isFrameDisplayed(frame);
    },
    displayFrame: function () {
        return this.getSpriteFrame();
    },
    getSpriteFrame: function () {
        return new cc.SpriteFrame(this._texture,
            cc.rectPointsToPixels(this._rect),
            this._rectRotated,
            cc.pointPointsToPixels(this._unflippedOffsetPositionFromCenter),
            cc.sizePointsToPixels(this._contentSize));
    },
    setBatchNode:function (spriteBatchNode) {
        var _t = this;
        _t._batchNode = spriteBatchNode;
        if (!_t._batchNode) {
            _t.atlasIndex = cc.Sprite.INDEX_NOT_INITIALIZED;
            _t.textureAtlas = null;
            _t._recursiveDirty = false;
            _t.dirty = false;
        } else {
            _t._transformToBatch = cc.affineTransformIdentity();
            _t.textureAtlas = _t._batchNode.getTextureAtlas();
        }
    },
    setTexture: function (texture) {
        if(!texture)
            return this._renderCmd._setTexture(null);
        var isFileName = cc.isString(texture);
        if(isFileName)
            texture = cc.textureCache.addImage(texture);
        this._loader.clear();
        if (!texture._textureLoaded) {
            this._loader.once(texture, function () {
                this.setTexture(texture);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        this._renderCmd._setTexture(texture);
        if (isFileName)
            this._changeRectWithTexture(texture);
        this.setColor(this._realColor);
        this._textureLoaded = true;
    },
    _changeRectWithTexture: function(texture){
        var contentSize = texture._contentSize;
        var rect = cc.rect(
            0, 0,
            contentSize.width, contentSize.height
        );
        this.setTextureRect(rect);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.Sprite.CanvasRenderCmd(this);
        else
            return new cc.Sprite.WebGLRenderCmd(this);
    }
});
cc.Sprite.create = function (fileName, rect, rotated) {
    return new cc.Sprite(fileName, rect, rotated);
};
cc.Sprite.createWithTexture = cc.Sprite.create;
cc.Sprite.createWithSpriteFrameName = cc.Sprite.create;
cc.Sprite.createWithSpriteFrame = cc.Sprite.create;
cc.Sprite.INDEX_NOT_INITIALIZED = -1;
cc.EventHelper.prototype.apply(cc.Sprite.prototype);
cc.assert(cc.isFunction(cc._tmp.PrototypeSprite), cc._LogInfos.MissingFile, "SpritesPropertyDefine.js");
cc._tmp.PrototypeSprite();
delete cc._tmp.PrototypeSprite;
(function () {
    var manager = cc.Sprite.LoadManager = function () {
        this.list = [];
    };
    manager.prototype.add = function (source, callback, target) {
        if (!source || !source.addEventListener) return;
        source.addEventListener('load', callback, target);
        this.list.push({
            source: source,
            listener: callback,
            target: target
        });
    };
    manager.prototype.once = function (source, callback, target) {
        if (!source || !source.addEventListener) return;
        var tmpCallback = function (event) {
            source.removeEventListener('load', tmpCallback, target);
            callback.call(target, event);
        };
        source.addEventListener('load', tmpCallback, target);
        this.list.push({
            source: source,
            listener: tmpCallback,
            target: target
        });
    };
    manager.prototype.clear = function () {
        while (this.list.length > 0) {
            var item = this.list.pop();
            item.source.removeEventListener('load', item.listener, item.target);
        }
    };
})();
(function() {
    cc.Sprite.CanvasRenderCmd = function (renderable) {
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._textureCoord = {
            renderX: 0,
            renderY: 0,
            x: 0,
            y: 0,
            width: 0,
            height: 0,
            validRect: false
        };
        this._blendFuncStr = "source-over";
        this._colorized = false;
        this._canUseDirtyRegion = true;
        this._textureToRender = null;
    };
    var proto = cc.Sprite.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.Sprite.CanvasRenderCmd;
    proto.setDirtyRecursively = function (value) {};
    proto._setTexture = function (texture) {
        var node = this._node;
        if (node._texture !== texture) {
            if (texture) {
                node._textureLoaded = texture._textureLoaded;
            }else{
                node._textureLoaded = false;
            }
            node._texture = texture;
            this._updateColor();
        }
    };
    proto._setColorDirty = function () {
        this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty | cc.Node._dirtyFlags.opacityDirty);
    };
    proto.isFrameDisplayed = function (frame) {
        var node = this._node;
        if (frame.getTexture() !== node._texture)
            return false;
        return cc.rectEqualToRect(frame.getRect(), node._rect);
    };
    proto.updateBlendFunc = function (blendFunc) {
        this._blendFuncStr = cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc(blendFunc);
    };
    proto._setBatchNodeForAddChild = function (child) {
        return true;
    };
    proto._handleTextureForRotatedTexture = function (texture, rect, rotated, counterclockwise) {
        if (rotated && texture.isLoaded()) {
            var tempElement = texture.getHtmlElementObj();
            tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, rect, counterclockwise);
            var tempTexture = new cc.Texture2D();
            tempTexture.initWithElement(tempElement);
            tempTexture.handleLoadedTexture();
            texture = tempTexture;
            rect.x = rect.y = 0;
            this._node._rect = cc.rect(0, 0, rect.width, rect.height);
        }
        return texture;
    };
    proto._checkTextureBoundary = function (texture, rect, rotated) {
        if (texture && texture.url) {
            var _x = rect.x + rect.width, _y = rect.y + rect.height;
            if (_x > texture.width)
                cc.error(cc._LogInfos.RectWidth, texture.url);
            if (_y > texture.height)
                cc.error(cc._LogInfos.RectHeight, texture.url);
        }
    };
    proto.rendering = function (ctx, scaleX, scaleY) {
        var node = this._node;
        var locTextureCoord = this._textureCoord, alpha = (this._displayedOpacity / 255);
        var texture = this._textureToRender || node._texture;
        if ((texture && (locTextureCoord.width === 0 || locTextureCoord.height === 0|| !texture._textureLoaded)) || alpha === 0)
            return;
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        var locX = node._offsetPosition.x, locHeight = node._rect.height, locWidth = node._rect.width,
            locY = -node._offsetPosition.y - locHeight, image;
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        wrapper.setCompositeOperation(this._blendFuncStr);
        wrapper.setGlobalAlpha(alpha);
        if(node._flippedX || node._flippedY)
            wrapper.save();
        if (node._flippedX) {
            locX = -locX - locWidth;
            context.scale(-1, 1);
        }
        if (node._flippedY) {
            locY = node._offsetPosition.y;
            context.scale(1, -1);
        }
        var sx, sy, sw, sh, x, y, w, h;
        if (this._colorized) {
            sx = 0;
            sy = 0;
        }else{
            sx = locTextureCoord.renderX;
            sy = locTextureCoord.renderY;
        }
        sw = locTextureCoord.width;
        sh = locTextureCoord.height;
        x = locX;
        y = locY;
        w = locWidth;
        h = locHeight;
        if (texture && texture._htmlElementObj) {
            image = texture._htmlElementObj;
            if (texture._pattern !== "") {
                wrapper.setFillStyle(context.createPattern(image, texture._pattern));
                context.fillRect(x, y, w, h);
            } else {
                context.drawImage(image,
                    sx, sy, sw, sh,
                    x, y, w, h);
            }
        } else {
            var contentSize = node._contentSize;
            if (locTextureCoord.validRect) {
                var curColor = this._displayedColor;
                wrapper.setFillStyle("rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)");
                context.fillRect(x, y, contentSize.width * scaleX, contentSize.height * scaleY);
            }
        }
        if(node._flippedX || node._flippedY)
            wrapper.restore();
        cc.g_NumberOfDraws++;
    };
    proto._updateColor = function(){
        var node = this._node;
        var texture = node._texture, rect = this._textureCoord;
        var dColor = this._displayedColor;
        if(texture){
            if(dColor.r !== 255 || dColor.g !== 255 || dColor.b !== 255){
                this._textureToRender = texture._generateColorTexture(dColor.r, dColor.g, dColor.b, rect);
                this._colorized = true;
            }else if(texture){
                this._textureToRender = texture;
                this._colorized = false;
            }
        }
    };
    proto._textureLoadedCallback = function (sender) {
        var node = this;
        if (node._textureLoaded)
            return;
        node._textureLoaded = true;
        var locRect = node._rect, locRenderCmd = this._renderCmd;
        if (!locRect) {
            locRect = cc.rect(0, 0, sender.width, sender.height);
        } else if (cc._rectEqualToZero(locRect)) {
            locRect.width = sender.width;
            locRect.height = sender.height;
        }
        node.texture = sender;
        node.setTextureRect(locRect, node._rectRotated);
        var locColor = locRenderCmd._displayedColor;
        if (locColor.r !== 255 || locColor.g !== 255 || locColor.b !== 255)
            locRenderCmd._updateColor();
        node.setBatchNode(node._batchNode);
        node.dispatchEvent("load");
    };
    proto._setTextureCoords = function (rect, needConvert) {
        if (needConvert === undefined)
            needConvert = true;
        var locTextureRect = this._textureCoord,
            scaleFactor = needConvert ? cc.contentScaleFactor() : 1;
        locTextureRect.renderX = locTextureRect.x = 0 | (rect.x * scaleFactor);
        locTextureRect.renderY = locTextureRect.y = 0 | (rect.y * scaleFactor);
        locTextureRect.width = 0 | (rect.width * scaleFactor);
        locTextureRect.height = 0 | (rect.height * scaleFactor);
        locTextureRect.validRect = !(locTextureRect.width === 0 || locTextureRect.height === 0 || locTextureRect.x < 0 || locTextureRect.y < 0);
    };
    cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas = function (texture, rect, counterclockwise) {
        if (!texture)
            return null;
        if (!rect)
            return texture;
        counterclockwise = counterclockwise == null? true: counterclockwise;
        var nCanvas = document.createElement("canvas");
        nCanvas.width = rect.width;
        nCanvas.height = rect.height;
        var ctx = nCanvas.getContext("2d");
        ctx.translate(nCanvas.width / 2, nCanvas.height / 2);
        if(counterclockwise)
            ctx.rotate(-1.5707963267948966);
        else
            ctx.rotate(1.5707963267948966);
        ctx.drawImage(texture, rect.x, rect.y, rect.height, rect.width, -rect.height / 2, -rect.width / 2, rect.height, rect.width);
        return nCanvas;
    };
})();
cc.BakeSprite = cc.Sprite.extend({
    _cacheCanvas: null,
    _cacheContext: null,
    ctor: function(){
        cc.Sprite.prototype.ctor.call(this);
        var canvasElement = document.createElement("canvas");
        canvasElement.width = canvasElement.height = 10;
        this._cacheCanvas = canvasElement;
        this._cacheContext = new cc.CanvasContextWrapper(canvasElement.getContext("2d"));
        var texture = new cc.Texture2D();
        texture.initWithElement(canvasElement);
        texture.handleLoadedTexture();
        this.setTexture(texture);
    },
    getCacheContext: function(){
        return this._cacheContext;
    },
    getCacheCanvas: function(){
        return this._cacheCanvas;
    },
    resetCanvasSize: function(sizeOrWidth, height){
        var locCanvas = this._cacheCanvas,
            locContext = this._cacheContext,
            strokeStyle = locContext._context.strokeStyle,
            fillStyle = locContext._context.fillStyle;
        if(height === undefined){
            height = sizeOrWidth.height;
            sizeOrWidth = sizeOrWidth.width;
        }
        locCanvas.width = sizeOrWidth;
        locCanvas.height = height;
        if(strokeStyle !== locContext._context.strokeStyle)
            locContext._context.strokeStyle = strokeStyle;
        if(fillStyle !== locContext._context.fillStyle)
            locContext._context.fillStyle = fillStyle;
        this.getTexture().handleLoadedTexture();
        this.setTextureRect(cc.rect(0,0, sizeOrWidth, height), false, null, false);
    }
});
cc.AnimationFrame = cc.Class.extend({
    _spriteFrame:null,
    _delayPerUnit:0,
    _userInfo:null,
    ctor:function (spriteFrame, delayUnits, userInfo) {
        this._spriteFrame = spriteFrame || null;
        this._delayPerUnit = delayUnits || 0;
        this._userInfo = userInfo || null;
    },
    clone: function(){
        var frame = new cc.AnimationFrame();
        frame.initWithSpriteFrame(this._spriteFrame.clone(), this._delayPerUnit, this._userInfo);
        return frame;
    },
    copyWithZone:function (pZone) {
        return cc.clone(this);
    },
    copy:function (pZone) {
        var newFrame = new cc.AnimationFrame();
        newFrame.initWithSpriteFrame(this._spriteFrame.clone(), this._delayPerUnit, this._userInfo);
        return newFrame;
    },
    initWithSpriteFrame:function (spriteFrame, delayUnits, userInfo) {
        this._spriteFrame = spriteFrame;
        this._delayPerUnit = delayUnits;
        this._userInfo = userInfo;
        return true;
    },
    getSpriteFrame:function () {
        return this._spriteFrame;
    },
    setSpriteFrame:function (spriteFrame) {
        this._spriteFrame = spriteFrame;
    },
    getDelayUnits:function () {
        return this._delayPerUnit;
    },
    setDelayUnits:function (delayUnits) {
        this._delayPerUnit = delayUnits;
    },
    getUserInfo:function () {
        return this._userInfo;
    },
    setUserInfo:function (userInfo) {
        this._userInfo = userInfo;
    }
});
cc.AnimationFrame.create = function(spriteFrame,delayUnits,userInfo){
    return new cc.AnimationFrame(spriteFrame,delayUnits,userInfo);
};
cc.Animation = cc.Class.extend({
    _frames:null,
    _loops:0,
    _restoreOriginalFrame:false,
    _duration:0,
    _delayPerUnit:0,
    _totalDelayUnits:0,
    ctor:function (frames, delay, loops) {
        this._frames = [];
        if (frames === undefined) {
            this.initWithSpriteFrames(null, 0);
        } else {
            var frame0 = frames[0];
            if(frame0){
                if (frame0 instanceof cc.SpriteFrame) {
                    this.initWithSpriteFrames(frames, delay, loops);
                }else if(frame0 instanceof cc.AnimationFrame) {
                    this.initWithAnimationFrames(frames, delay, loops);
                }
            }
        }
    },
    getFrames:function () {
        return this._frames;
    },
    setFrames:function (frames) {
        this._frames = frames;
    },
    addSpriteFrame:function (frame) {
        var animFrame = new cc.AnimationFrame();
        animFrame.initWithSpriteFrame(frame, 1, null);
        this._frames.push(animFrame);
        this._totalDelayUnits++;
    },
    addSpriteFrameWithFile:function (fileName) {
        var texture = cc.textureCache.addImage(fileName);
        var rect = cc.rect(0, 0, 0, 0);
        rect.width = texture.width;
        rect.height = texture.height;
        var frame = new cc.SpriteFrame(texture, rect);
        this.addSpriteFrame(frame);
    },
    addSpriteFrameWithTexture:function (texture, rect) {
        var pFrame = new cc.SpriteFrame(texture, rect);
        this.addSpriteFrame(pFrame);
    },
    initWithAnimationFrames:function (arrayOfAnimationFrames, delayPerUnit, loops) {
        cc.arrayVerifyType(arrayOfAnimationFrames, cc.AnimationFrame);
        this._delayPerUnit = delayPerUnit;
        this._loops = loops === undefined ? 1 : loops;
        this._totalDelayUnits = 0;
        var locFrames = this._frames;
        locFrames.length = 0;
        for (var i = 0; i < arrayOfAnimationFrames.length; i++) {
            var animFrame = arrayOfAnimationFrames[i];
            locFrames.push(animFrame);
            this._totalDelayUnits += animFrame.getDelayUnits();
        }
        return true;
    },
    clone: function(){
        var animation = new cc.Animation();
        animation.initWithAnimationFrames(this._copyFrames(), this._delayPerUnit, this._loops);
        animation.setRestoreOriginalFrame(this._restoreOriginalFrame);
        return animation;
    },
    copyWithZone:function (pZone) {
        var pCopy = new cc.Animation();
        pCopy.initWithAnimationFrames(this._copyFrames(), this._delayPerUnit, this._loops);
        pCopy.setRestoreOriginalFrame(this._restoreOriginalFrame);
        return pCopy;
    },
    _copyFrames:function(){
       var copyFrames = [];
        for(var i = 0; i< this._frames.length;i++)
            copyFrames.push(this._frames[i].clone());
        return copyFrames;
    },
    copy:function (pZone) {
        return this.copyWithZone(null);
    },
    getLoops:function () {
        return this._loops;
    },
    setLoops:function (value) {
        this._loops = value;
    },
    setRestoreOriginalFrame:function (restOrigFrame) {
        this._restoreOriginalFrame = restOrigFrame;
    },
    getRestoreOriginalFrame:function () {
        return this._restoreOriginalFrame;
    },
    getDuration:function () {
        return this._totalDelayUnits * this._delayPerUnit;
    },
    getDelayPerUnit:function () {
        return this._delayPerUnit;
    },
    setDelayPerUnit:function (delayPerUnit) {
        this._delayPerUnit = delayPerUnit;
    },
    getTotalDelayUnits:function () {
        return this._totalDelayUnits;
    },
    initWithSpriteFrames:function (frames, delay, loops) {
        cc.arrayVerifyType(frames, cc.SpriteFrame);
        this._loops = loops === undefined ? 1 : loops;
        this._delayPerUnit = delay || 0;
        this._totalDelayUnits = 0;
        var locFrames = this._frames;
        locFrames.length = 0;
        if (frames) {
            for (var i = 0; i < frames.length; i++) {
                var frame = frames[i];
                var animFrame = new cc.AnimationFrame();
                animFrame.initWithSpriteFrame(frame, 1, null);
                locFrames.push(animFrame);
            }
            this._totalDelayUnits += frames.length;
        }
        return true;
    },
    retain:function () {
    },
    release:function () {
    }
});
cc.Animation.create = function (frames, delay, loops) {
    return new cc.Animation(frames, delay, loops);
};
cc.Animation.createWithAnimationFrames = cc.Animation.create;
cc.animationCache = {
    _animations: {},
    addAnimation:function (animation, name) {
        this._animations[name] = animation;
    },
    removeAnimation:function (name) {
        if (!name) {
            return;
        }
        if (this._animations[name]) {
            delete this._animations[name];
        }
    },
    getAnimation:function (name) {
        if (this._animations[name])
            return this._animations[name];
        return null;
    },
    _addAnimationsWithDictionary:function (dictionary,plist) {
        var animations = dictionary["animations"];
        if (!animations) {
            cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary);
            return;
        }
        var version = 1;
        var properties = dictionary["properties"];
        if (properties) {
            version = (properties["format"] != null) ? parseInt(properties["format"]) : version;
            var spritesheets = properties["spritesheets"];
            var spriteFrameCache = cc.spriteFrameCache;
            var path = cc.path;
            for (var i = 0; i < spritesheets.length; i++) {
                spriteFrameCache.addSpriteFrames(path.changeBasename(plist, spritesheets[i]));
            }
        }
        switch (version) {
            case 1:
                this._parseVersion1(animations);
                break;
            case 2:
                this._parseVersion2(animations);
                break;
            default :
                cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary_2);
                break;
        }
    },
    addAnimations:function (plist) {
        cc.assert(plist, cc._LogInfos.animationCache_addAnimations_2);
        var dict = cc.loader.getRes(plist);
        if(!dict){
            cc.log(cc._LogInfos.animationCache_addAnimations);
            return;
        }
        this._addAnimationsWithDictionary(dict,plist);
    },
    _parseVersion1:function (animations) {
        var frameCache = cc.spriteFrameCache;
        for (var key in animations) {
            var animationDict = animations[key];
            var frameNames = animationDict["frames"];
            var delay = parseFloat(animationDict["delay"]) || 0;
            var animation = null;
            if (!frameNames) {
                cc.log(cc._LogInfos.animationCache__parseVersion1, key);
                continue;
            }
            var frames = [];
            for (var i = 0; i < frameNames.length; i++) {
                var spriteFrame = frameCache.getSpriteFrame(frameNames[i]);
                if (!spriteFrame) {
                    cc.log(cc._LogInfos.animationCache__parseVersion1_2, key, frameNames[i]);
                    continue;
                }
                var animFrame = new cc.AnimationFrame();
                animFrame.initWithSpriteFrame(spriteFrame, 1, null);
                frames.push(animFrame);
            }
            if (frames.length === 0) {
                cc.log(cc._LogInfos.animationCache__parseVersion1_3, key);
                continue;
            } else if (frames.length !== frameNames.length) {
                cc.log(cc._LogInfos.animationCache__parseVersion1_4, key);
            }
            animation = new cc.Animation(frames, delay, 1);
            cc.animationCache.addAnimation(animation, key);
        }
    },
    _parseVersion2:function (animations) {
        var frameCache = cc.spriteFrameCache;
        for (var key in animations) {
            var animationDict = animations[key];
            var isLoop = animationDict["loop"];
            var loopsTemp = parseInt(animationDict["loops"]);
            var loops = isLoop ? cc.REPEAT_FOREVER : ((isNaN(loopsTemp)) ? 1 : loopsTemp);
            var restoreOriginalFrame = (animationDict["restoreOriginalFrame"] && animationDict["restoreOriginalFrame"] == true) ? true : false;
            var frameArray = animationDict["frames"];
            if (!frameArray) {
                cc.log(cc._LogInfos.animationCache__parseVersion2, key);
                continue;
            }
            var arr = [];
            for (var i = 0; i < frameArray.length; i++) {
                var entry = frameArray[i];
                var spriteFrameName = entry["spriteframe"];
                var spriteFrame = frameCache.getSpriteFrame(spriteFrameName);
                if (!spriteFrame) {
                    cc.log(cc._LogInfos.animationCache__parseVersion2_2, key, spriteFrameName);
                    continue;
                }
                var delayUnits = parseFloat(entry["delayUnits"]) || 0;
                var userInfo = entry["notification"];
                var animFrame = new cc.AnimationFrame();
                animFrame.initWithSpriteFrame(spriteFrame, delayUnits, userInfo);
                arr.push(animFrame);
            }
            var delayPerUnit = parseFloat(animationDict["delayPerUnit"]) || 0;
            var animation = new cc.Animation();
            animation.initWithAnimationFrames(arr, delayPerUnit, loops);
            animation.setRestoreOriginalFrame(restoreOriginalFrame);
            cc.animationCache.addAnimation(animation, key);
        }
    },
    _clear: function () {
        this._animations = {};
    }
};
cc.SpriteFrame = cc.Class.extend({
    _offset:null,
    _originalSize:null,
    _rectInPixels:null,
    _rotated:false,
    _rect:null,
    _offsetInPixels:null,
    _originalSizeInPixels:null,
    _texture:null,
    _textureFilename:"",
    _textureLoaded:false,
    ctor:function (filename, rect, rotated, offset, originalSize) {
        this._offset = cc.p(0, 0);
        this._offsetInPixels = cc.p(0, 0);
        this._originalSize = cc.size(0, 0);
        this._rotated = false;
        this._originalSizeInPixels = cc.size(0, 0);
        this._textureFilename = "";
        this._texture = null;
        this._textureLoaded = false;
        if(filename !== undefined && rect !== undefined ){
            if(rotated === undefined || offset === undefined || originalSize === undefined)
                this.initWithTexture(filename, rect);
            else
                this.initWithTexture(filename, rect, rotated, offset, originalSize)
        }
    },
    textureLoaded:function(){
        return this._textureLoaded;
    },
    addLoadedEventListener:function(callback, target){
        this.addEventListener("load", callback, target);
    },
    getRectInPixels:function () {
        var locRectInPixels = this._rectInPixels;
        return cc.rect(locRectInPixels.x, locRectInPixels.y, locRectInPixels.width, locRectInPixels.height);
    },
    setRectInPixels:function (rectInPixels) {
        if (!this._rectInPixels){
            this._rectInPixels = cc.rect(0,0,0,0);
        }
        this._rectInPixels.x = rectInPixels.x;
        this._rectInPixels.y = rectInPixels.y;
        this._rectInPixels.width = rectInPixels.width;
        this._rectInPixels.height = rectInPixels.height;
        this._rect = cc.rectPixelsToPoints(rectInPixels);
    },
    isRotated:function () {
        return this._rotated;
    },
    setRotated:function (bRotated) {
        this._rotated = bRotated;
    },
    getRect:function () {
        var locRect = this._rect;
        return cc.rect(locRect.x, locRect.y, locRect.width, locRect.height);
    },
    setRect:function (rect) {
        if (!this._rect){
            this._rect = cc.rect(0,0,0,0);
        }
        this._rect.x = rect.x;
        this._rect.y = rect.y;
        this._rect.width = rect.width;
        this._rect.height = rect.height;
        this._rectInPixels = cc.rectPointsToPixels(this._rect);
    },
    getOffsetInPixels:function () {
        return cc.p(this._offsetInPixels);
    },
    setOffsetInPixels:function (offsetInPixels) {
        this._offsetInPixels.x = offsetInPixels.x;
        this._offsetInPixels.y = offsetInPixels.y;
        cc._pointPixelsToPointsOut(this._offsetInPixels, this._offset);
    },
    getOriginalSizeInPixels:function () {
        return cc.size(this._originalSizeInPixels);
    },
    setOriginalSizeInPixels:function (sizeInPixels) {
        this._originalSizeInPixels.width = sizeInPixels.width;
        this._originalSizeInPixels.height = sizeInPixels.height;
    },
    getOriginalSize:function () {
        return cc.size(this._originalSize);
    },
    setOriginalSize:function (sizeInPixels) {
        this._originalSize.width = sizeInPixels.width;
        this._originalSize.height = sizeInPixels.height;
    },
    getTexture:function () {
        if (this._texture)
            return this._texture;
        if (this._textureFilename !== "") {
            var locTexture = cc.textureCache.addImage(this._textureFilename);
            if (locTexture)
                this._textureLoaded = locTexture.isLoaded();
            return locTexture;
        }
        return null;
    },
    setTexture:function (texture) {
        if (this._texture !== texture) {
            var locLoaded = texture.isLoaded();
            this._textureLoaded = locLoaded;
            this._texture = texture;
            if(!locLoaded){
                texture.addEventListener("load", function(sender){
                    this._textureLoaded = true;
                    if(this._rotated && cc._renderType === cc.game.RENDER_TYPE_CANVAS){
                        var tempElement = sender.getHtmlElementObj();
                        tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, this.getRect());
                        var tempTexture = new cc.Texture2D();
                        tempTexture.initWithElement(tempElement);
                        tempTexture.handleLoadedTexture();
                        this.setTexture(tempTexture);
                        var rect = this.getRect();
                        this.setRect(cc.rect(0, 0, rect.width, rect.height));
                    }
                    var locRect = this._rect;
                    if(locRect.width === 0 && locRect.height === 0){
                        var w = sender.width, h = sender.height;
                        this._rect.width = w;
                        this._rect.height = h;
                        this._rectInPixels = cc.rectPointsToPixels(this._rect);
                        this._originalSizeInPixels.width = this._rectInPixels.width;
                        this._originalSizeInPixels.height = this._rectInPixels.height;
                        this._originalSize.width =  w;
                        this._originalSize.height =  h;
                    }
                    this.dispatchEvent("load");
                }, this);
            }
        }
    },
    getOffset:function () {
        return cc.p(this._offset);
    },
    setOffset:function (offsets) {
        this._offset.x = offsets.x;
        this._offset.y = offsets.y;
    },
    clone: function(){
        var frame = new cc.SpriteFrame();
        frame.initWithTexture(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels);
        frame.setTexture(this._texture);
        return frame;
    },
    copyWithZone:function () {
        var copy = new cc.SpriteFrame();
        copy.initWithTexture(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels);
        copy.setTexture(this._texture);
        return copy;
    },
    copy:function () {
        return this.copyWithZone();
    },
    initWithTexture:function (texture, rect, rotated, offset, originalSize) {
        if(arguments.length === 2)
            rect = cc.rectPointsToPixels(rect);
        offset = offset || cc.p(0, 0);
        originalSize = originalSize || rect;
        rotated = rotated || false;
        if (cc.isString(texture)){
            this._texture = null;
            this._textureFilename = texture;
        } else if (texture instanceof cc.Texture2D){
            this.setTexture(texture);
        }
        texture = this.getTexture();
        this._rectInPixels = rect;
        this._rect = cc.rectPixelsToPoints(rect);
        if(texture && texture.url && texture.isLoaded()) {
            var _x, _y;
            if(rotated){
                _x = rect.x + rect.height;
                _y = rect.y + rect.width;
            }else{
                _x = rect.x + rect.width;
                _y = rect.y + rect.height;
            }
            if(_x > texture.getPixelsWide()){
                cc.error(cc._LogInfos.RectWidth, texture.url);
            }
            if(_y > texture.getPixelsHigh()){
                cc.error(cc._LogInfos.RectHeight, texture.url);
            }
        }
        this._offsetInPixels.x = offset.x;
        this._offsetInPixels.y = offset.y;
        cc._pointPixelsToPointsOut(offset, this._offset);
        this._originalSizeInPixels.width = originalSize.width;
        this._originalSizeInPixels.height = originalSize.height;
        cc._sizePixelsToPointsOut(originalSize, this._originalSize);
        this._rotated = rotated;
        return true;
    }
});
cc.EventHelper.prototype.apply(cc.SpriteFrame.prototype);
cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) {
    return new cc.SpriteFrame(filename,rect,rotated,offset,originalSize);
};
cc.SpriteFrame.createWithTexture = cc.SpriteFrame.create;
cc.SpriteFrame._frameWithTextureForCanvas = function (texture, rect, rotated, offset, originalSize) {
    var spriteFrame = new cc.SpriteFrame();
    spriteFrame._texture = texture;
    spriteFrame._rectInPixels = rect;
    spriteFrame._rect = cc.rectPixelsToPoints(rect);
    spriteFrame._offsetInPixels.x = offset.x;
    spriteFrame._offsetInPixels.y = offset.y;
    cc._pointPixelsToPointsOut(spriteFrame._offsetInPixels, spriteFrame._offset);
    spriteFrame._originalSizeInPixels.width = originalSize.width;
    spriteFrame._originalSizeInPixels.height = originalSize.height;
    cc._sizePixelsToPointsOut(spriteFrame._originalSizeInPixels, spriteFrame._originalSize);
    spriteFrame._rotated = rotated;
    return spriteFrame;
};
cc.spriteFrameCache = {
    _CCNS_REG1 : /^\s*\{\s*([\-]?\d+[.]?\d*)\s*,\s*([\-]?\d+[.]?\d*)\s*\}\s*$/,
    _CCNS_REG2 : /^\s*\{\s*\{\s*([\-]?\d+[.]?\d*)\s*,\s*([\-]?\d+[.]?\d*)\s*\}\s*,\s*\{\s*([\-]?\d+[.]?\d*)\s*,\s*([\-]?\d+[.]?\d*)\s*\}\s*\}\s*$/,
    _spriteFrames: {},
    _spriteFramesAliases: {},
    _frameConfigCache : {},
    _rectFromString :  function (content) {
        var result = this._CCNS_REG2.exec(content);
        if(!result) return cc.rect(0, 0, 0, 0);
        return cc.rect(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]));
    },
    _pointFromString : function (content) {
        var result = this._CCNS_REG1.exec(content);
        if(!result) return cc.p(0,0);
        return cc.p(parseFloat(result[1]), parseFloat(result[2]));
    },
    _sizeFromString : function (content) {
        var result = this._CCNS_REG1.exec(content);
        if(!result) return cc.size(0, 0);
        return cc.size(parseFloat(result[1]), parseFloat(result[2]));
    },
    _getFrameConfig : function(url){
        var dict = cc.loader.getRes(url);
        cc.assert(dict, cc._LogInfos.spriteFrameCache__getFrameConfig_2, url);
        cc.loader.release(url);//release it in loader
        if(dict._inited){
            this._frameConfigCache[url] = dict;
            return dict;
        }
        this._frameConfigCache[url] = this._parseFrameConfig(dict);
        return this._frameConfigCache[url];
    },
    _getFrameConfigByJsonObject: function(url, jsonObject) {
        cc.assert(jsonObject, cc._LogInfos.spriteFrameCache__getFrameConfig_2, url);
        this._frameConfigCache[url] = this._parseFrameConfig(jsonObject);
        return this._frameConfigCache[url];
    },
    _parseFrameConfig: function(dict) {
        var tempFrames = dict["frames"], tempMeta = dict["metadata"] || dict["meta"];
        var frames = {}, meta = {};
        var format = 0;
        if(tempMeta){//init meta
            var tmpFormat = tempMeta["format"];
            format = (tmpFormat.length <= 1) ? parseInt(tmpFormat) : tmpFormat;
            meta.image = tempMeta["textureFileName"] || tempMeta["textureFileName"] || tempMeta["image"];
        }
        for (var key in tempFrames) {
            var frameDict = tempFrames[key];
            if(!frameDict) continue;
            var tempFrame = {};
            if (format == 0) {
                tempFrame.rect = cc.rect(frameDict["x"], frameDict["y"], frameDict["width"], frameDict["height"]);
                tempFrame.rotated = false;
                tempFrame.offset = cc.p(frameDict["offsetX"], frameDict["offsetY"]);
                var ow = frameDict["originalWidth"];
                var oh = frameDict["originalHeight"];
                if (!ow || !oh) {
                    cc.log(cc._LogInfos.spriteFrameCache__getFrameConfig);
                }
                ow = Math.abs(ow);
                oh = Math.abs(oh);
                tempFrame.size = cc.size(ow, oh);
            } else if (format == 1 || format == 2) {
                tempFrame.rect = this._rectFromString(frameDict["frame"]);
                tempFrame.rotated = frameDict["rotated"] || false;
                tempFrame.offset = this._pointFromString(frameDict["offset"]);
                tempFrame.size = this._sizeFromString(frameDict["sourceSize"]);
            } else if (format == 3) {
                var spriteSize = this._sizeFromString(frameDict["spriteSize"]);
                var textureRect = this._rectFromString(frameDict["textureRect"]);
                if (spriteSize) {
                    textureRect = cc.rect(textureRect.x, textureRect.y, spriteSize.width, spriteSize.height);
                }
                tempFrame.rect = textureRect;
                tempFrame.rotated = frameDict["textureRotated"] || false;
                tempFrame.offset = this._pointFromString(frameDict["spriteOffset"]);
                tempFrame.size = this._sizeFromString(frameDict["spriteSourceSize"]);
                tempFrame.aliases = frameDict["aliases"];
            } else {
                var tmpFrame = frameDict["frame"], tmpSourceSize = frameDict["sourceSize"];
                key = frameDict["filename"] || key;
                tempFrame.rect = cc.rect(tmpFrame["x"], tmpFrame["y"], tmpFrame["w"], tmpFrame["h"]);
                tempFrame.rotated = frameDict["rotated"] || false;
                tempFrame.offset = cc.p(0, 0);
                tempFrame.size = cc.size(tmpSourceSize["w"], tmpSourceSize["h"]);
            }
            frames[key] = tempFrame;
        }
        return {_inited: true, frames: frames, meta: meta};
    },
    _addSpriteFramesByObject: function(url, jsonObject, texture) {
        cc.assert(url, cc._LogInfos.spriteFrameCache_addSpriteFrames_2);
        if(!jsonObject || !jsonObject["frames"])
            return;
        var frameConfig = this._frameConfigCache[url] || this._getFrameConfigByJsonObject(url, jsonObject);
        this._createSpriteFrames(url, frameConfig, texture);
    },
    _createSpriteFrames: function(url, frameConfig, texture) {
        var frames = frameConfig.frames, meta = frameConfig.meta;
        if(!texture){
            var texturePath = cc.path.changeBasename(url, meta.image || ".png");
            texture = cc.textureCache.addImage(texturePath);
        }else if(texture instanceof cc.Texture2D){
        }else if(cc.isString(texture)){//string
            texture = cc.textureCache.addImage(texture);
        }else{
            cc.assert(0, cc._LogInfos.spriteFrameCache_addSpriteFrames_3);
        }
        var spAliases = this._spriteFramesAliases, spriteFrames = this._spriteFrames;
        for (var key in frames) {
            var frame = frames[key];
            var spriteFrame = spriteFrames[key];
            if (!spriteFrame) {
                spriteFrame = new cc.SpriteFrame(texture, frame.rect, frame.rotated, frame.offset, frame.size);
                var aliases = frame.aliases;
                if(aliases){//set aliases
                    for(var i = 0, li = aliases.length; i < li; i++){
                        var alias = aliases[i];
                        if (spAliases[alias])
                            cc.log(cc._LogInfos.spriteFrameCache_addSpriteFrames, alias);
                        spAliases[alias] = key;
                    }
                }
                if (cc._renderType === cc.game.RENDER_TYPE_CANVAS && spriteFrame.isRotated()) {
                    var locTexture = spriteFrame.getTexture();
                    if (locTexture.isLoaded()) {
                        var tempElement = spriteFrame.getTexture().getHtmlElementObj();
                        tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, spriteFrame.getRectInPixels());
                        var tempTexture = new cc.Texture2D();
                        tempTexture.initWithElement(tempElement);
                        tempTexture.handleLoadedTexture();
                        spriteFrame.setTexture(tempTexture);
                        var rect = spriteFrame._rect;
                        spriteFrame.setRect(cc.rect(0, 0, rect.width, rect.height));
                    }
                }
                spriteFrames[key] = spriteFrame;
            }
        }
    },
    addSpriteFrames: function (url, texture) {
        cc.assert(url, cc._LogInfos.spriteFrameCache_addSpriteFrames_2);
        var dict = this._frameConfigCache[url] || cc.loader.getRes(url);
        if(!dict || !dict["frames"])
            return;
        var frameConfig = this._frameConfigCache[url] || this._getFrameConfig(url);
        this._createSpriteFrames(url, frameConfig, texture);
    },
    _checkConflict: function (dictionary) {
        var framesDict = dictionary["frames"];
        for (var key in framesDict) {
            if (this._spriteFrames[key]) {
                cc.log(cc._LogInfos.spriteFrameCache__checkConflict, key);
            }
        }
    },
    addSpriteFrame: function (frame, frameName) {
        this._spriteFrames[frameName] = frame;
    },
    removeSpriteFrames: function () {
        this._spriteFrames = {};
        this._spriteFramesAliases = {};
    },
    removeSpriteFrameByName: function (name) {
        if (!name) {
            return;
        }
        if (this._spriteFramesAliases[name]) {
            delete(this._spriteFramesAliases[name]);
        }
        if (this._spriteFrames[name]) {
            delete(this._spriteFrames[name]);
        }
    },
    removeSpriteFramesFromFile: function (url) {
        var self = this, spriteFrames = self._spriteFrames,
            aliases = self._spriteFramesAliases, cfg = self._frameConfigCache[url];
        if(!cfg) return;
        var frames = cfg.frames;
        for (var key in frames) {
            if (spriteFrames[key]) {
                delete(spriteFrames[key]);
                for (var alias in aliases) {//remove alias
                    if(aliases[alias] === key) delete aliases[alias];
                }
            }
        }
    },
    removeSpriteFramesFromTexture: function (texture) {
        var self = this, spriteFrames = self._spriteFrames, aliases = self._spriteFramesAliases;
        for (var key in spriteFrames) {
            var frame = spriteFrames[key];
            if (frame && (frame.getTexture() === texture)) {
                delete(spriteFrames[key]);
                for (var alias in aliases) {//remove alias
                    if(aliases[alias] === key) delete aliases[alias];
                }
            }
        }
    },
    getSpriteFrame: function (name) {
        var self = this, frame = self._spriteFrames[name];
        if (!frame) {
            var key = self._spriteFramesAliases[name];
            if (key) {
                frame = self._spriteFrames[key.toString()];
                if(!frame) delete self._spriteFramesAliases[name];
            }
        }
        return frame;
    },
    _clear: function () {
        this._spriteFrames = {};
        this._spriteFramesAliases = {};
        this._frameConfigCache = {};
    }
};
cc.g_NumberOfDraws = 0;
cc.Director = cc.Class.extend({
    _landscape: false,
    _nextDeltaTimeZero: false,
    _paused: false,
    _purgeDirectorInNextLoop: false,
    _sendCleanupToScene: false,
    _animationInterval: 0.0,
    _oldAnimationInterval: 0.0,
    _projection: 0,
    _contentScaleFactor: 1.0,
    _deltaTime: 0.0,
    _winSizeInPoints: null,
    _lastUpdate: null,
    _nextScene: null,
    _notificationNode: null,
    _openGLView: null,
    _scenesStack: null,
    _projectionDelegate: null,
    _runningScene: null,
    _totalFrames: 0,
    _secondsPerFrame: 0,
    _dirtyRegion: null,
    _scheduler: null,
    _actionManager: null,
    _eventProjectionChanged: null,
    _eventAfterUpdate: null,
    _eventAfterVisit: null,
    _eventAfterDraw: null,
    ctor: function () {
        var self = this;
        self._lastUpdate = Date.now();
        cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () {
            self._lastUpdate = Date.now();
        });
    },
    init: function () {
        this._oldAnimationInterval = this._animationInterval = 1.0 / cc.defaultFPS;
        this._scenesStack = [];
        this._projection = cc.Director.PROJECTION_DEFAULT;
        this._projectionDelegate = null;
        this._totalFrames = 0;
        this._lastUpdate = Date.now();
        this._paused = false;
        this._purgeDirectorInNextLoop = false;
        this._winSizeInPoints = cc.size(0, 0);
        this._openGLView = null;
        this._contentScaleFactor = 1.0;
        this._scheduler = new cc.Scheduler();
        if(cc.ActionManager){
            this._actionManager = new cc.ActionManager();
            this._scheduler.scheduleUpdate(this._actionManager, cc.Scheduler.PRIORITY_SYSTEM, false);
        }else{
            this._actionManager = null;
        }
        this._eventAfterUpdate = new cc.EventCustom(cc.Director.EVENT_AFTER_UPDATE);
        this._eventAfterUpdate.setUserData(this);
        this._eventAfterVisit = new cc.EventCustom(cc.Director.EVENT_AFTER_VISIT);
        this._eventAfterVisit.setUserData(this);
        this._eventAfterDraw = new cc.EventCustom(cc.Director.EVENT_AFTER_DRAW);
        this._eventAfterDraw.setUserData(this);
        this._eventProjectionChanged = new cc.EventCustom(cc.Director.EVENT_PROJECTION_CHANGED);
        this._eventProjectionChanged.setUserData(this);
        return true;
    },
    calculateDeltaTime: function () {
        var now = Date.now();
        if (this._nextDeltaTimeZero) {
            this._deltaTime = 0;
            this._nextDeltaTimeZero = false;
        } else {
            this._deltaTime = (now - this._lastUpdate) / 1000;
        }
        if ((cc.game.config[cc.game.CONFIG_KEY.debugMode] > 0) && (this._deltaTime > 0.2))
            this._deltaTime = 1 / 60.0;
        this._lastUpdate = now;
    },
    convertToGL: function (uiPoint) {
        var docElem = document.documentElement;
        var view = cc.view;
        var box = element.getBoundingClientRect();
        box.left += window.pageXOffset - docElem.clientLeft;
        box.top += window.pageYOffset - docElem.clientTop;
        var x = view._devicePixelRatio * (uiPoint.x - box.left);
        var y = view._devicePixelRatio * (box.top + box.height - uiPoint.y);
        return view._isRotated ? {x: view._viewPortRect.width - y, y: x} : {x: x, y: y};
    },
    convertToUI: function (glPoint) {
        var docElem = document.documentElement;
        var view = cc.view;
        var box = element.getBoundingClientRect();
        box.left += window.pageXOffset - docElem.clientLeft;
        box.top += window.pageYOffset - docElem.clientTop;
        var uiPoint = {x: 0, y: 0};
        if (view._isRotated) {
            uiPoint.x = box.left + glPoint.y / view._devicePixelRatio;
            uiPoint.y = box.top + box.height - (view._viewPortRect.width - glPoint.x) / view._devicePixelRatio;
        }
        else {
            uiPoint.x = box.left + glPoint.x / view._devicePixelRatio;
            uiPoint.y = box.top + box.height - glPoint.y / view._devicePixelRatio;
        }
        return uiPoint;
    },
    drawScene: function () {
        var renderer = cc.renderer;
        this.calculateDeltaTime();
        if (!this._paused) {
            this._scheduler.update(this._deltaTime);
            cc.eventManager.dispatchEvent(this._eventAfterUpdate);
        }
        if (this._nextScene) {
            this.setNextScene();
        }
        if (this._beforeVisitScene)
            this._beforeVisitScene();
        if (this._runningScene) {
            if (renderer.childrenOrderDirty) {
                cc.renderer.clearRenderCommands();
                cc.renderer.assignedZ = 0;
                this._runningScene._renderCmd._curLevel = 0;
                this._runningScene.visit();
                renderer.resetFlag();
            }
            else if (renderer.transformDirty()) {
                renderer.transform();
            }
        }
        renderer.clear();
        if (this._notificationNode)
            this._notificationNode.visit();
        cc.eventManager.dispatchEvent(this._eventAfterVisit);
        cc.g_NumberOfDraws = 0;
        if (this._afterVisitScene)
            this._afterVisitScene();
        renderer.rendering(cc._renderContext);
        this._totalFrames++;
        cc.eventManager.dispatchEvent(this._eventAfterDraw);
        this._calculateMPF();
    },
    _beforeVisitScene: null,
    _afterVisitScene: null,
    end: function () {
        this._purgeDirectorInNextLoop = true;
    },
    getContentScaleFactor: function () {
        return this._contentScaleFactor;
    },
    getNotificationNode: function () {
        return this._notificationNode;
    },
    getWinSize: function () {
        return cc.size(this._winSizeInPoints);
    },
    getWinSizeInPixels: function () {
        return cc.size(this._winSizeInPoints.width * this._contentScaleFactor, this._winSizeInPoints.height * this._contentScaleFactor);
    },
    getVisibleSize: null,
    getVisibleOrigin: null,
    getZEye: null,
    pause: function () {
        if (this._paused)
            return;
        this._oldAnimationInterval = this._animationInterval;
        this.setAnimationInterval(1 / 4.0);
        this._paused = true;
    },
    popScene: function () {
        cc.assert(this._runningScene, cc._LogInfos.Director_popScene);
        this._scenesStack.pop();
        var c = this._scenesStack.length;
        if (c === 0)
            this.end();
        else {
            this._sendCleanupToScene = true;
            this._nextScene = this._scenesStack[c - 1];
        }
    },
    purgeCachedData: function () {
        cc.animationCache._clear();
        cc.spriteFrameCache._clear();
        cc.textureCache._clear();
    },
    purgeDirector: function () {
        this.getScheduler().unscheduleAll();
        if (cc.eventManager)
            cc.eventManager.setEnabled(false);
        if (this._runningScene) {
            this._runningScene.onExitTransitionDidStart();
            this._runningScene.onExit();
            this._runningScene.cleanup();
        }
        this._runningScene = null;
        this._nextScene = null;
        this._scenesStack.length = 0;
        this.stopAnimation();
        this.purgeCachedData();
        cc.checkGLErrorDebug();
    },
    pushScene: function (scene) {
        cc.assert(scene, cc._LogInfos.Director_pushScene);
        this._sendCleanupToScene = false;
        this._scenesStack.push(scene);
        this._nextScene = scene;
    },
    runScene: function (scene) {
        cc.assert(scene, cc._LogInfos.Director_pushScene);
        if (!this._runningScene) {
            this.pushScene(scene);
            this.startAnimation();
        } else {
            var i = this._scenesStack.length;
            if (i === 0) {
                this._sendCleanupToScene = true;
                this._scenesStack[i] = scene;
                this._nextScene = scene;
            } else {
                this._sendCleanupToScene = true;
                this._scenesStack[i - 1] = scene;
                this._nextScene = scene;
            }
        }
    },
    resume: function () {
        if (!this._paused) {
            return;
        }
        this.setAnimationInterval(this._oldAnimationInterval);
        this._lastUpdate = Date.now();
        if (!this._lastUpdate) {
            cc.log(cc._LogInfos.Director_resume);
        }
        this._paused = false;
        this._deltaTime = 0;
    },
    setContentScaleFactor: function (scaleFactor) {
        if (scaleFactor !== this._contentScaleFactor) {
            this._contentScaleFactor = scaleFactor;
        }
    },
    setDepthTest: null,
    setClearColor: null,
    setDefaultValues: function () {
    },
    setNextDeltaTimeZero: function (nextDeltaTimeZero) {
        this._nextDeltaTimeZero = nextDeltaTimeZero;
    },
    setNextScene: function () {
        var runningIsTransition = false, newIsTransition = false;
        if (cc.TransitionScene) {
            runningIsTransition = this._runningScene ? this._runningScene instanceof cc.TransitionScene : false;
            newIsTransition = this._nextScene ? this._nextScene instanceof cc.TransitionScene : false;
        }
        if (!newIsTransition) {
            var locRunningScene = this._runningScene;
            if (locRunningScene) {
                locRunningScene.onExitTransitionDidStart();
                locRunningScene.onExit();
            }
            if (this._sendCleanupToScene && locRunningScene)
                locRunningScene.cleanup();
        }
        this._runningScene = this._nextScene;
        cc.renderer.childrenOrderDirty = true;
        this._nextScene = null;
        if ((!runningIsTransition) && (this._runningScene !== null)) {
            this._runningScene.onEnter();
            this._runningScene.onEnterTransitionDidFinish();
        }
    },
    setNotificationNode: function (node) {
        cc.renderer.childrenOrderDirty = true;
        if(this._notificationNode){
            this._notificationNode.onExitTransitionDidStart();
            this._notificationNode.onExit();
            this._notificationNode.cleanup();
        }
        this._notificationNode = node;
        if(!node)
            return;
        this._notificationNode.onEnter();
        this._notificationNode.onEnterTransitionDidFinish();
    },
    getDelegate: function () {
        return this._projectionDelegate;
    },
    setDelegate: function (delegate) {
        this._projectionDelegate = delegate;
    },
    setOpenGLView: null,
    setProjection: null,
    setViewport: null,
    getOpenGLView: null,
    getProjection: null,
    setAlphaBlending: null,
    isSendCleanupToScene: function () {
        return this._sendCleanupToScene;
    },
    getRunningScene: function () {
        return this._runningScene;
    },
    getAnimationInterval: function () {
        return this._animationInterval;
    },
    isDisplayStats: function () {
        return cc.profiler ? cc.profiler.isShowingStats() : false;
    },
    setDisplayStats: function (displayStats) {
        if (cc.profiler) {
            displayStats ? cc.profiler.showStats() : cc.profiler.hideStats();
        }
    },
    getSecondsPerFrame: function () {
        return this._secondsPerFrame;
    },
    isNextDeltaTimeZero: function () {
        return this._nextDeltaTimeZero;
    },
    isPaused: function () {
        return this._paused;
    },
    getTotalFrames: function () {
        return this._totalFrames;
    },
    popToRootScene: function () {
        this.popToSceneStackLevel(1);
    },
    popToSceneStackLevel: function (level) {
        cc.assert(this._runningScene, cc._LogInfos.Director_popToSceneStackLevel_2);
        var locScenesStack = this._scenesStack;
        var c = locScenesStack.length;
        if (level === 0) {
            this.end();
            return;
        }
        if (level >= c)
            return;
        while (c > level) {
            var current = locScenesStack.pop();
            if (current.running) {
                current.onExitTransitionDidStart();
                current.onExit();
            }
            current.cleanup();
            c--;
        }
        this._nextScene = locScenesStack[locScenesStack.length - 1];
        this._sendCleanupToScene = true;
    },
    getScheduler: function () {
        return this._scheduler;
    },
    setScheduler: function (scheduler) {
        if (this._scheduler !== scheduler) {
            this._scheduler = scheduler;
        }
    },
    getActionManager: function () {
        return this._actionManager;
    },
    setActionManager: function (actionManager) {
        if (this._actionManager !== actionManager) {
            this._actionManager = actionManager;
        }
    },
    getDeltaTime: function () {
        return this._deltaTime;
    },
    _calculateMPF: function () {
        var now = Date.now();
        this._secondsPerFrame = (now - this._lastUpdate) / 1000;
    }
});
cc.Director.EVENT_PROJECTION_CHANGED = "director_projection_changed";
cc.Director.EVENT_AFTER_UPDATE = "director_after_update";
cc.Director.EVENT_AFTER_VISIT = "director_after_visit";
cc.Director.EVENT_AFTER_DRAW = "director_after_draw";
cc.DisplayLinkDirector = cc.Director.extend({
    invalid: false,
    startAnimation: function () {
        this._nextDeltaTimeZero = true;
        this.invalid = false;
    },
    mainLoop: function () {
        if (this._purgeDirectorInNextLoop) {
            this._purgeDirectorInNextLoop = false;
            this.purgeDirector();
        }
        else if (!this.invalid) {
            this.drawScene();
        }
    },
    stopAnimation: function () {
        this.invalid = true;
    },
    setAnimationInterval: function (value) {
        this._animationInterval = value;
        if (!this.invalid) {
            this.stopAnimation();
            this.startAnimation();
        }
    }
});
cc.Director.sharedDirector = null;
cc.Director.firstUseDirector = true;
cc.Director._getInstance = function () {
    if (cc.Director.firstUseDirector) {
        cc.Director.firstUseDirector = false;
        cc.Director.sharedDirector = new cc.DisplayLinkDirector();
        cc.Director.sharedDirector.init();
    }
    return cc.Director.sharedDirector;
};
cc.defaultFPS = 60;
cc.Director.PROJECTION_2D = 0;
cc.Director.PROJECTION_3D = 1;
cc.Director.PROJECTION_CUSTOM = 3;
cc.Director.PROJECTION_DEFAULT = cc.Director.PROJECTION_2D;
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
        var _p = cc.Director.prototype;
        _p.getProjection = function (projection) {
            return this._projection;
        };
        _p.setProjection = function (projection) {
            this._projection = projection;
            cc.eventManager.dispatchEvent(this._eventProjectionChanged);
        };
        _p.setDepthTest = function () {
        };
        _p.setClearColor = function (clearColor) {
            cc.renderer._clearColor = clearColor;
            cc.renderer._clearFillStyle = 'rgb(' + clearColor.r + ',' + clearColor.g + ',' + clearColor.b +')' ;
        };
        _p.setOpenGLView = function (openGLView) {
            this._winSizeInPoints.width = cc._canvas.width;
            this._winSizeInPoints.height = cc._canvas.height;
            this._openGLView = openGLView || cc.view;
            if (cc.eventManager)
                cc.eventManager.setEnabled(true);
        };
        _p.getVisibleSize = function () {
            return this.getWinSize();
        };
        _p.getVisibleOrigin = function () {
            return cc.p(0, 0);
        };
    } else {
        cc.Director._fpsImage = new Image();
        cc.Director._fpsImage.addEventListener("load", function () {
            cc.Director._fpsImageLoaded = true;
        });
        if (cc._fpsImage) {
            cc.Director._fpsImage.src = cc._fpsImage;
        }
    }
});
cc.PRIORITY_NON_SYSTEM = cc.PRIORITY_SYSTEM + 1;
cc.ListEntry = function (prev, next, callback, target, priority, paused, markedForDeletion) {
    this.prev = prev;
    this.next = next;
    this.callback = callback;
    this.target = target;
    this.priority = priority;
    this.paused = paused;
    this.markedForDeletion = markedForDeletion;
};
cc.HashUpdateEntry = function (list, entry, target, callback, hh) {
    this.list = list;
    this.entry = entry;
    this.target = target;
    this.callback = callback;
    this.hh = hh;
};
cc.HashTimerEntry = cc.hashSelectorEntry = function (timers, target, timerIndex, currentTimer, currentTimerSalvaged, paused, hh) {
    var _t = this;
    _t.timers = timers;
    _t.target = target;
    _t.timerIndex = timerIndex;
    _t.currentTimer = currentTimer;
    _t.currentTimerSalvaged = currentTimerSalvaged;
    _t.paused = paused;
    _t.hh = hh;
};
cc.Timer = cc.Class.extend({
    _scheduler: null,
    _elapsed:0.0,
    _runForever:false,
    _useDelay:false,
    _timesExecuted:0,
    _repeat:0,
    _delay:0,
    _interval:0.0,
    getInterval : function(){return this._interval;},
    setInterval : function(interval){this._interval = interval;},
    setupTimerWithInterval: function(seconds, repeat, delay){
        this._elapsed = -1;
        this._interval = seconds;
        this._delay = delay;
        this._useDelay = (this._delay > 0);
        this._repeat = repeat;
        this._runForever = (this._repeat === cc.REPEAT_FOREVER);
    },
    trigger: function(){
        return 0;
    },
    cancel: function(){
        return 0;
    },
    ctor:function () {
        this._scheduler = null;
        this._elapsed = -1;
        this._runForever = false;
        this._useDelay = false;
        this._timesExecuted = 0;
        this._repeat = 0;
        this._delay = 0;
        this._interval = 0;
    },
    update:function (dt) {
        if (this._elapsed === -1) {
            this._elapsed = 0;
            this._timesExecuted = 0;
        } else {
            this._elapsed += dt;
            if (this._runForever && !this._useDelay) {//standard timer usage
                if (this._elapsed >= this._interval) {
                    this.trigger();
                    this._elapsed = 0;
                }
            } else {//advanced usage
                if (this._useDelay) {
                    if (this._elapsed >= this._delay) {
                        this.trigger();
                        this._elapsed -= this._delay;
                        this._timesExecuted += 1;
                        this._useDelay = false;
                    }
                } else {
                    if (this._elapsed >= this._interval) {
                        this.trigger();
                        this._elapsed = 0;
                        this._timesExecuted += 1;
                    }
                }
                if (!this._runForever && this._timesExecuted > this._repeat)
                    this.cancel();
            }
        }
    }
});
cc.TimerTargetSelector = cc.Timer.extend({
    _target: null,
    _selector: null,
    ctor: function(){
        this._target = null;
        this._selector = null;
    },
    initWithSelector: function(scheduler, selector, target, seconds, repeat, delay){
        this._scheduler = scheduler;
        this._target = target;
        this._selector = selector;
        this.setupTimerWithInterval(seconds, repeat, delay);
        return true;
    },
    getSelector: function(){
        return this._selector;
    },
    trigger: function(){
        if (this._target && this._selector){
            this._target.call(this._selector, this._elapsed);
        }
    },
    cancel: function(){
        this._scheduler.unschedule(this._selector, this._target);
    }
});
cc.TimerTargetCallback = cc.Timer.extend({
    _target: null,
    _callback: null,
    _key: null,
    ctor: function(){
        this._target = null;
        this._callback = null;
    },
    initWithCallback: function(scheduler, callback, target, key, seconds, repeat, delay){
        this._scheduler = scheduler;
        this._target = target;
        this._callback = callback;
        this._key = key;
        this.setupTimerWithInterval(seconds, repeat, delay);
        return true;
    },
    getCallback: function(){
        return this._callback;
    },
    getKey: function(){
        return this._key;
    },
    trigger: function(){
        if(this._callback)
            this._callback.call(this._target, this._elapsed);
    },
    cancel: function(){
        this._scheduler.unschedule(this._callback, this._target);
    }
});
cc.Scheduler = cc.Class.extend({
    _timeScale:1.0,
    _updatesNegList: null,
    _updates0List: null,
    _updatesPosList: null,
    _hashForTimers:null,
    _arrayForTimers:null,
    _hashForUpdates:null,
    _currentTarget:null,
    _currentTargetSalvaged:false,
    _updateHashLocked:false,
    ctor:function () {
        this._timeScale = 1.0;
        this._updatesNegList = [];
        this._updates0List = [];
        this._updatesPosList = [];
        this._hashForUpdates = {};
        this._hashForTimers = {};
        this._currentTarget = null;
        this._currentTargetSalvaged = false;
        this._updateHashLocked = false;
        this._arrayForTimers = [];
    },
    _schedulePerFrame: function(callback, target, priority, paused){
        var hashElement = this._hashForUpdates[target.__instanceId];
        if (hashElement && hashElement.entry){
            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{
                    this.unscheduleUpdate(target);
                }
            }else{
                hashElement.entry.markedForDeletion = false;
                hashElement.entry.paused = paused;
                return;
            }
        }
        if (priority === 0){
            this._appendIn(this._updates0List, callback, target, paused);
        }else if (priority < 0){
            this._priorityIn(this._updatesNegList, callback, target, priority, paused);
        }else{
            this._priorityIn(this._updatesPosList, callback, target, priority, paused);
        }
    },
    _removeHashElement:function (element) {
        delete this._hashForTimers[element.target.__instanceId];
        cc.arrayRemoveObject(this._arrayForTimers, element);
        element.Timer = null;
        element.target = null;
        element = null;
    },
    _removeUpdateFromHash:function (entry) {
        var self = this, element = self._hashForUpdates[entry.target.__instanceId];
        if (element) {
            cc.arrayRemoveObject(element.list, element.entry);
            delete self._hashForUpdates[element.target.__instanceId];
            element.entry = null;
            element.target = null;
        }
    },
    _priorityIn:function (ppList, callback,  target, priority, paused) {
        var self = this,
            listElement = new cc.ListEntry(null, null, callback, target, priority, paused, false);
        if (!ppList) {
            ppList = [];
            ppList.push(listElement);
        } else {
            var index2Insert = ppList.length - 1;
            for(var i = 0; i <= index2Insert; i++){
                if (priority < ppList[i].priority) {
                    index2Insert = i;
                    break;
                }
            }
            ppList.splice(i, 0, listElement);
        }
        self._hashForUpdates[target.__instanceId] = new cc.HashUpdateEntry(ppList, listElement, target, null);
        return ppList;
    },
    _appendIn:function (ppList, callback, target, paused) {
        var self = this, listElement = new cc.ListEntry(null, null, callback, target, 0, paused, false);
        ppList.push(listElement);
        self._hashForUpdates[target.__instanceId] = new cc.HashUpdateEntry(ppList, listElement, target, null, null);
    },
    setTimeScale:function (timeScale) {
        this._timeScale = timeScale;
    },
    getTimeScale:function () {
        return this._timeScale;
    },
    update:function (dt) {
        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<len; i++){
            entry = list[i];
            if(!entry.paused && !entry.markedForDeletion)
                entry.callback(dt);
        }
        for(i=0, list=this._updates0List, len=list.length; i<len; i++){
            entry = list[i];
            if (!entry.paused && !entry.markedForDeletion)
                entry.callback(dt);
        }
        for(i=0, list=this._updatesPosList, len=list.length; i<len; i++){
            entry = list[i];
            if (!entry.paused && !entry.markedForDeletion)
                entry.callback(dt);
        }
        var elt, arr = this._arrayForTimers;
        for(i=0; i<arr.length; i++){
            elt = arr[i];
            this._currentTarget = elt;
            this._currentTargetSalvaged = false;
            if (!elt.paused){
                for (elt.timerIndex = 0; elt.timerIndex < elt.timers.length; ++(elt.timerIndex)){
                    elt.currentTimer = elt.timers[elt.timerIndex];
                    elt.currentTimerSalvaged = false;
                    elt.currentTimer.update(dt);
                    elt.currentTimer = null;
                }
            }
            if (this._currentTargetSalvaged && this._currentTarget.timers.length === 0)
                this._removeHashElement(this._currentTarget);
        }
        for(i=0,list=this._updatesNegList; i<list.length; ){
            entry = list[i];
            if(entry.markedForDeletion)
                this._removeUpdateFromHash(entry);
            else
                i++;
        }
        for(i=0, list=this._updates0List; i<list.length; ){
            entry = list[i];
            if (entry.markedForDeletion)
                this._removeUpdateFromHash(entry);
            else
                i++;
        }
        for(i=0, list=this._updatesPosList; i<list.length; ){
            entry = list[i];
            if (entry.markedForDeletion)
                this._removeUpdateFromHash(entry);
            else
                i++;
        }
        this._updateHashLocked = false;
        this._currentTarget = null;
    },
    scheduleCallbackForTarget: function(target, callback_fn, interval, repeat, delay, paused){
        this.schedule(callback_fn, target, interval, repeat, delay, paused, target.__instanceId + "");
    },
    schedule: function(callback, target, interval, repeat, delay, paused, key){
        var isSelector = false;
        if(typeof callback !== "function"){
            var selector = callback;
            isSelector = true;
        }
        if(isSelector === false){
            if(arguments.length === 4 || arguments.length === 5){
                key = delay;
                paused = repeat;
                delay = 0;
                repeat = cc.REPEAT_FOREVER;
            }
        }else{
            if(arguments.length === 4){
                paused = repeat;
                repeat = cc.REPEAT_FOREVER;
                delay = 0;
            }
        }
        if (key === undefined) {
            key = target.__instanceId + "";
        }
        cc.assert(target, cc._LogInfos.Scheduler_scheduleCallbackForTarget_3);
        var element = this._hashForTimers[target.__instanceId];
        if(!element){
            element = new cc.HashTimerEntry(null, target, 0, null, null, paused, null);
            this._arrayForTimers.push(element);
            this._hashForTimers[target.__instanceId] = element;
        }else{
            cc.assert(element.paused === paused, "");
        }
        var timer, i;
        if (element.timers == null) {
            element.timers = [];
        } else if(isSelector === false) {
            for (i = 0; i < element.timers.length; i++) {
                timer = element.timers[i];
                if (callback === timer._callback) {
                    cc.log(cc._LogInfos.Scheduler_scheduleCallbackForTarget, timer.getInterval().toFixed(4), interval.toFixed(4));
                    timer._interval = interval;
                    return;
                }
            }
        }else{
            for (i = 0; i < element.timers.length; ++i){
                timer =element.timers[i];
                if (timer && selector === timer.getSelector()){
                    cc.log("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", timer.getInterval(), interval);
                    timer.setInterval(interval);
                    return;
                }
            }
        }
        if(isSelector === false){
            timer = new cc.TimerTargetCallback();
            timer.initWithCallback(this, callback, target, key, interval, repeat, delay);
            element.timers.push(timer);
        }else{
            timer = new cc.TimerTargetSelector();
            timer.initWithSelector(this, selector, target, interval, repeat, delay);
            element.timers.push(timer);
        }
    },
    scheduleUpdate: function(target, priority, paused){
        this._schedulePerFrame(function(dt){
            target.update(dt);
        }, target, priority, paused);
    },
    _getUnscheduleMark: function(key, timer){
        switch (typeof key){
            case "number":
            case "string":
                return key === timer.getKey();
            case "function":
                return key === timer._callback;
            default:
                return key === timer.getSelector();
        }
    },
    unschedule: function(key, target){
        if (!target || !key)
            return;
        var self = this, element = self._hashForTimers[target.__instanceId];
        if (element) {
            var timers = element.timers;
            for(var i = 0, li = timers.length; i < li; i++){
                var timer = timers[i];
                if (this._getUnscheduleMark(key, timer)) {
                    if ((timer === element.currentTimer) && (!element.currentTimerSalvaged)) {
                        element.currentTimerSalvaged = true;
                    }
                    timers.splice(i, 1);
                    if (element.timerIndex >= i) {
                        element.timerIndex--;
                    }
                    if (timers.length === 0) {
                        if (self._currentTarget === element) {
                            self._currentTargetSalvaged = true;
                        } else {
                            self._removeHashElement(element);
                        }
                    }
                    return;
                }
            }
        }
    },
    unscheduleUpdate: function(target){
        if (target == null)
            return;
        var element = this._hashForUpdates[target.__instanceId];
        if (element){
            if (this._updateHashLocked){
                element.entry.markedForDeletion = true;
            }else{
                this._removeUpdateFromHash(element.entry);
            }
        }
    },
    unscheduleAllForTarget: function(target){
        if (target == null){
            return;
        }
        var element = this._hashForTimers[target.__instanceId];
        if (element){
            if (element.timers.indexOf(element.currentTimer) > -1
                && (! element.currentTimerSalvaged)){
                element.currentTimerSalvaged = true;
            }
            element.timers.length = 0;
            if (this._currentTarget === element){
                this._currentTargetSalvaged = true;
            }else{
                this._removeHashElement(element);
            }
        }
        this.unscheduleUpdate(target);
    },
    unscheduleAll: function(){
        this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
    },
    unscheduleAllWithMinPriority: function(minPriority){
        var i, element, arr = this._arrayForTimers;
        for(i=arr.length-1; i>=0; i--){
            element = arr[i];
            this.unscheduleAllForTarget(element.target);
        }
        var entry;
        var temp_length = 0;
        if(minPriority < 0){
            for(i=0; i<this._updatesNegList.length; ){
                temp_length = this._updatesNegList.length;
                entry = this._updatesNegList[i];
                if(entry && entry.priority >= minPriority)
                    this.unscheduleUpdate(entry.target);
                if (temp_length == this._updatesNegList.length)
                    i++;
            }
        }
        if(minPriority <= 0){
            for(i=0; i<this._updates0List.length; ){
                temp_length = this._updates0List.length;
                entry = this._updates0List[i];
                if (entry)
                    this.unscheduleUpdate(entry.target);
                if (temp_length == this._updates0List.length)
                    i++;
            }
        }
        for(i=0; i<this._updatesPosList.length; ){
            temp_length = this._updatesPosList.length;
            entry = this._updatesPosList[i];
            if(entry && entry.priority >= minPriority)
                this.unscheduleUpdate(entry.target);
            if (temp_length == this._updatesPosList.length)
                i++;
        }
    },
    isScheduled: function(key, target){
        cc.assert(key, "Argument key must not be empty");
        cc.assert(target, "Argument target must be non-nullptr");
        var element = this._hashForUpdates[target.__instanceId];
        if (!element){
            return false;
        }
        if (element.timers == null){
            return false;
        }else{
            var timers = element.timers;
            for (var i = 0; i < timers.length; ++i){
                var timer =  timers[i];
                if (key === timer.getKey()){
                    return true;
                }
            }
            return false;
        }
    },
    pauseAllTargets:function () {
        return this.pauseAllTargetsWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
    },
    pauseAllTargetsWithMinPriority:function (minPriority) {
        var idsWithSelectors = [];
        var self = this, element, locArrayForTimers = self._arrayForTimers;
        var i, li;
        for(i = 0, li = locArrayForTimers.length; i < li; i++){
            element = locArrayForTimers[i];
            if (element) {
                element.paused = true;
                idsWithSelectors.push(element.target);
            }
        }
        var entry;
        if(minPriority < 0){
            for(i=0; i<this._updatesNegList.length; i++){
                entry = this._updatesNegList[i];
                if (entry) {
                    if(entry.priority >= minPriority){
                        entry.paused = true;
                        idsWithSelectors.push(entry.target);
                    }
                }
            }
        }
        if(minPriority <= 0){
            for(i=0; i<this._updates0List.length; i++){
                entry = this._updates0List[i];
                if (entry) {
                    entry.paused = true;
                    idsWithSelectors.push(entry.target);
                }
            }
        }
        for(i=0; i<this._updatesPosList.length; i++){
            entry = this._updatesPosList[i];
            if (entry) {
                if(entry.priority >= minPriority){
                    entry.paused = true;
                    idsWithSelectors.push(entry.target);
                }
            }
        }
        return idsWithSelectors;
    },
    resumeTargets:function (targetsToResume) {
        if (!targetsToResume)
            return;
        for (var i = 0; i < targetsToResume.length; i++) {
            this.resumeTarget(targetsToResume[i]);
        }
    },
    pauseTarget:function (target) {
        cc.assert(target, cc._LogInfos.Scheduler_pauseTarget);
        var self = this, element = self._hashForTimers[target.__instanceId];
        if (element) {
            element.paused = true;
        }
        var elementUpdate = self._hashForUpdates[target.__instanceId];
        if (elementUpdate) {
            elementUpdate.entry.paused = true;
        }
    },
    resumeTarget:function (target) {
        cc.assert(target, cc._LogInfos.Scheduler_resumeTarget);
        var self = this, element = self._hashForTimers[target.__instanceId];
        if (element) {
            element.paused = false;
        }
        var elementUpdate = self._hashForUpdates[target.__instanceId];
        if (elementUpdate) {
            elementUpdate.entry.paused = false;
        }
    },
    isTargetPaused:function (target) {
        cc.assert(target, cc._LogInfos.Scheduler_isTargetPaused);
        var element = this._hashForTimers[target.__instanceId];
        if (element) {
            return element.paused;
        }
        var elementUpdate = this._hashForUpdates[target.__instanceId];
        if (elementUpdate) {
            return elementUpdate.entry.paused;
        }
        return false;
    },
    scheduleUpdateForTarget: function(target, priority, paused){
        this.scheduleUpdate(target, priority, paused);
    },
    unscheduleCallbackForTarget:function (target, callback) {
        this.unschedule(callback, target);
    },
    unscheduleUpdateForTarget:function (target) {
        this.unscheduleUpdate(target);
    },
    unscheduleAllCallbacksForTarget: function(target){
        this.unschedule(target.__instanceId + "", target);
    },
    unscheduleAllCallbacks: function(){
        this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
    },
    unscheduleAllCallbacksWithMinPriority:function (minPriority) {
        this.unscheduleAllWithMinPriority(minPriority);
    }
});
cc.Scheduler.PRIORITY_SYSTEM = (-2147483647 - 1);
cc._tmp.PrototypeLabelTTF = function () {
    var _p = cc.LabelTTF.prototype;
    cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
    cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
    _p.string;
    cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
    _p.textAlign;
    cc.defineGetterSetter(_p, "textAlign", _p.getHorizontalAlignment, _p.setHorizontalAlignment);
    _p.verticalAlign;
    cc.defineGetterSetter(_p, "verticalAlign", _p.getVerticalAlignment, _p.setVerticalAlignment);
    _p.fontSize;
    cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
    _p.fontName;
    cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
    _p.font;
    cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
    _p.boundingSize;
    _p.boundingWidth;
    cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
    _p.boundingHeight;
    cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
    _p.fillStyle;
    cc.defineGetterSetter(_p, "fillStyle", _p._getFillStyle, _p.setFontFillColor);
    _p.strokeStyle;
    cc.defineGetterSetter(_p, "strokeStyle", _p._getStrokeStyle, _p._setStrokeStyle);
    _p.lineWidth;
    cc.defineGetterSetter(_p, "lineWidth", _p._getLineWidth, _p._setLineWidth);
    _p.shadowOffset;
    _p.shadowOffsetX;
    cc.defineGetterSetter(_p, "shadowOffsetX", _p._getShadowOffsetX, _p._setShadowOffsetX);
    _p.shadowOffsetY;
    cc.defineGetterSetter(_p, "shadowOffsetY", _p._getShadowOffsetY, _p._setShadowOffsetY);
    _p.shadowOpacity;
    cc.defineGetterSetter(_p, "shadowOpacity", _p._getShadowOpacity, _p._setShadowOpacity);
    _p.shadowBlur;
    cc.defineGetterSetter(_p, "shadowBlur", _p._getShadowBlur, _p._setShadowBlur);
};
cc.LabelTTF = cc.Sprite.extend({
    _dimensions: null,
    _hAlignment: cc.TEXT_ALIGNMENT_CENTER,
    _vAlignment: cc.VERTICAL_TEXT_ALIGNMENT_TOP,
    _fontName: null,
    _fontSize: 0.0,
    _string: "",
    _originalText: null,
    _onCacheCanvasMode: true,
    _shadowEnabled: false,
    _shadowOffset: null,
    _shadowOpacity: 0,
    _shadowBlur: 0,
    _shadowColor: null,
    _strokeEnabled: false,
    _strokeColor: null,
    _strokeSize: 0,
    _textFillColor: null,
    _strokeShadowOffsetX: 0,
    _strokeShadowOffsetY: 0,
    _needUpdateTexture: false,
    _lineWidths: null,
    _className: "LabelTTF",
    _fontStyle: "normal",
    _fontWeight: "normal",
    _lineHeight: "normal",
    initWithString: function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
        var strInfo;
        if (label)
            strInfo = label + "";
        else
            strInfo = "";
        fontSize = fontSize || 16;
        dimensions = dimensions || cc.size(0, 0);
        hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT;
        vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP;
        this._opacityModifyRGB = false;
        this._dimensions = cc.size(dimensions.width, dimensions.height);
        this._fontName = fontName || "Arial";
        this._hAlignment = hAlignment;
        this._vAlignment = vAlignment;
        this._fontSize = fontSize;
        this._renderCmd._setFontStyle(this._fontName, fontSize, this._fontStyle, this._fontWeight);
        this.string = strInfo;
        this._renderCmd._setColorsString();
        this._renderCmd._updateTexture();
        this._setUpdateTextureDirty();
        this._scaleX = this._scaleY = 1 / cc.view.getDevicePixelRatio();
        return true;
    },
    _setUpdateTextureDirty: function () {
        this._needUpdateTexture = true;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.textDirty);
    },
    ctor: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
        cc.Sprite.prototype.ctor.call(this);
        this._dimensions = cc.size(0, 0);
        this._hAlignment = cc.TEXT_ALIGNMENT_LEFT;
        this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
        this._opacityModifyRGB = false;
        this._fontName = "Arial";
        this._shadowEnabled = false;
        this._shadowOffset = cc.p(0, 0);
        this._shadowOpacity = 0;
        this._shadowBlur = 0;
        this._strokeEnabled = false;
        this._strokeColor = cc.color(255, 255, 255, 255);
        this._strokeSize = 0;
        this._textFillColor = cc.color(255, 255, 255, 255);
        this._strokeShadowOffsetX = 0;
        this._strokeShadowOffsetY = 0;
        this._needUpdateTexture = false;
        this._lineWidths = [];
        this._renderCmd._setColorsString();
        this._textureLoaded = true;
        if (fontName && fontName instanceof cc.FontDefinition) {
            this.initWithStringAndTextDefinition(text, fontName);
        } else {
            cc.LabelTTF.prototype.initWithString.call(this, text, fontName, fontSize, dimensions, hAlignment, vAlignment);
        }
    },
    init: function () {
        return this.initWithString(" ", this._fontName, this._fontSize);
    },
    description: function () {
        return "<cc.LabelTTF | FontName =" + this._fontName + " FontSize = " + this._fontSize.toFixed(1) + ">";
    },
    getLineHeight: function () {
        return !this._lineHeight || this._lineHeight.charAt ?
            this._renderCmd._getFontClientHeight() :
            this._lineHeight || this._renderCmd._getFontClientHeight();
    },
    setLineHeight: function (lineHeight) {
        this._lineHeight = lineHeight;
    },
    getString: function () {
        return this._string;
    },
    getHorizontalAlignment: function () {
        return this._hAlignment;
    },
    getVerticalAlignment: function () {
        return this._vAlignment;
    },
    getDimensions: function () {
        return cc.size(this._dimensions);
    },
    getFontSize: function () {
        return this._fontSize;
    },
    getFontName: function () {
        return this._fontName;
    },
    initWithStringAndTextDefinition: function (text, textDefinition) {
        this._updateWithTextDefinition(textDefinition, false);
        this.string = text;
        return true;
    },
    setTextDefinition: function (theDefinition) {
        if (theDefinition)
            this._updateWithTextDefinition(theDefinition, true);
    },
    getTextDefinition: function () {
        return this._prepareTextDefinition(false);
    },
    enableShadow: function (a, b, c, d) {
        if (a.r != null && a.g != null && a.b != null && a.a != null) {
            this._enableShadow(a, b, c);
        } else {
            this._enableShadowNoneColor(a, b, c, d);
        }
    },
    _enableShadowNoneColor: function (shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur) {
        shadowOpacity = shadowOpacity || 0.5;
        if (false === this._shadowEnabled)
            this._shadowEnabled = true;
        var locShadowOffset = this._shadowOffset;
        if (locShadowOffset && (locShadowOffset.x !== shadowOffsetX) || (locShadowOffset._y !== shadowOffsetY)) {
            locShadowOffset.x = shadowOffsetX;
            locShadowOffset.y = shadowOffsetY;
        }
        if (this._shadowOpacity !== shadowOpacity) {
            this._shadowOpacity = shadowOpacity;
        }
        this._renderCmd._setColorsString();
        if (this._shadowBlur !== shadowBlur)
            this._shadowBlur = shadowBlur;
        this._setUpdateTextureDirty();
    },
    _enableShadow: function (shadowColor, offset, blurRadius) {
        if (!this._shadowColor) {
            this._shadowColor = cc.color(255, 255, 255, 128);
        }
        this._shadowColor.r = shadowColor.r;
        this._shadowColor.g = shadowColor.g;
        this._shadowColor.b = shadowColor.b;
        var x, y, a, b;
        x = offset.width || offset.x || 0;
        y = offset.height || offset.y || 0;
        a = (shadowColor.a != null) ? (shadowColor.a / 255) : 0.5;
        b = blurRadius;
        this._enableShadowNoneColor(x, y, a, b);
    },
    _getShadowOffsetX: function () {
        return this._shadowOffset.x;
    },
    _setShadowOffsetX: function (x) {
        if (false === this._shadowEnabled)
            this._shadowEnabled = true;
        if (this._shadowOffset.x !== x) {
            this._shadowOffset.x = x;
            this._setUpdateTextureDirty();
        }
    },
    _getShadowOffsetY: function () {
        return this._shadowOffset._y;
    },
    _setShadowOffsetY: function (y) {
        if (false === this._shadowEnabled)
            this._shadowEnabled = true;
        if (this._shadowOffset._y !== y) {
            this._shadowOffset._y = y;
            this._setUpdateTextureDirty();
        }
    },
    _getShadowOffset: function () {
        return cc.p(this._shadowOffset.x, this._shadowOffset.y);
    },
    _setShadowOffset: function (offset) {
        if (false === this._shadowEnabled)
            this._shadowEnabled = true;
        if (this._shadowOffset.x !== offset.x || this._shadowOffset.y !== offset.y) {
            this._shadowOffset.x = offset.x;
            this._shadowOffset.y = offset.y;
            this._setUpdateTextureDirty();
        }
    },
    _getShadowOpacity: function () {
        return this._shadowOpacity;
    },
    _setShadowOpacity: function (shadowOpacity) {
        if (false === this._shadowEnabled)
            this._shadowEnabled = true;
        if (this._shadowOpacity !== shadowOpacity) {
            this._shadowOpacity = shadowOpacity;
            this._renderCmd._setColorsString();
            this._setUpdateTextureDirty();
        }
    },
    _getShadowBlur: function () {
        return this._shadowBlur;
    },
    _setShadowBlur: function (shadowBlur) {
        if (false === this._shadowEnabled)
            this._shadowEnabled = true;
        if (this._shadowBlur !== shadowBlur) {
            this._shadowBlur = shadowBlur;
            this._setUpdateTextureDirty();
        }
    },
    disableShadow: function () {
        if (this._shadowEnabled) {
            this._shadowEnabled = false;
            this._setUpdateTextureDirty();
        }
    },
    enableStroke: function (strokeColor, strokeSize) {
        if (this._strokeEnabled === false)
            this._strokeEnabled = true;
        var locStrokeColor = this._strokeColor;
        if ((locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b)) {
            locStrokeColor.r = strokeColor.r;
            locStrokeColor.g = strokeColor.g;
            locStrokeColor.b = strokeColor.b;
            this._renderCmd._setColorsString();
        }
        if (this._strokeSize !== strokeSize)
            this._strokeSize = strokeSize || 0;
        this._setUpdateTextureDirty();
    },
    _getStrokeStyle: function () {
        return this._strokeColor;
    },
    _setStrokeStyle: function (strokeStyle) {
        if (this._strokeEnabled === false)
            this._strokeEnabled = true;
        var locStrokeColor = this._strokeColor;
        if ((locStrokeColor.r !== strokeStyle.r) || (locStrokeColor.g !== strokeStyle.g) || (locStrokeColor.b !== strokeStyle.b)) {
            locStrokeColor.r = strokeStyle.r;
            locStrokeColor.g = strokeStyle.g;
            locStrokeColor.b = strokeStyle.b;
            this._renderCmd._setColorsString();
            this._setUpdateTextureDirty();
        }
    },
    _getLineWidth: function () {
        return this._strokeSize;
    },
    _setLineWidth: function (lineWidth) {
        if (this._strokeEnabled === false)
            this._strokeEnabled = true;
        if (this._strokeSize !== lineWidth) {
            this._strokeSize = lineWidth || 0;
            this._setUpdateTextureDirty();
        }
    },
    disableStroke: function () {
        if (this._strokeEnabled) {
            this._strokeEnabled = false;
            this._setUpdateTextureDirty();
        }
    },
    setFontFillColor: function (fillColor) {
        var locTextFillColor = this._textFillColor;
        if (locTextFillColor.r !== fillColor.r || locTextFillColor.g !== fillColor.g || locTextFillColor.b !== fillColor.b) {
            locTextFillColor.r = fillColor.r;
            locTextFillColor.g = fillColor.g;
            locTextFillColor.b = fillColor.b;
            this._renderCmd._setColorsString();
            this._needUpdateTexture = true;
        }
    },
    _getFillStyle: function () {
        return this._textFillColor;
    },
    _updateWithTextDefinition: function (textDefinition, mustUpdateTexture) {
        if (textDefinition.fontDimensions) {
            this._dimensions.width = textDefinition.boundingWidth;
            this._dimensions.height = textDefinition.boundingHeight;
        } else {
            this._dimensions.width = 0;
            this._dimensions.height = 0;
        }
        this._hAlignment = textDefinition.textAlign;
        this._vAlignment = textDefinition.verticalAlign;
        this._fontName = textDefinition.fontName;
        this._fontSize = textDefinition.fontSize || 12;
        if(textDefinition.lineHeight)
            this._lineHeight = textDefinition.lineHeight
        else
            this._lineHeight = this._fontSize;
        this._renderCmd._setFontStyle(textDefinition);
        if (textDefinition.shadowEnabled)
            this.enableShadow(textDefinition.shadowOffsetX,
                textDefinition.shadowOffsetY,
                textDefinition.shadowOpacity,
                textDefinition.shadowBlur);
        if (textDefinition.strokeEnabled)
            this.enableStroke(textDefinition.strokeStyle, textDefinition.lineWidth);
        this.setFontFillColor(textDefinition.fillStyle);
        if (mustUpdateTexture)
            this._renderCmd._updateTexture();
        var flags = cc.Node._dirtyFlags;
        this._renderCmd.setDirtyFlag(flags.colorDirty|flags.opacityDirty|flags.textDirty);
    },
    _prepareTextDefinition: function (adjustForResolution) {
        var texDef = new cc.FontDefinition();
        if (adjustForResolution) {
            texDef.fontSize = this._fontSize;
            texDef.boundingWidth = cc.contentScaleFactor() * this._dimensions.width;
            texDef.boundingHeight = cc.contentScaleFactor() * this._dimensions.height;
        } else {
            texDef.fontSize = this._fontSize;
            texDef.boundingWidth = this._dimensions.width;
            texDef.boundingHeight = this._dimensions.height;
        }
        texDef.fontName = this._fontName;
        texDef.textAlign = this._hAlignment;
        texDef.verticalAlign = this._vAlignment;
        if (this._strokeEnabled) {
            texDef.strokeEnabled = true;
            var locStrokeColor = this._strokeColor;
            texDef.strokeStyle = cc.color(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b);
            texDef.lineWidth = this._strokeSize;
        } else
            texDef.strokeEnabled = false;
        if (this._shadowEnabled) {
            texDef.shadowEnabled = true;
            texDef.shadowBlur = this._shadowBlur;
            texDef.shadowOpacity = this._shadowOpacity;
            texDef.shadowOffsetX = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.x;
            texDef.shadowOffsetY = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.y;
        } else
            texDef._shadowEnabled = false;
        var locTextFillColor = this._textFillColor;
        texDef.fillStyle = cc.color(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b);
        return texDef;
    },
    getScale: function () {
        if (this._scaleX !== this._scaleY)
            cc.log(cc._LogInfos.Node_getScale);
        return this._scaleX * cc.view.getDevicePixelRatio();
    },
    setScale: function (scale, scaleY) {
        this._scaleX = scale / cc.view.getDevicePixelRatio();
        this._scaleY = ((scaleY || scaleY === 0) ? scaleY : scale) /
            cc.view.getDevicePixelRatio();
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getScaleX: function () {
        return this._scaleX * cc.view.getDevicePixelRatio();
    },
    setScaleX: function (newScaleX) {
        this._scaleX = newScaleX / cc.view.getDevicePixelRatio();
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getScaleY: function () {
        return this._scaleY * cc.view.getDevicePixelRatio();
    },
    setScaleY: function (newScaleY) {
        this._scaleY = newScaleY / cc.view.getDevicePixelRatio();
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    setString: function (text) {
        text = String(text);
        if (this._originalText !== text) {
            this._originalText = text + "";
            this._updateString();
            this._setUpdateTextureDirty();
            this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        }
    },
    _updateString: function () {
        if ((!this._string || this._string === "") && this._string !== this._originalText)
            cc.renderer.childrenOrderDirty = true;
        this._string = this._originalText;
    },
    setHorizontalAlignment: function (alignment) {
        if (alignment !== this._hAlignment) {
            this._hAlignment = alignment;
            this._setUpdateTextureDirty();
        }
    },
    setVerticalAlignment: function (verticalAlignment) {
        if (verticalAlignment !== this._vAlignment) {
            this._vAlignment = verticalAlignment;
            this._setUpdateTextureDirty();
        }
    },
    setDimensions: function (dim, height) {
        var width;
        if (height === undefined) {
            width = dim.width;
            height = dim.height;
        } else
            width = dim;
        if (width !== this._dimensions.width || height !== this._dimensions.height) {
            this._dimensions.width = width;
            this._dimensions.height = height;
            this._updateString();
            this._setUpdateTextureDirty();
        }
    },
    _getBoundingWidth: function () {
        return this._dimensions.width;
    },
    _setBoundingWidth: function (width) {
        if (width !== this._dimensions.width) {
            this._dimensions.width = width;
            this._updateString();
            this._setUpdateTextureDirty();
        }
    },
    _getBoundingHeight: function () {
        return this._dimensions.height;
    },
    _setBoundingHeight: function (height) {
        if (height !== this._dimensions.height) {
            this._dimensions.height = height;
            this._updateString();
            this._setUpdateTextureDirty();
        }
    },
    setFontSize: function (fontSize) {
        if (this._fontSize !== fontSize) {
            this._fontSize = fontSize;
            this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
            this._setUpdateTextureDirty();
        }
    },
    setFontName: function (fontName) {
        if (this._fontName && this._fontName !== fontName) {
            this._fontName = fontName;
            this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
            this._setUpdateTextureDirty();
        }
    },
    _getFont: function () {
        return this._renderCmd._getFontStyle();
    },
    _setFont: function (fontStyle) {
        var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
        if (res) {
            this._fontSize = parseInt(res[1]);
            this._fontName = res[2];
            this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
            this._setUpdateTextureDirty();
        }
    },
    getContentSize: function () {
        if (this._needUpdateTexture)
            this._renderCmd._updateTTF();
        return cc.size(this._contentSize);
    },
    _getWidth: function () {
        if (this._needUpdateTexture)
            this._renderCmd._updateTTF();
        return this._contentSize.width;
    },
    _getHeight: function () {
        if (this._needUpdateTexture)
            this._renderCmd._updateTTF();
        return this._contentSize.height;
    },
    setTextureRect: function (rect, rotated, untrimmedSize) {
        cc.Sprite.prototype.setTextureRect.call(this, rect, rotated, untrimmedSize, false);
    },
    setDrawMode: function (onCacheMode) {
        this._onCacheCanvasMode = onCacheMode;
    },
    _createRenderCmd: function () {
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new cc.LabelTTF.WebGLRenderCmd(this);
        else if (this._onCacheCanvasMode)
            return new cc.LabelTTF.CacheCanvasRenderCmd(this);
        else
            return new cc.LabelTTF.CanvasRenderCmd(this);
    },
    _setFontStyle: function(fontStyle){
        if (this._fontStyle !== fontStyle) {
            this._fontStyle = fontStyle;
            this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
            this._setUpdateTextureDirty();
        }
    },
    _getFontStyle: function(){
        return this._fontStyle;
    },
    _setFontWeight: function(fontWeight){
        if (this._fontWeight !== fontWeight) {
            this._fontWeight = fontWeight;
            this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
            this._setUpdateTextureDirty();
        }
    },
    _getFontWeight: function(){
        return this._fontWeight;
    }
});
cc.assert(cc.isFunction(cc._tmp.PrototypeLabelTTF), cc._LogInfos.MissingFile, "LabelTTFPropertyDefine.js");
cc._tmp.PrototypeLabelTTF();
delete cc._tmp.PrototypeLabelTTF;
cc.LabelTTF._fontStyleRE = /^(\d+)px\s+['"]?([\w\s\d]+)['"]?$/;
cc.LabelTTF.create = function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
    return new cc.LabelTTF(text, fontName, fontSize, dimensions, hAlignment, vAlignment);
};
cc.LabelTTF.createWithFontDefinition = cc.LabelTTF.create;
cc.LabelTTF.__labelHeightDiv = document.createElement("div");
cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial";
cc.LabelTTF.__labelHeightDiv.style.position = "absolute";
cc.LabelTTF.__labelHeightDiv.style.left = "-100px";
cc.LabelTTF.__labelHeightDiv.style.top = "-100px";
cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal";
document.body ?
    document.body.appendChild(cc.LabelTTF.__labelHeightDiv) :
    window.addEventListener('load', function () {
        this.removeEventListener('load', arguments.callee, false);
        document.body.appendChild(cc.LabelTTF.__labelHeightDiv);
    }, false);
cc.LabelTTF.__getFontHeightByDiv = function (fontName, fontSize) {
    var clientHeight, labelDiv = cc.LabelTTF.__labelHeightDiv;
    if(fontName instanceof cc.FontDefinition){
        var fontDef = fontName;
        clientHeight = cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()];
        if (clientHeight > 0) return clientHeight;
        labelDiv.innerHTML = "ajghl~!";
        labelDiv.style.fontFamily = fontDef.fontName;
        labelDiv.style.fontSize = fontDef.fontSize + "px";
        labelDiv.style.fontStyle = fontDef.fontStyle;
        labelDiv.style.fontWeight = fontDef.fontWeight;
        clientHeight = labelDiv.clientHeight;
        cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()] = clientHeight;
        labelDiv.innerHTML = "";
    }
    else {
        clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize];
        if (clientHeight > 0) return clientHeight;
        labelDiv.innerHTML = "ajghl~!";
        labelDiv.style.fontFamily = fontName;
        labelDiv.style.fontSize = fontSize + "px";
        clientHeight = labelDiv.clientHeight;
        cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight;
        labelDiv.innerHTML = "";
    }
    return clientHeight;
};
cc.LabelTTF.__fontHeightCache = {};
cc.LabelTTF._textAlign = ["left", "center", "right"];
cc.LabelTTF._textBaseline = ["top", "middle", "bottom"];
cc.LabelTTF.wrapInspection = true;
cc.LabelTTF._wordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\S)/;
cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>、‘“》?。,!]/;
cc.LabelTTF._lastWordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\S)$/;
cc.LabelTTF._lastEnglish = /[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+$/;
cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/;
(function() {
    cc.LabelTTF.RenderCmd = function () {
        this._fontClientHeight = 18;
        this._fontStyleStr = "";
        this._shadowColorStr = "rgba(128, 128, 128, 0.5)";
        this._strokeColorStr = "";
        this._fillColorStr = "rgba(255,255,255,1)";
        this._labelCanvas = null;
        this._labelContext = null;
        this._lineWidths = [];
        this._strings = [];
        this._isMultiLine = false;
        this._status = [];
        this._renderingIndex = 0;
        this._texRect = cc.rect();
        this._canUseDirtyRegion = true;
    };
    var proto = cc.LabelTTF.RenderCmd.prototype;
    proto.constructor = cc.LabelTTF.RenderCmd;
    proto._setFontStyle = function (fontNameOrFontDef, fontSize, fontStyle, fontWeight) {
        if(fontNameOrFontDef instanceof cc.FontDefinition){
            this._fontStyleStr = fontNameOrFontDef._getCanvasFontStr();
            this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontNameOrFontDef);
        }else {
            var deviceFontSize = fontSize * cc.view.getDevicePixelRatio();
            this._fontStyleStr = fontStyle + " " + fontWeight + " " + deviceFontSize + "px '" + fontNameOrFontDef + "'";
            this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontNameOrFontDef, fontSize);
        }
    };
    proto._getFontStyle = function () {
        return this._fontStyleStr;
    };
    proto._getFontClientHeight = function () {
        return this._fontClientHeight;
    };
    proto._updateColor = function(){
        this._setColorsString();
        this._updateTexture();
    };
    proto._setColorsString = function () {
        var locDisplayColor = this._displayedColor, node = this._node,
            locShadowColor = node._shadowColor || this._displayedColor;
        var locStrokeColor = node._strokeColor, locFontFillColor = node._textFillColor;
        var dr = locDisplayColor.r / 255, dg = locDisplayColor.g / 255, db = locDisplayColor.b / 255;
        this._shadowColorStr = "rgba(" + (0 | (dr * locShadowColor.r)) + "," + (0 | ( dg * locShadowColor.g)) + ","
            + (0 | (db * locShadowColor.b)) + "," + node._shadowOpacity + ")";
        this._fillColorStr = "rgba(" + (0 | (dr * locFontFillColor.r)) + "," + (0 | (dg * locFontFillColor.g)) + ","
            + (0 | (db * locFontFillColor.b)) + ", 1)";
        this._strokeColorStr = "rgba(" + (0 | (dr * locStrokeColor.r)) + "," + (0 | (dg * locStrokeColor.g)) + ","
            + (0 | (db * locStrokeColor.b)) + ", 1)";
    };
    var localBB = new cc.Rect();
    proto.getLocalBB = function () {
        var node = this._node;
        localBB.x = localBB.y = 0;
        var pixelRatio = cc.view.getDevicePixelRatio();
        localBB.width = node._getWidth() * pixelRatio;
        localBB.height = node._getHeight() * pixelRatio;
        return localBB;
    };
    proto._updateTTF = function () {
        var node = this._node;
        var pixelRatio = cc.view.getDevicePixelRatio();
        var locDimensionsWidth = node._dimensions.width * pixelRatio, i, strLength;
        var locLineWidth = this._lineWidths;
        locLineWidth.length = 0;
        this._isMultiLine = false;
        this._measureConfig();
        if (locDimensionsWidth !== 0) {
            this._strings = node._string.split('\n');
            for (i = 0; i < this._strings.length; i++) {
                this._checkWarp(this._strings, i, locDimensionsWidth);
            }
        } else {
            this._strings = node._string.split('\n');
            for (i = 0, strLength = this._strings.length; i < strLength; i++) {
                locLineWidth.push(this._measure(this._strings[i]));
            }
        }
        if (this._strings.length > 1)
            this._isMultiLine = true;
        var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0;
        if (node._strokeEnabled)
            locStrokeShadowOffsetX = locStrokeShadowOffsetY = node._strokeSize * 2;
        if (node._shadowEnabled) {
            var locOffsetSize = node._shadowOffset;
            locStrokeShadowOffsetX += Math.abs(locOffsetSize.x) * 2;
            locStrokeShadowOffsetY += Math.abs(locOffsetSize.y) * 2;
        }
        if (locDimensionsWidth === 0) {
            if (this._isMultiLine)
                locSize = cc.size(
                    Math.ceil(Math.max.apply(Math, locLineWidth) + locStrokeShadowOffsetX),
                    Math.ceil((this._fontClientHeight * pixelRatio * this._strings.length) + locStrokeShadowOffsetY));
            else
                locSize = cc.size(
                    Math.ceil(this._measure(node._string) + locStrokeShadowOffsetX),
                    Math.ceil(this._fontClientHeight * pixelRatio + locStrokeShadowOffsetY));
        } else {
            if (node._dimensions.height === 0) {
                if (this._isMultiLine)
                    locSize = cc.size(
                        Math.ceil(locDimensionsWidth + locStrokeShadowOffsetX),
                        Math.ceil((node.getLineHeight() * pixelRatio * this._strings.length) + locStrokeShadowOffsetY));
                else
                    locSize = cc.size(
                        Math.ceil(locDimensionsWidth + locStrokeShadowOffsetX),
                        Math.ceil(node.getLineHeight() * pixelRatio + locStrokeShadowOffsetY));
            } else {
                locSize = cc.size(
                    Math.ceil(locDimensionsWidth + locStrokeShadowOffsetX),
                    Math.ceil(node._dimensions.height * pixelRatio + locStrokeShadowOffsetY));
            }
        }
        if (node._getFontStyle() !== "normal") {
            locSize.width = Math.ceil(locSize.width + node._fontSize * 0.3);
        }
        if (this._strings.length === 0) {
            this._texRect.width = 1;
            this._texRect.height = locSize.height || 1;
        }
        else {
            this._texRect.width = locSize.width;
            this._texRect.height = locSize.height;
        }
        var nodeW = locSize.width / pixelRatio, nodeH = locSize.height / pixelRatio;
        node.setContentSize(nodeW, nodeH);
        node._strokeShadowOffsetX = locStrokeShadowOffsetX;
        node._strokeShadowOffsetY = locStrokeShadowOffsetY;
        var locAP = node._anchorPoint;
        this._anchorPointInPoints.x = (locStrokeShadowOffsetX * 0.5) + ((locSize.width - locStrokeShadowOffsetX) * locAP.x);
        this._anchorPointInPoints.y = (locStrokeShadowOffsetY * 0.5) + ((locSize.height - locStrokeShadowOffsetY) * locAP.y);
    };
    proto._saveStatus = function () {
        var node = this._node;
        var scale = cc.view.getDevicePixelRatio();
        var locStrokeShadowOffsetX = node._strokeShadowOffsetX, locStrokeShadowOffsetY = node._strokeShadowOffsetY;
        var locContentSizeHeight = node._contentSize.height * scale - locStrokeShadowOffsetY, locVAlignment = node._vAlignment,
            locHAlignment = node._hAlignment;
        var dx = locStrokeShadowOffsetX * 0.5,
            dy = locContentSizeHeight + locStrokeShadowOffsetY * 0.5;
        var xOffset = 0, yOffset = 0, OffsetYArray = [];
        var locContentWidth = node._contentSize.width * scale - locStrokeShadowOffsetX;
        var lineHeight = node.getLineHeight() * scale;
        var transformTop = (lineHeight - this._fontClientHeight * scale) / 2;
        if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT)
            xOffset += locContentWidth;
        else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER)
            xOffset += locContentWidth / 2;
        else
            xOffset += 0;
        if (this._isMultiLine) {
            var locStrLen = this._strings.length;
            if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM)
                yOffset = lineHeight - transformTop * 2 + locContentSizeHeight - lineHeight * locStrLen;
            else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
                yOffset = (lineHeight - transformTop * 2) / 2 + (locContentSizeHeight - lineHeight * locStrLen) / 2;
            for (var i = 0; i < locStrLen; i++) {
                var tmpOffsetY = -locContentSizeHeight + (lineHeight * i + transformTop) + yOffset;
                OffsetYArray.push(tmpOffsetY);
            }
        } else {
            if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) {
            } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
                yOffset -= locContentSizeHeight;
            } else {
                yOffset -= locContentSizeHeight * 0.5;
            }
            OffsetYArray.push(yOffset);
        }
        var tmpStatus = {
            contextTransform:cc.p(dx,dy),
            xOffset:xOffset,
            OffsetYArray:OffsetYArray
        };
        this._status.push(tmpStatus);
    };
    proto._drawTTFInCanvas = function (context) {
        if (!context)
            return;
        var locStatus = this._status.pop();
        context.setTransform(1, 0, 0, 1, locStatus.contextTransform.x, locStatus.contextTransform.y);
        var xOffset = locStatus.xOffset;
        var yOffsetArray = locStatus.OffsetYArray;
        this.drawLabels(context, xOffset, yOffsetArray);
    };
    proto._checkWarp = function (strArr, i, maxWidth) {
        var text = strArr[i];
        var allWidth = this._measure(text);
        if (allWidth > maxWidth && text.length > 1) {
            var fuzzyLen = text.length * ( maxWidth / allWidth ) | 0;
            var tmpText = text.substr(fuzzyLen);
            var width = allWidth - this._measure(tmpText);
            var sLine;
            var pushNum = 0;
            var checkWhile = 0;
            while (width > maxWidth && checkWhile++ < 100) {
                fuzzyLen *= maxWidth / width;
                fuzzyLen = fuzzyLen | 0;
                tmpText = text.substr(fuzzyLen);
                width = allWidth - this._measure(tmpText);
            }
            checkWhile = 0;
            while (width < maxWidth && checkWhile++ < 100) {
                if (tmpText) {
                    var exec = cc.LabelTTF._wordRex.exec(tmpText);
                    pushNum = exec ? exec[0].length : 1;
                    sLine = tmpText;
                }
                fuzzyLen = fuzzyLen + pushNum;
                tmpText = text.substr(fuzzyLen);
                width = allWidth - this._measure(tmpText);
            }
            fuzzyLen -= pushNum;
            if (fuzzyLen === 0) {
                fuzzyLen = 1;
                sLine = sLine.substr(1);
            }
            var sText = text.substr(0, fuzzyLen), result;
            if (cc.LabelTTF.wrapInspection) {
                if (cc.LabelTTF._symbolRex.test(sLine || tmpText)) {
                    result = cc.LabelTTF._lastWordRex.exec(sText);
                    fuzzyLen -= result ? result[0].length : 0;
                    if (fuzzyLen === 0) fuzzyLen = 1;
                    sLine = text.substr(fuzzyLen);
                    sText = text.substr(0, fuzzyLen);
                }
            }
            if (cc.LabelTTF._firsrEnglish.test(sLine)) {
                result = cc.LabelTTF._lastEnglish.exec(sText);
                if (result && sText !== result[0]) {
                    fuzzyLen -= result[0].length;
                    sLine = text.substr(fuzzyLen);
                    sText = text.substr(0, fuzzyLen);
                }
            }
            strArr[i] = sLine || tmpText;
            strArr.splice(i, 0, sText);
        }
    };
    proto.updateStatus = function () {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.textDirty)
            this._updateTexture();
        cc.Node.RenderCmd.prototype.updateStatus.call(this);
        if (this._dirtyFlag & flags.transformDirty){
            this.transform(this.getParentRenderCmd(), true);
            this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty ^ this._dirtyFlag;
        }
    };
    proto._syncStatus = function (parentCmd) {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.textDirty)
            this._updateTexture();
        cc.Node.RenderCmd.prototype._syncStatus.call(this, parentCmd);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL || locFlag & flags.transformDirty)
            this.transform(parentCmd);
    };
    proto.drawLabels = function (context, xOffset, yOffsetArray) {
        var node = this._node;
        if (node._shadowEnabled) {
            var locShadowOffset = node._shadowOffset;
            context.shadowColor = this._shadowColorStr;
            context.shadowOffsetX = locShadowOffset.x;
            context.shadowOffsetY = -locShadowOffset.y;
            context.shadowBlur = node._shadowBlur;
        }
        var locHAlignment = node._hAlignment,
            locVAlignment = node._vAlignment,
            locStrokeSize = node._strokeSize;
        if (context.font !== this._fontStyleStr)
            context.font = this._fontStyleStr;
        context.fillStyle = this._fillColorStr;
        var locStrokeEnabled = node._strokeEnabled;
        if (locStrokeEnabled) {
            context.lineWidth = locStrokeSize * 2;
            context.strokeStyle = this._strokeColorStr;
        }
        context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment];
        context.textAlign = cc.LabelTTF._textAlign[locHAlignment];
        var locStrLen = this._strings.length;
        for (var i = 0; i < locStrLen; i++) {
            var line = this._strings[i];
            if (locStrokeEnabled)
                context.strokeText(line, xOffset, yOffsetArray[i]);
            context.fillText(line, xOffset, yOffsetArray[i]);
        }
        cc.g_NumberOfDraws++;
    };
})();
(function(){
    cc.LabelTTF.CacheRenderCmd = function (renderable) {
        cc.LabelTTF.RenderCmd.call(this,renderable);
        var locCanvas = this._labelCanvas = document.createElement("canvas");
        locCanvas.width = 1;
        locCanvas.height = 1;
        this._labelContext = locCanvas.getContext("2d");
        this._texRect = cc.rect();
    };
    cc.LabelTTF.CacheRenderCmd.prototype = Object.create( cc.LabelTTF.RenderCmd.prototype);
    cc.inject(cc.LabelTTF.RenderCmd.prototype, cc.LabelTTF.CacheRenderCmd.prototype);
    var proto = cc.LabelTTF.CacheRenderCmd.prototype;
    proto.constructor = cc.LabelTTF.CacheRenderCmd;
    proto._updateTexture = function () {
        this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.textDirty ^ this._dirtyFlag;
        var node = this._node;
        this._updateTTF();
        var width = this._texRect.width, height = this._texRect.height;
        var locContext = this._labelContext, locLabelCanvas = this._labelCanvas;
        if(!node._texture){
            var labelTexture = new cc.Texture2D();
            labelTexture.initWithElement(this._labelCanvas);
            node.setTexture(labelTexture);
        }
        if (node._string.length === 0) {
            locLabelCanvas.width = width;
            locLabelCanvas.height = height;
            node._texture && node._texture.handleLoadedTexture();
            node.setTextureRect(this._texRect);
            return true;
        }
        locContext.font = this._fontStyleStr;
        var flag = locLabelCanvas.width === width && locLabelCanvas.height === height;
        locLabelCanvas.width = this._texRect.width;
        locLabelCanvas.height = this._texRect.height;
        if (flag) locContext.clearRect(0, 0, width, height);
        this._saveStatus();
        this._drawTTFInCanvas(locContext);
        node._texture && node._texture.handleLoadedTexture();
        node.setTextureRect(this._texRect);
        return true;
    };
    proto._measureConfig = function () {
        this._labelContext.font = this._fontStyleStr;
    };
    proto._measure = function (text) {
        return this._labelContext.measureText(text).width;
    };
})();
(function(){
    cc.LabelTTF.CacheCanvasRenderCmd = function (renderable) {
        cc.Sprite.CanvasRenderCmd.call(this, renderable);
        cc.LabelTTF.CacheRenderCmd.call(this);
    };
    var proto = cc.LabelTTF.CacheCanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
    cc.inject(cc.LabelTTF.CacheRenderCmd.prototype, proto);
    proto.constructor = cc.LabelTTF.CacheCanvasRenderCmd;
})();
(function(){
    cc.LabelTTF.CanvasRenderCmd = function (renderable) {
        cc.Sprite.CanvasRenderCmd.call(this, renderable);
        cc.LabelTTF.RenderCmd.call(this);
    };
    cc.LabelTTF.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
    cc.inject(cc.LabelTTF.RenderCmd.prototype, cc.LabelTTF.CanvasRenderCmd.prototype);
    var proto = cc.LabelTTF.CanvasRenderCmd.prototype;
    proto.constructor = cc.LabelTTF.CanvasRenderCmd;
    proto._measureConfig = function () {};
    proto._measure = function (text) {
        var context = cc._renderContext.getContext();
        context.font = this._fontStyleStr;
        return context.measureText(text).width;
    };
    proto._updateTexture = function () {
        this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.textDirty ^ this._dirtyFlag;
        var node = this._node;
        var scale = cc.view.getDevicePixelRatio();
        this._updateTTF();
        if (node._string.length === 0) {
            node.setTextureRect(this._texRect);
            return true;
        }
        this._saveStatus();
        node.setTextureRect(this._texRect);
        return true;
    };
    proto.rendering = function(ctx) {
        var scaleX = cc.view.getScaleX(),
            scaleY = cc.view.getScaleY();
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        if (!context)
            return;
        var node = this._node;
        wrapper.computeRealOffsetY();
        if(this._status.length <= 0)
            return;
        var locIndex = (this._renderingIndex >= this._status.length)? this._renderingIndex-this._status.length:this._renderingIndex;
        var status = this._status[locIndex];
        this._renderingIndex = locIndex+1;
        var locHeight = node._rect.height,
            locX = node._offsetPosition.x,
            locY = -node._offsetPosition.y - locHeight;
        var alpha = (this._displayedOpacity / 255);
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        wrapper.setCompositeOperation(this._blendFuncStr);
        wrapper.setGlobalAlpha(alpha);
        wrapper.save();
        if (node._flippedX) {
            locX = -locX - node._rect.width;
            context.scale(-1, 1);
        }
        if (node._flippedY) {
            locY = node._offsetPosition.y;
            context.scale(1, -1);
        }
        var xOffset = status.xOffset + status.contextTransform.x + locX * scaleX;
        var yOffsetArray = [];
        var locStrLen = this._strings.length;
        for (var i = 0; i < locStrLen; i++)
            yOffsetArray.push(status.OffsetYArray[i] + status.contextTransform.y + locY * scaleY);
        this.drawLabels(context, xOffset, yOffsetArray);
        wrapper.restore();
    };
})();
var cc = cc || {};
cc._tmp = cc._tmp || {};
cc.associateWithNative = function (jsObj, superclass) {
};
cc.KEY = {
    none:0,
    back:6,
    menu:18,
    backspace:8,
    tab:9,
    enter:13,
    shift:16,
    ctrl:17,
    alt:18,
    pause:19,
    capslock:20,
    escape:27,
    space:32,
    pageup:33,
    pagedown:34,
    end:35,
    home:36,
    left:37,
    up:38,
    right:39,
    down:40,
    select:41,
    insert:45,
    Delete:46,
    0:48,
    1:49,
    2:50,
    3:51,
    4:52,
    5:53,
    6:54,
    7:55,
    8:56,
    9:57,
    a:65,
    b:66,
    c:67,
    d:68,
    e:69,
    f:70,
    g:71,
    h:72,
    i:73,
    j:74,
    k:75,
    l:76,
    m:77,
    n:78,
    o:79,
    p:80,
    q:81,
    r:82,
    s:83,
    t:84,
    u:85,
    v:86,
    w:87,
    x:88,
    y:89,
    z:90,
    num0:96,
    num1:97,
    num2:98,
    num3:99,
    num4:100,
    num5:101,
    num6:102,
    num7:103,
    num8:104,
    num9:105,
    '*':106,
    '+':107,
    '-':109,
    'numdel':110,
    '/':111,
    f1:112,
    f2:113,
    f3:114,
    f4:115,
    f5:116,
    f6:117,
    f7:118,
    f8:119,
    f9:120,
    f10:121,
    f11:122,
    f12:123,
    numlock:144,
    scrolllock:145,
    ';':186,
    semicolon:186,
    equal:187,
    '=':187,
    ',':188,
    comma:188,
    dash:189,
    '.':190,
    period:190,
    forwardslash:191,
    grave:192,
    '[':219,
    openbracket:219,
    backslash:220,
    ']':221,
    closebracket:221,
    quote:222,
    dpadLeft:1000,
    dpadRight:1001,
    dpadUp:1003,
    dpadDown:1004,
    dpadCenter:1005
};
cc.FMT_JPG = 0;
cc.FMT_PNG = 1;
cc.FMT_TIFF = 2;
cc.FMT_RAWDATA = 3;
cc.FMT_WEBP = 4;
cc.FMT_UNKNOWN = 5;
cc.getImageFormatByData = function (imgData) {
    if (imgData.length > 8 && imgData[0] === 0x89
        && imgData[1] === 0x50
        && imgData[2] === 0x4E
        && imgData[3] === 0x47
        && imgData[4] === 0x0D
        && imgData[5] === 0x0A
        && imgData[6] === 0x1A
        && imgData[7] === 0x0A) {
        return cc.FMT_PNG;
    }
    if (imgData.length > 2 && ((imgData[0] === 0x49 && imgData[1] === 0x49)
        || (imgData[0] === 0x4d && imgData[1] === 0x4d)
        || (imgData[0] === 0xff && imgData[1] === 0xd8))) {
        return cc.FMT_TIFF;
    }
    return cc.FMT_UNKNOWN;
};
cc.inherits = function (childCtor, parentCtor) {
    function tempCtor() {}
    tempCtor.prototype = parentCtor.prototype;
    childCtor.superClass_ = parentCtor.prototype;
    childCtor.prototype = new tempCtor();
    childCtor.prototype.constructor = childCtor;
};
cc.base = function(me, opt_methodName, var_args) {
    var caller = arguments.callee.caller;
    if (caller.superClass_) {
        ret = caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1));
        return ret;
    }
    var args = Array.prototype.slice.call(arguments, 2);
    var foundCaller = false;
    for (var ctor = me.constructor; ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
        if (ctor.prototype[opt_methodName] === caller) {
            foundCaller = true;
        } else if (foundCaller) {
            return ctor.prototype[opt_methodName].apply(me, args);
        }
    }
    if (me[opt_methodName] === caller) {
        return me.constructor.prototype[opt_methodName].apply(me, args);
    } else {
        throw Error(
            'cc.base called from a method of one name ' +
                'to a method of a different name');
    }
};
var GlobalVertexBuffer = (function () {
var VERTICES_SIZE = 888;
var GlobalVertexBuffer = function (gl) {
    this.gl = gl;
    this.vertexBuffer = gl.createBuffer();
    this.size = VERTICES_SIZE;
    this.byteLength = VERTICES_SIZE * 4 * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
    this.data = new ArrayBuffer(this.byteLength);
    this.dataArray = new Float32Array(this.data);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, this.dataArray, gl.DYNAMIC_DRAW);
    this._dirty = false;
    this._spaces = {
        0: this.byteLength
    };
};
GlobalVertexBuffer.prototype = {
    constructor: GlobalVertexBuffer,
    allocBuffer: function (offset, size) {
        var space = this._spaces[offset];
        if (space && space >= size) {
            delete this._spaces[offset];
            if (space > size) {
                var newOffset = offset + size;
                this._spaces[newOffset] = space - size;
            }
            return true;
        }
        else {
            return false;
        }
    },
    requestBuffer: function (size) {
        var key, offset, available;
        for (key in this._spaces) {
            offset = parseInt(key);
            available = this._spaces[key];
            if (available >= size && this.allocBuffer(offset, size)) {
                return {
                    buffer: this,
                    offset: offset,
                    size: size
                };
            }
        }
        return null;
    },
    freeBuffer: function (offset, size) {
        var spaces = this._spaces;
        var i, key, end;
        for (key in spaces) {
            i = parseInt(key);
            if (i > offset) {
                break;
            }
            if (i + spaces[key] >= offset) {
                size = size + offset - i;
                offset = i;
                break;
            }
        }
        end = offset + size;
        if (this._spaces[end]) {
            size += this._spaces[end];
            delete this._spaces[end];
        }
        this._spaces[offset] = size;
    },
    setDirty: function () {
        this._dirty = true;
    },
    update: function () {
        if (this._dirty) {
            this.gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
            this.gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.dataArray);
            this._dirty = false;
        }
    },
    destroy: function () {
        this.gl.deleteBuffer(this.vertexBuffer);
        this.data = null;
        this.positions = null;
        this.colors = null;
        this.texCoords = null;
        this.vertexBuffer = null;
    }
};
return GlobalVertexBuffer;
})();
cc.rendererCanvas = {
    childrenOrderDirty: true,
    assignedZ: 0,
    assignedZStep: 1 / 10000,
    _transformNodePool: [],
    _renderCmds: [],
    _isCacheToCanvasOn: false,
    _cacheToCanvasCmds: {},
    _cacheInstanceIds: [],
    _currentID: 0,
    _clearColor: cc.color(),
    _clearFillStyle: "rgb(0, 0, 0)",
    _dirtyRegion: null,
    _allNeedDraw: true,
    _enableDirtyRegion: false,
    _debugDirtyRegion: false,
    _canUseDirtyRegion: false,
    _dirtyRegionCountThreshold: 10,
    getRenderCmd: function (renderableObject) {
        return renderableObject._createRenderCmd();
    },
    enableDirtyRegion: function (enabled) {
        this._enableDirtyRegion = enabled;
    },
    isDirtyRegionEnabled: function () {
        return this._enableDirtyRegion;
    },
    setDirtyRegionCountThreshold: function(threshold) {
        this._dirtyRegionCountThreshold = threshold;
    },
    _collectDirtyRegion: function () {
        var locCmds = this._renderCmds, i, len;
        var dirtyRegion = this._dirtyRegion;
        var dirtryRegionCount = 0;
        var result = true;
        var localStatus = cc.Node.CanvasRenderCmd.RegionStatus;
        for (i = 0, len = locCmds.length; i < len; i++) {
            var cmd = locCmds[i];
            var regionFlag = cmd._regionFlag;
            var oldRegion = cmd._oldRegion;
            var currentRegion = cmd._currentRegion;
            if (regionFlag > localStatus.NotDirty) {
                ++dirtryRegionCount;
                if(dirtryRegionCount > this._dirtyRegionCountThreshold)
                    result = false;
                if(result) {
                    (!currentRegion.isEmpty()) && dirtyRegion.addRegion(currentRegion);
                    if (cmd._regionFlag > localStatus.Dirty) {
                        (!oldRegion.isEmpty()) && dirtyRegion.addRegion(oldRegion);
                    }
                }
                cmd._regionFlag = localStatus.NotDirty;
            }
        }
        return result;
    },
    _beginDrawDirtyRegion: function (ctxWrapper) {
        var ctx = ctxWrapper.getContext();
        var dirtyList = this._dirtyRegion.getDirtyRegions();
        ctx.save();
        var scaleX = ctxWrapper._scaleX;
        var scaleY = ctxWrapper._scaleY;
        ctxWrapper.setTransform({a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0}, scaleX, scaleY);
        ctx.beginPath();
        for (var index = 0, count = dirtyList.length; index < count; ++index) {
            var region = dirtyList[index];
            ctx.rect(region._minX , -region._maxY , region._width , region._height );
        }
        ctx.clip();
    },
    _endDrawDirtyRegion: function (ctx) {
        ctx.restore();
    },
    _debugDrawDirtyRegion: function (ctxWrapper) {
        if (!this._debugDirtyRegion) return;
        var ctx = ctxWrapper.getContext();
        var dirtyList = this._dirtyRegion.getDirtyRegions();
        var scaleX = ctxWrapper._scaleX;
        var scaleY = ctxWrapper._scaleY;
        ctxWrapper.setTransform({a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0}, scaleX, scaleY);
        ctx.beginPath();
        for (var index = 0, count = dirtyList.length; index < count; ++index) {
            var region = dirtyList[index];
            ctx.rect(region._minX, -region._maxY , region._width , region._height );
        }
        var oldstyle = ctx.fillStyle;
        ctx.fillStyle = 'green';
        ctx.fill();
        ctx.fillStyle = oldstyle;
    },
    rendering: function (ctxWrapper) {
        var dirtyRegion = this._dirtyRegion = this._dirtyRegion || new cc.DirtyRegion();
        var viewport = cc._canvas;
        var wrapper = ctxWrapper || cc._renderContext;
        var ctx = wrapper.getContext();
        var scaleX = cc.view.getScaleX(),
            scaleY = cc.view.getScaleY();
        wrapper.setViewScale(scaleX, scaleY);
        wrapper.computeRealOffsetY();
        var dirtyList = this._dirtyRegion.getDirtyRegions();
        var locCmds = this._renderCmds, i, len;
        var allNeedDraw = this._allNeedDraw || !this._enableDirtyRegion || !this._canUseDirtyRegion;
        var collectResult = true;
        if (!allNeedDraw) {
            collectResult = this._collectDirtyRegion();
        }
        allNeedDraw = allNeedDraw || (!collectResult);
        if(!allNeedDraw) {
            this._beginDrawDirtyRegion(wrapper);
        }
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        ctx.clearRect(0, 0, viewport.width, viewport.height);
        if (this._clearColor.r !== 0 ||
            this._clearColor.g !== 0 ||
            this._clearColor.b !== 0) {
            wrapper.setFillStyle(this._clearFillStyle);
            wrapper.setGlobalAlpha(this._clearColor.a);
            ctx.fillRect(0, 0, viewport.width, viewport.height);
        }
        for (i = 0, len = locCmds.length; i < len; i++) {
            var cmd = locCmds[i];
            var needRendering = false;
            var cmdRegion = cmd._currentRegion;
            if (!cmdRegion || allNeedDraw) {
                needRendering = true;
            } else {
                for (var index = 0, count = dirtyList.length; index < count; ++index) {
                    if (dirtyList[index].intersects(cmdRegion)) {
                        needRendering = true;
                        break;
                    }
                }
            }
            if (needRendering) {
                cmd.rendering(wrapper, scaleX, scaleY);
            }
        }
        if (!allNeedDraw) {
            this._debugDrawDirtyRegion(wrapper);
            this._endDrawDirtyRegion(ctx);
        }
        dirtyRegion.clear();
        this._allNeedDraw = false;
    },
    _renderingToCacheCanvas: function (ctx, instanceID, scaleX, scaleY) {
        if (!ctx)
            cc.log("The context of RenderTexture is invalid.");
        scaleX = cc.isUndefined(scaleX) ? 1 : scaleX;
        scaleY = cc.isUndefined(scaleY) ? 1 : scaleY;
        instanceID = instanceID || this._currentID;
        var locCmds = this._cacheToCanvasCmds[instanceID], i, len;
        ctx.computeRealOffsetY();
        for (i = 0, len = locCmds.length; i < len; i++) {
            locCmds[i].rendering(ctx, scaleX, scaleY);
        }
        this._removeCache(instanceID);
        var locIDs = this._cacheInstanceIds;
        if (locIDs.length === 0)
            this._isCacheToCanvasOn = false;
        else
            this._currentID = locIDs[locIDs.length - 1];
    },
    _turnToCacheMode: function (renderTextureID) {
        this._isCacheToCanvasOn = true;
        renderTextureID = renderTextureID || 0;
        this._cacheToCanvasCmds[renderTextureID] = [];
        if (this._cacheInstanceIds.indexOf(renderTextureID) === -1)
            this._cacheInstanceIds.push(renderTextureID);
        this._currentID = renderTextureID;
    },
    _turnToNormalMode: function () {
        this._isCacheToCanvasOn = false;
    },
    _removeCache: function (instanceID) {
        instanceID = instanceID || this._currentID;
        var cmds = this._cacheToCanvasCmds[instanceID];
        if (cmds) {
            cmds.length = 0;
            delete this._cacheToCanvasCmds[instanceID];
        }
        var locIDs = this._cacheInstanceIds;
        cc.arrayRemoveObject(locIDs, instanceID);
    },
    resetFlag: function () {
        this.childrenOrderDirty = false;
        this._transformNodePool.length = 0;
    },
    transform: function () {
        var locPool = this._transformNodePool;
        locPool.sort(this._sortNodeByLevelAsc);
        for (var i = 0, len = locPool.length; i < len; i++) {
            if (locPool[i]._dirtyFlag !== 0)
                locPool[i].updateStatus();
        }
        locPool.length = 0;
    },
    transformDirty: function () {
        return this._transformNodePool.length > 0;
    },
    _sortNodeByLevelAsc: function (n1, n2) {
        return n1._curLevel - n2._curLevel;
    },
    pushDirtyNode: function (node) {
        this._transformNodePool.push(node);
    },
    clear: function () {
    },
    clearRenderCommands: function () {
        this._renderCmds.length = 0;
        this._cacheInstanceIds.length = 0;
        this._isCacheToCanvasOn = false;
        this._allNeedDraw = true;
        this._canUseDirtyRegion = true;
    },
    pushRenderCommand: function (cmd) {
        if (!cmd.needDraw())
            return;
        if (!cmd._canUseDirtyRegion) {
            this._canUseDirtyRegion = false;
        }
        if (this._isCacheToCanvasOn) {
            var currentId = this._currentID, locCmdBuffer = this._cacheToCanvasCmds;
            var cmdList = locCmdBuffer[currentId];
            if (cmdList.indexOf(cmd) === -1)
                cmdList.push(cmd);
        } else {
            if (this._renderCmds.indexOf(cmd) === -1)
                this._renderCmds.push(cmd);
        }
    }
};
(function () {
    cc.CanvasContextWrapper = function (context) {
        this._context = context;
        this._saveCount = 0;
        this._currentAlpha = context.globalAlpha;
        this._currentCompositeOperation = context.globalCompositeOperation;
        this._currentFillStyle = context.fillStyle;
        this._currentStrokeStyle = context.strokeStyle;
        this._offsetX = 0;
        this._offsetY = 0;
        this._realOffsetY = this.height;
        this._armatureMode = 0;
    };
    var proto = cc.CanvasContextWrapper.prototype;
    proto.resetCache = function () {
        var context = this._context;
        this._currentAlpha = context.globalAlpha;
        this._currentCompositeOperation = context.globalCompositeOperation;
        this._currentFillStyle = context.fillStyle;
        this._currentStrokeStyle = context.strokeStyle;
        this._realOffsetY = this._context.canvas.height + this._offsetY;
    };
    proto.setOffset = function (x, y) {
        this._offsetX = x;
        this._offsetY = y;
        this._realOffsetY = this._context.canvas.height + this._offsetY;
    };
    proto.computeRealOffsetY = function () {
        this._realOffsetY = this._context.canvas.height + this._offsetY;
    };
    proto.setViewScale = function (scaleX, scaleY) {
        this._scaleX = scaleX;
        this._scaleY = scaleY;
    };
    proto.getContext = function () {
        return this._context;
    };
    proto.save = function () {
        this._context.save();
        this._saveCount++;
    };
    proto.restore = function () {
        this._context.restore();
        this._saveCount--;
    };
    proto.setGlobalAlpha = function (alpha) {
        if (this._saveCount > 0) {
            this._context.globalAlpha = alpha;
        } else {
            if (this._currentAlpha !== alpha) {
                this._currentAlpha = alpha;
                this._context.globalAlpha = alpha;
            }
        }
    };
    proto.setCompositeOperation = function (compositionOperation) {
        if (this._saveCount > 0) {
            this._context.globalCompositeOperation = compositionOperation;
        } else {
            if (this._currentCompositeOperation !== compositionOperation) {
                this._currentCompositeOperation = compositionOperation;
                this._context.globalCompositeOperation = compositionOperation;
            }
        }
    };
    proto.setFillStyle = function (fillStyle) {
        if (this._saveCount > 0) {
            this._context.fillStyle = fillStyle;
        } else {
            if (this._currentFillStyle !== fillStyle) {
                this._currentFillStyle = fillStyle;
                this._context.fillStyle = fillStyle;
            }
        }
    };
    proto.setStrokeStyle = function (strokeStyle) {
        if (this._saveCount > 0) {
            this._context.strokeStyle = strokeStyle;
        } else {
            if (this._currentStrokeStyle !== strokeStyle) {
                this._currentStrokeStyle = strokeStyle;
                this._context.strokeStyle = strokeStyle;
            }
        }
    };
    proto.setTransform = function (t, scaleX, scaleY) {
        if (this._armatureMode > 0) {
            this.restore();
            this.save();
            this._context.transform(t.a * scaleX, -t.b * scaleY, -t.c * scaleX, t.d * scaleY, t.tx * scaleX, -(t.ty * scaleY));
        } else {
            this._context.setTransform(t.a * scaleX, -t.b * scaleY, -t.c * scaleX, t.d * scaleY, this._offsetX + t.tx * scaleX, this._realOffsetY - (t.ty * scaleY));
        }
    };
    proto._switchToArmatureMode = function (enable, t, scaleX, scaleY) {
        if (enable) {
            this._armatureMode++;
            this._context.setTransform(t.a, t.c, t.b, t.d, this._offsetX + t.tx * scaleX, this._realOffsetY - (t.ty * scaleY));
            this.save();
        } else {
            this._armatureMode--;
            this.restore();
        }
    };
})();
var Region = function () {
    this._minX = 0;
    this._minY = 0;
    this._maxX = 0;
    this._maxY = 0;
    this._width = 0;
    this._height = 0;
    this._area = 0;
};
var regionProto = Region.prototype;
var regionPool = [];
function regionCreate() {
    var region = regionPool.pop();
    if (!region) {
        region = new Region();
    }
    return region;
}
function regionRelease(region) {
    regionPool.push(region);
}
regionProto.setTo = function (minX, minY, maxX, maxY) {
    this._minX = minX;
    this._minY = minY;
    this._maxX = maxX;
    this._maxY = maxY;
    this.updateArea();
    return this;
};
regionProto.intValues = function () {
    this._minX = Math.floor(this._minX);
    this._minY = Math.floor(this._minY);
    this._maxX = Math.ceil(this._maxX);
    this._maxY = Math.ceil(this._maxY);
    this.updateArea();
};
regionProto.updateArea = function () {
    this._width = this._maxX - this._minX;
    this._height = this._maxY - this._minY;
    this._area = this._width * this._height;
};
regionProto.union = function (target) {
    if(this._width <= 0 || this._height <= 0) {
        this.setTo(target._minX, target._minY, target._maxX, target._maxY);
        return;
    }
    if (this._minX > target._minX) {
        this._minX = target._minX;
    }
    if (this._minY > target._minY) {
        this._minY = target._minY;
    }
    if (this._maxX < target._maxX) {
        this._maxX = target._maxX;
    }
    if (this._maxY < target._maxY) {
        this._maxY = target._maxY;
    }
    this.updateArea();
};
regionProto.setEmpty = function () {
    this._minX = 0;
    this._minY = 0;
    this._maxX = 0;
    this._maxY = 0;
    this._width = 0;
    this._height = 0;
    this._area = 0;
};
regionProto.isEmpty = function () {
    return this._width <= 0 || this._height <= 0;
};
regionProto.intersects = function (target) {
    if (this._width <= 0 || this._height <= 0 || target._width <= 0 || target._height <= 0) {
        return false;
    }
    var max = this._minX > target._minX ? this._minX : target._minX;
    var min = this._maxX < target._maxX ? this._maxX : target._maxX;
    if (max > min) {
        return false;
    }
    max = this._minY > target._minY ? this._minY : target._minY;
    min = this._maxY < target._maxY ? this._maxY : target._maxY;
    return max <= min;
};
regionProto.updateRegion = function (bounds, matrix) {
    if (bounds.width == 0 || bounds.height == 0) {
        this.setEmpty();
        return;
    }
    var m = matrix;
    var a = m.a;
    var b = m.b;
    var c = m.c;
    var d = m.d;
    var tx = m.tx;
    var ty = m.ty;
    var x = bounds.x;
    var y = bounds.y;
    var xMax = x + bounds.width;
    var yMax = y + bounds.height;
    var minX, minY, maxX, maxY;
    if (a == 1.0 && b == 0.0 && c == 0.0 && d == 1.0) {
        minX = x + tx - 1;
        minY = y + ty - 1;
        maxX = xMax + tx + 1;
        maxY = yMax + ty + 1;
    }
    else {
        var x0 = a * x + c * y + tx;
        var y0 = b * x + d * y + ty;
        var x1 = a * xMax + c * y + tx;
        var y1 = b * xMax + d * y + ty;
        var x2 = a * xMax + c * yMax + tx;
        var y2 = b * xMax + d * yMax + ty;
        var x3 = a * x + c * yMax + tx;
        var y3 = b * x + d * yMax + ty;
        var tmp = 0;
        if (x0 > x1) {
            tmp = x0;
            x0 = x1;
            x1 = tmp;
        }
        if (x2 > x3) {
            tmp = x2;
            x2 = x3;
            x3 = tmp;
        }
        minX = (x0 < x2 ? x0 : x2) - 1;
        maxX = (x1 > x3 ? x1 : x3) + 1;
        if (y0 > y1) {
            tmp = y0;
            y0 = y1;
            y1 = tmp;
        }
        if (y2 > y3) {
            tmp = y2;
            y2 = y3;
            y3 = tmp;
        }
        minY = (y0 < y2 ? y0 : y2) - 1;
        maxY = (y1 > y3 ? y1 : y3) + 1;
    }
    this._minX = minX;
    this._minY = minY;
    this._maxX = maxX;
    this._maxY = maxY;
    this._width = maxX - minX;
    this._height = maxY - minY;
    this._area = this._width * this._height;
};
function unionArea(r1, r2) {
    var minX = r1._minX < r2._minX ? r1._minX : r2._minX;
    var minY = r1._minY < r2._minY ? r1._minY : r2._minY;
    var maxX = r1._maxX > r2._maxX ? r1._maxX : r2._maxX;
    var maxY = r1._maxY > r2._maxY ? r1._maxY : r2._maxY;
    return (maxX - minX) * (maxY - minY);
}
var DirtyRegion = function() {
    this.dirtyList = [];
    this.hasClipRect = false;
    this.clipWidth = 0;
    this.clipHeight = 0;
    this.clipArea = 0;
    this.clipRectChanged = false;
};
var dirtyRegionProto = DirtyRegion.prototype;
dirtyRegionProto.setClipRect = function(width, height) {
    this.hasClipRect = true;
    this.clipRectChanged = true;
    this.clipWidth = Math.ceil(width);
    this.clipHeight = Math.ceil(height);
    this.clipArea = this.clipWidth * this.clipHeight;
};
dirtyRegionProto.addRegion = function(target) {
    var minX = target._minX, minY = target._minY, maxX = target._maxX, maxY = target._maxY;
    if (this.hasClipRect) {
        if (minX < 0) {
            minX = 0;
        }
        if (minY < 0) {
            minY = 0;
        }
        if (maxX > this.clipWidth) {
            maxX = this.clipWidth;
        }
        if (maxY > this.clipHeight) {
            maxY = this.clipHeight;
        }
    }
    if (minX >= maxX || minY >= maxY) {
        return false;
    }
    if (this.clipRectChanged) {
        return true;
    }
    var dirtyList = this.dirtyList;
    var region = regionCreate();
    dirtyList.push(region.setTo(minX, minY, maxX, maxY));
    this.mergeDirtyList(dirtyList);
    return true;
};
dirtyRegionProto.clear = function() {
    var dirtyList = this.dirtyList;
    var length = dirtyList.length;
    for (var i = 0; i < length; i++) {
        regionRelease(dirtyList[i]);
    }
    dirtyList.length = 0;
};
dirtyRegionProto.getDirtyRegions = function() {
    var dirtyList = this.dirtyList;
    if (this.clipRectChanged) {
        this.clipRectChanged = false;
        this.clear();
        var region = regionCreate();
        dirtyList.push(region.setTo(0, 0, this.clipWidth, this.clipHeight));
    }
    else {
        while (this.mergeDirtyList(dirtyList)) {
        }
    }
    var numDirty = this.dirtyList.length;
    if (numDirty > 0) {
        for (var i = 0; i < numDirty; i++) {
            this.dirtyList[i].intValues();
        }
    }
    return this.dirtyList;
};
dirtyRegionProto.mergeDirtyList = function(dirtyList) {
    var length = dirtyList.length;
    if (length < 2) {
        return false;
    }
    var hasClipRect = this.hasClipRect;
    var bestDelta = length > 3 ? Number.POSITIVE_INFINITY : 0;
    var mergeA = 0;
    var mergeB = 0;
    var totalArea = 0;
    for (var i = 0; i < length - 1; i++) {
        var regionA = dirtyList[i];
        hasClipRect && (totalArea += regionA.area);
        for (var j = i + 1; j < length; j++) {
            var regionB = dirtyList[j];
            var delta = unionArea(regionA, regionB) - regionA.area - regionB.area;
            if (bestDelta > delta) {
                mergeA = i;
                mergeB = j;
                bestDelta = delta;
            }
        }
    }
    if (hasClipRect && (totalArea / this.clipArea) > 0.95) {
        this.clipRectChanged = true;
    }
    if (mergeA != mergeB) {
        var region = dirtyList[mergeB];
        dirtyList[mergeA].union(region);
        regionRelease(region);
        dirtyList.splice(mergeB, 1);
        return true;
    }
    return false;
};
cc.Region = Region;
cc.DirtyRegion = DirtyRegion;
cc.profiler = (function () {
    var _showFPS = false;
    var _inited = false;
    var _frames = 0, _frameRate = 0, _lastSPF = 0, _accumDt = 0;
    var _afterVisitListener = null,
        _FPSLabel = document.createElement('div'),
        _SPFLabel = document.createElement('div'),
        _drawsLabel = document.createElement('div'),
        _fps = document.createElement('div');
    var LEVEL_DET_FACTOR = 0.6, _levelDetCycle = 10;
    var LEVELS = [0, 10, 20, 30];
    var _fpsCount = [0, 0, 0, 0];
    var _currLevel = 3, _analyseCount = 0, _totalFPS = 0;
    _fps.id = 'fps';
    _fps.style.position = 'absolute';
    _fps.style.padding = '3px';
    _fps.style.textAlign = 'left';
    _fps.style.backgroundColor = 'rgb(0, 0, 34)';
    _fps.style.bottom = cc.DIRECTOR_STATS_POSITION.y + '0px';
    _fps.style.left = cc.DIRECTOR_STATS_POSITION.x + 'px';
    _fps.style.width = '45px';
    _fps.style.height = '60px';
    var labels = [_drawsLabel, _SPFLabel, _FPSLabel];
    for (var i = 0; i < 3; ++i) {
        var style = labels[i].style;
        style.color = 'rgb(0, 255, 255)';
        style.font = 'bold 12px Helvetica, Arial';
        style.lineHeight = '20px';
        style.width = '100%';
        _fps.appendChild(labels[i]);
    }
    var analyseFPS = function (fps) {
        var lastId = LEVELS.length - 1, i = lastId, ratio, average = 0;
        _analyseCount++;
        _totalFPS += fps;
        for (; i >= 0; i--) {
            if (fps >= LEVELS[i]) {
                _fpsCount[i]++;
                break;
            }
        }
        if (_analyseCount >= _levelDetCycle) {
            average = _totalFPS / _levelDetCycle;
            for (i = lastId; i >0; i--) {
                ratio = _fpsCount[i] / _levelDetCycle;
                if (ratio >= LEVEL_DET_FACTOR && average >= LEVELS[i]) {
                    if (i != _currLevel) {
                        _currLevel = i;
                        profiler.onFrameRateChange && profiler.onFrameRateChange(average.toFixed(2));
                    }
                    break;
                }
            }
            _changeCount = 0;
            _analyseCount = 0;
            _totalFPS = 0;
            for (i = lastId; i > 0; i--) {
                _fpsCount[i] = 0;
            }
        }
    };
    var afterVisit = function () {
        _lastSPF = cc.director.getSecondsPerFrame();
        _frames++;
        _accumDt += cc.director.getDeltaTime();
        if (_accumDt > cc.DIRECTOR_FPS_INTERVAL) {
            _frameRate = _frames / _accumDt;
            _frames = 0;
            _accumDt = 0;
            if (profiler.onFrameRateChange) {
                analyseFPS(_frameRate);
            }
            if (_showFPS) {
                _SPFLabel.innerText = _lastSPF.toFixed(3);
                _FPSLabel.innerText = _frameRate.toFixed(1);
                _drawsLabel.innerText = (0 | cc.g_NumberOfDraws).toString();
            }
        }
    };
    var profiler = {
        onFrameRateChange: null,
        getSecondsPerFrame: function () {
            return _lastSPF;
        },
        getFrameRate: function () {
            return _frameRate;
        },
        setProfileDuration: function (duration) {
            if (!isNaN(duration) && duration > 0) {
                _levelDetCycle = duration / cc.DIRECTOR_FPS_INTERVAL;
            }
        },
        resumeProfiling: function () {
            cc.eventManager.addListener(_afterVisitListener, 1);
        },
        stopProfiling: function () {
            cc.eventManager.removeListener(_afterVisitListener);
        },
        isShowingStats: function () {
            return _showFPS;
        },
        showStats: function () {
            if (!_inited) {
                this.init();
            }
            if (_fps.parentElement === null) {
                cc.container.appendChild(_fps);
            }
            _showFPS = true;
        },
        hideStats: function () {
            _showFPS = false;
            if (_fps.parentElement === cc.container) {
                cc.container.removeChild(_fps);
            }
        },
        init: function () {
            if (!_inited) {
                _afterVisitListener = cc.eventManager.addCustomListener(cc.Director.EVENT_AFTER_VISIT, afterVisit);
                _inited = true;
            }
        }
    };
    return profiler;
})();
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType !== cc.game.RENDER_TYPE_WEBGL) {
        return;
    }
    cc.DirectorDelegate = cc.Class.extend({
        updateProjection: function () {
        }
    });
    var _p = cc.Director.prototype;
    var recursiveChild = function(node){
        if(node && node._renderCmd){
            node._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
            var i, children = node._children;
            for(i=0; i<children.length; i++){
                recursiveChild(children[i]);
            }
        }
    };
    cc.eventManager.addCustomListener(cc.Director.EVENT_PROJECTION_CHANGED, function(){
        var director = cc.director;
        var stack = cc.director._scenesStack;
        for(var  i=0; i<stack.length; i++)
            recursiveChild(stack[i]);
    });
    _p.setProjection = function (projection) {
        var _t = this;
        var size = _t._winSizeInPoints;
        _t.setViewport();
        var view = _t._openGLView,
            ox = view._viewPortRect.x / view._scaleX,
            oy = view._viewPortRect.y / view._scaleY;
        switch (projection) {
            case cc.Director.PROJECTION_2D:
                cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
                cc.kmGLLoadIdentity();
                var orthoMatrix = cc.math.Matrix4.createOrthographicProjection(
                    0,
                    size.width,
                    0,
                    size.height,
                    -1024, 1024);
                cc.kmGLMultMatrix(orthoMatrix);
                cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
                cc.kmGLLoadIdentity();
                break;
            case cc.Director.PROJECTION_3D:
                var zeye = _t.getZEye();
                var matrixPerspective = new cc.math.Matrix4(), matrixLookup = new cc.math.Matrix4();
                cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
                cc.kmGLLoadIdentity();
                matrixPerspective = cc.math.Matrix4.createPerspectiveProjection(60, size.width / size.height, 0.1, zeye * 2);
                cc.kmGLMultMatrix(matrixPerspective);
                cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
                cc.kmGLLoadIdentity();
                var eye = new cc.math.Vec3(-ox + size.width / 2, -oy + size.height / 2, zeye);
                var center = new cc.math.Vec3( -ox + size.width / 2, -oy + size.height / 2, 0.0);
                var up = new cc.math.Vec3( 0.0, 1.0, 0.0);
                matrixLookup.lookAt(eye, center, up);
                cc.kmGLMultMatrix(matrixLookup);
                break;
            case cc.Director.PROJECTION_CUSTOM:
                if (_t._projectionDelegate)
                    _t._projectionDelegate.updateProjection();
                break;
            default:
                cc.log(cc._LogInfos.Director_setProjection);
                break;
        }
        _t._projection = projection;
        cc.eventManager.dispatchEvent(_t._eventProjectionChanged);
        cc.setProjectionMatrixDirty();
        cc.renderer.childrenOrderDirty = true;
    };
    _p.setDepthTest = function (on) {
        cc.renderer.setDepthTest(on);
    };
    _p.setClearColor = function (clearColor) {
        cc.renderer._clearColor = clearColor;
    };
    _p.setOpenGLView = function (openGLView) {
        var _t = this;
        _t._winSizeInPoints.width = cc._canvas.width;
        _t._winSizeInPoints.height = cc._canvas.height;
        _t._openGLView = openGLView || cc.view;
        var conf = cc.configuration;
        conf.gatherGPUInfo();
        conf.dumpInfo();
        _t.setGLDefaultValues();
        if (cc.eventManager)
            cc.eventManager.setEnabled(true);
    };
    _p._clear = function () {
        var gl = cc._renderContext;
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    };
    _p.getVisibleSize = function () {
        return this._openGLView.getVisibleSize();
    };
    _p.getVisibleOrigin = function () {
        return this._openGLView.getVisibleOrigin();
    };
    _p.getZEye = function () {
        return (this._winSizeInPoints.height / 1.1566 );
    };
    _p.setViewport = function () {
        var view = this._openGLView;
        if (view) {
            var locWinSizeInPoints = this._winSizeInPoints;
            view.setViewPortInPoints(-view._viewPortRect.x/view._scaleX, -view._viewPortRect.y/view._scaleY, locWinSizeInPoints.width, locWinSizeInPoints.height);
        }
    };
    _p.getOpenGLView = function () {
        return this._openGLView;
    };
    _p.getProjection = function () {
        return this._projection;
    };
    _p.setAlphaBlending = function (on) {
        if (on)
            cc.glBlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
        else
            cc.glBlendFunc(cc._renderContext.ONE, cc._renderContext.ZERO);
    };
    _p.setGLDefaultValues = function () {
        var _t = this;
        _t.setAlphaBlending(true);
        _t.setProjection(_t._projection);
        cc._renderContext.clearColor(0.0, 0.0, 0.0, 0.0);
    };
});
cc.configuration = {
    ERROR:0,
    STRING:1,
    INT:2,
    DOUBLE:3,
    BOOLEAN:4,
    _maxTextureSize:0,
    _maxModelviewStackDepth:0,
    _supportsPVRTC:false,
    _supportsNPOT:false,
    _supportsBGRA8888:false,
    _supportsDiscardFramebuffer:false,
    _supportsShareableVAO:false,
    _maxSamplesAllowed:0,
    _maxTextureUnits:0,
    _GlExtensions:"",
    _valueDict:{},
    _inited: false,
    _init:function () {
        var locValueDict = this._valueDict;
        locValueDict["cocos2d.x.version"] = cc.ENGINE_VERSION;
        locValueDict["cocos2d.x.compiled_with_profiler"] = false;
        locValueDict["cocos2d.x.compiled_with_gl_state_cache"] = cc.ENABLE_GL_STATE_CACHE;
        this._inited = true;
    },
    getMaxTextureSize:function () {
        return this._maxTextureSize;
    },
    getMaxModelviewStackDepth:function () {
        return this._maxModelviewStackDepth;
    },
    getMaxTextureUnits:function () {
        return this._maxTextureUnits;
    },
    supportsNPOT:function () {
        return this._supportsNPOT;
    },
    supportsPVRTC: function () {
        return this._supportsPVRTC;
    },
    supportsETC: function() {
        return false;
    },
    supportsS3TC: function() {
        return false;
    },
    supportsATITC: function() {
        return false;
    },
    supportsBGRA8888:function () {
        return this._supportsBGRA8888;
    },
    supportsDiscardFramebuffer:function () {
        return this._supportsDiscardFramebuffer;
    },
    supportsShareableVAO:function () {
        return this._supportsShareableVAO;
    },
    checkForGLExtension:function (searchName) {
        return this._GlExtensions.indexOf(searchName) > -1;
    },
    getValue: function(key, default_value){
        if(!this._inited)
            this._init();
        var locValueDict = this._valueDict;
        if(locValueDict[key])
            return locValueDict[key];
        return default_value;
    },
    setValue: function(key, value){
        this._valueDict[key] = value;
    },
    dumpInfo: function(){
         if(cc.ENABLE_GL_STATE_CACHE === 0){
             cc.log("");
             cc.log(cc._LogInfos.configuration_dumpInfo);
             cc.log("")
         }
    },
    gatherGPUInfo: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return;
        if(!this._inited)
            this._init();
        var gl = cc._renderContext;
        var locValueDict = this._valueDict;
        locValueDict["gl.vendor"] = gl.getParameter(gl.VENDOR);
        locValueDict["gl.renderer"] = gl.getParameter(gl.RENDERER);
        locValueDict["gl.version"] = gl.getParameter(gl.VERSION);
        this._GlExtensions = "";
        var extArr = gl.getSupportedExtensions();
        for (var i = 0; i < extArr.length; i++)
            this._GlExtensions += extArr[i] + " ";
        this._maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
        locValueDict["gl.max_texture_size"] = this._maxTextureSize;
        this._maxTextureUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
        locValueDict["gl.max_texture_units"] = this._maxTextureUnits;
        this._supportsPVRTC = this.checkForGLExtension("GL_IMG_texture_compression_pvrtc");
        locValueDict["gl.supports_PVRTC"] = this._supportsPVRTC;
        this._supportsNPOT = false;
        locValueDict["gl.supports_NPOT"] = this._supportsNPOT;
        this._supportsBGRA8888 = this.checkForGLExtension("GL_IMG_texture_format_BGRA888");
        locValueDict["gl.supports_BGRA8888"] = this._supportsBGRA8888;
        this._supportsDiscardFramebuffer = this.checkForGLExtension("GL_EXT_discard_framebuffer");
        locValueDict["gl.supports_discard_framebuffer"] = this._supportsDiscardFramebuffer;
        this._supportsShareableVAO = this.checkForGLExtension("vertex_array_object");
        locValueDict["gl.supports_vertex_array_object"] = this._supportsShareableVAO;
        cc.checkGLErrorDebug();
    },
    loadConfigFile: function( url){
        if(!this._inited)
            this._init();
        var dict = cc.loader.getRes(url);
        if(!dict) throw new Error("Please load the resource first : " + url);
        cc.assert(dict, cc._LogInfos.configuration_loadConfigFile_2, url);
        var getDatas = dict["data"];
        if(!getDatas){
            cc.log(cc._LogInfos.configuration_loadConfigFile, url);
            return;
        }
        for(var selKey in getDatas)
            this._valueDict[selKey] = getDatas[selKey];
    }
};
cc.rendererWebGL = (function () {
var _batchedInfo = {
        texture: null,
        blendSrc: null,
        blendDst: null,
        shader: null
    },
    _quadIndexBuffer = null,
    _quadVertexBuffer = null,
    _vertexSize = 0,
    _batchingSize = 0,
    _sizePerVertex = 6,
    _vertexData = null,
    _vertexDataSize = 0,
    _vertexDataF32 = null,
    _vertexDataUI32 = null,
    _IS_IOS = false;
function updateQuadBuffer (numQuads) {
    var gl = cc._renderContext;
    if (_quadIndexBuffer) {
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _quadIndexBuffer);
        var indices = new Uint16Array(numQuads * 6);
        var currentQuad = 0;
        for (var i = 0, len = numQuads * 6; i < len; i += 6) {
            indices[i] = currentQuad + 0;
            indices[i + 1] = currentQuad + 1;
            indices[i + 2] = currentQuad + 2;
            indices[i + 3] = currentQuad + 1;
            indices[i + 4] = currentQuad + 2;
            indices[i + 5] = currentQuad + 3;
            currentQuad += 4;
        }
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
    }
    if (_quadVertexBuffer) {
        _vertexDataSize = numQuads * 4 * _sizePerVertex;
        var byteLength = _vertexDataSize * 4;
        _vertexData = new ArrayBuffer(byteLength);
        _vertexDataF32 = new Float32Array(_vertexData);
        _vertexDataUI32 = new Uint32Array(_vertexData);
        gl.bindBuffer(gl.ARRAY_BUFFER, _quadVertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, _vertexDataF32, gl.DYNAMIC_DRAW);
    }
    _vertexSize = numQuads * 4;
}
function initQuadBuffer (numQuads) {
    var gl = cc._renderContext;
    if (_quadIndexBuffer === null) {
        _quadVertexBuffer = gl.createBuffer();
        _quadIndexBuffer = gl.createBuffer();
        updateQuadBuffer(numQuads);
    }
    else {
        updateQuadBuffer(numQuads);
    }
}
return {
    mat4Identity: null,
    childrenOrderDirty: true,
    assignedZ: 0,
    assignedZStep: 1/100,
    _transformNodePool: [],
    _renderCmds: [],
    _isCacheToBufferOn: false,
    _cacheToBufferCmds: {},
    _cacheInstanceIds: [],
    _currentID: 0,
    _clearColor: cc.color(),
    init: function () {
        var gl = cc._renderContext;
        gl.disable(gl.CULL_FACE);
        gl.disable(gl.DEPTH_TEST);
        this.mat4Identity = new cc.math.Matrix4();
        this.mat4Identity.identity();
        initQuadBuffer(2000);
        if (cc.sys.os === cc.sys.OS_IOS) {
            _IS_IOS = true;
        }
    },
    getVertexSize: function () {
        return _vertexSize;
    },
    getRenderCmd: function (renderableObject) {
        return renderableObject._createRenderCmd();
    },
    _turnToCacheMode: function (renderTextureID) {
        this._isCacheToBufferOn = true;
        renderTextureID = renderTextureID || 0;
        if (!this._cacheToBufferCmds[renderTextureID]) {
            this._cacheToBufferCmds[renderTextureID] = [];
        }
        else {
            this._cacheToBufferCmds[renderTextureID].length = 0;
        }
        if (this._cacheInstanceIds.indexOf(renderTextureID) === -1) {
            this._cacheInstanceIds.push(renderTextureID);
        }
        this._currentID = renderTextureID;
    },
    _turnToNormalMode: function () {
        this._isCacheToBufferOn = false;
    },
    _removeCache: function (instanceID) {
        instanceID = instanceID || this._currentID;
        var cmds = this._cacheToBufferCmds[instanceID];
        if (cmds) {
            cmds.length = 0;
            delete this._cacheToBufferCmds[instanceID];
        }
        var locIDs = this._cacheInstanceIds;
        cc.arrayRemoveObject(locIDs, instanceID);
    },
    _renderingToBuffer: function (renderTextureId) {
        renderTextureId = renderTextureId || this._currentID;
        var locCmds = this._cacheToBufferCmds[renderTextureId];
        var ctx = cc._renderContext;
        this.rendering(ctx, locCmds);
        this._removeCache(renderTextureId);
        var locIDs = this._cacheInstanceIds;
        if (locIDs.length === 0)
            this._isCacheToBufferOn = false;
        else
            this._currentID = locIDs[locIDs.length - 1];
    },
    resetFlag: function () {
        if (this.childrenOrderDirty) {
            this.childrenOrderDirty = false;
        }
        this._transformNodePool.length = 0;
    },
    transform: function () {
        var locPool = this._transformNodePool;
        locPool.sort(this._sortNodeByLevelAsc);
        var i, len, cmd;
        for (i = 0, len = locPool.length; i < len; i++) {
            cmd = locPool[i];
            cmd.updateStatus();
        }
        locPool.length = 0;
    },
    transformDirty: function () {
        return this._transformNodePool.length > 0;
    },
    _sortNodeByLevelAsc: function (n1, n2) {
        return n1._curLevel - n2._curLevel;
    },
    pushDirtyNode: function (node) {
        this._transformNodePool.push(node);
    },
    clearRenderCommands: function () {
        this._renderCmds.length = 0;
    },
    clear: function () {
        var gl = cc._renderContext;
        gl.clearColor(this._clearColor.r, this._clearColor.g, this._clearColor.b, this._clearColor.a);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    },
    setDepthTest: function (enable){
        var gl = cc._renderContext;
        if(enable){
            gl.clearDepth(1.0);
            gl.enable(gl.DEPTH_TEST);
            gl.depthFunc(gl.LEQUAL);
        }
        else{
            gl.disable(gl.DEPTH_TEST);
        }
    },
    pushRenderCommand: function (cmd) {
        if(!cmd.needDraw())
            return;
        if (this._isCacheToBufferOn) {
            var currentId = this._currentID, locCmdBuffer = this._cacheToBufferCmds;
            var cmdList = locCmdBuffer[currentId];
            if (cmdList.indexOf(cmd) === -1)
                cmdList.push(cmd);
        } else {
            if (this._renderCmds.indexOf(cmd) === -1) {
                this._renderCmds.push(cmd);
            }
        }
    },
    _increaseBatchingSize: function (increment) {
        _batchingSize += increment;
    },
    _uploadBufferData: function (cmd) {
        if (_batchingSize >= _vertexSize) {
            this._batchRendering();
        }
        var texture = cmd._node._texture;
        var blendSrc = cmd._node._blendFunc.src;
        var blendDst = cmd._node._blendFunc.dst;
        var shader = cmd._shaderProgram;
        if (_batchedInfo.texture !== texture ||
            _batchedInfo.blendSrc !== blendSrc ||
            _batchedInfo.blendDst !== blendDst ||
            _batchedInfo.shader !== shader) {
            this._batchRendering();
            _batchedInfo.texture = texture;
            _batchedInfo.blendSrc = blendSrc;
            _batchedInfo.blendDst = blendDst;
            _batchedInfo.shader = shader;
        }
        var len = cmd.uploadData(_vertexDataF32, _vertexDataUI32, _batchingSize * _sizePerVertex);
        if (len > 0) {
            _batchingSize += len;
        }
    },
    _batchRendering: function () {
        if (_batchingSize === 0 || !_batchedInfo.texture) {
            return;
        }
        var gl = cc._renderContext;
        var texture = _batchedInfo.texture;
        var shader = _batchedInfo.shader;
        var count = _batchingSize / 4;
        if (shader) {
            shader.use();
            shader._updateProjectionUniform();
        }
        cc.glBlendFunc(_batchedInfo.blendSrc, _batchedInfo.blendDst);
        cc.glBindTexture2DN(0, texture);
        var _bufferchanged = !gl.bindBuffer(gl.ARRAY_BUFFER, _quadVertexBuffer);
        if (_batchingSize > _vertexSize * 0.5) {
            gl.bufferData(gl.ARRAY_BUFFER, _vertexDataF32, gl.DYNAMIC_DRAW);
        }
        else {
            var view = _vertexDataF32.subarray(0, _batchingSize * _sizePerVertex);
            gl.bufferData(gl.ARRAY_BUFFER, view, gl.DYNAMIC_DRAW);
        }
        if (_bufferchanged) {
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
            gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
            gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
        }
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _quadIndexBuffer);
        gl.drawElements(gl.TRIANGLES, count * 6, gl.UNSIGNED_SHORT, 0);
        cc.g_NumberOfDraws++;
        _batchingSize = 0;
    },
    rendering: function (ctx, cmds) {
        var locCmds = cmds || this._renderCmds,
            i, len, cmd, next, batchCount,
            context = ctx || cc._renderContext;
        context.bindBuffer(gl.ARRAY_BUFFER, null);
        for (i = 0, len = locCmds.length; i < len; ++i) {
            cmd = locCmds[i];
            if (cmd.uploadData) {
                this._uploadBufferData(cmd);
            }
            else {
                if (_batchingSize > 0) {
                    this._batchRendering();
                }
                cmd.rendering(context);
            }
        }
        this._batchRendering();
        _batchedInfo.texture = null;
    }
};
})();
(function() {
    cc.Node.WebGLRenderCmd = function (renderable) {
        cc.Node.RenderCmd.call(this, renderable);
        this._shaderProgram = null;
    };
    var proto = cc.Node.WebGLRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype);
    proto.constructor = cc.Node.WebGLRenderCmd;
    proto._updateColor = function(){};
    proto.setShaderProgram = function (shaderProgram) {
        this._shaderProgram = shaderProgram;
    };
    proto.getShaderProgram = function () {
        return this._shaderProgram;
    };
})();
(function(){
    cc.Layer.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
    };
    var proto = cc.Layer.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.Layer.WebGLRenderCmd;
    proto.bake = function(){};
    proto.unbake = function(){};
    proto._bakeForAddChild = function(){};
})();
(function(){
    cc.LayerColor.WebGLRenderCmd = function(renderable){
        cc.Layer.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
        var _t = this;
        _t._squareVerticesAB = new ArrayBuffer(48);
        _t._squareColorsAB = new ArrayBuffer(16);
        var locSquareVerticesAB = _t._squareVerticesAB, locSquareColorsAB = _t._squareColorsAB;
        var locVertex3FLen = cc.Vertex3F.BYTES_PER_ELEMENT, locColorLen = cc.Color.BYTES_PER_ELEMENT;
        _t._squareVertices = [new cc.Vertex3F(0, 0, 0, locSquareVerticesAB, 0),
            new cc.Vertex3F(0, 0, 0, locSquareVerticesAB, locVertex3FLen),
            new cc.Vertex3F(0, 0, 0, locSquareVerticesAB, locVertex3FLen * 2),
            new cc.Vertex3F(0, 0, 0, locSquareVerticesAB, locVertex3FLen * 3)];
        _t._squareColors = [cc.color(0, 0, 0, 255, locSquareColorsAB, 0),
            cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen),
            cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen * 2),
            cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen * 3)];
        _t._verticesFloat32Buffer = cc._renderContext.createBuffer();
        _t._colorsUint8Buffer = cc._renderContext.createBuffer();
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR);
    };
    var proto = cc.LayerColor.WebGLRenderCmd.prototype = Object.create(cc.Layer.WebGLRenderCmd.prototype);
    proto.constructor = cc.LayerColor.WebGLRenderCmd;
    proto.rendering = function (ctx) {
        var context = ctx || cc._renderContext;
        var node = this._node;
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
        cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
        context.bindBuffer(context.ARRAY_BUFFER, this._verticesFloat32Buffer);
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, context.FLOAT, false, 0, 0);
        context.bindBuffer(context.ARRAY_BUFFER, this._colorsUint8Buffer);
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, 0, 0);
        context.drawArrays(context.TRIANGLE_STRIP, 0, this._squareVertices.length);
    };
    proto.transform = function (parentCmd, recursive) {
        this.originTransform(parentCmd, recursive);
        var node = this._node,
            width = node._contentSize.width,
            height = node._contentSize.height;
        var locSquareVertices = this._squareVertices;
        locSquareVertices[1].x = width;
        locSquareVertices[2].y = height;
        locSquareVertices[3].x = width;
        locSquareVertices[3].y = height;
        locSquareVertices[0].z =
        locSquareVertices[1].z =
        locSquareVertices[2].z =
        locSquareVertices[3].z = node._vertexZ;
        this._bindLayerVerticesBufferData();
    };
    proto._updateColor = function(){
        var locDisplayedColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity,
            locSquareColors = this._squareColors;
        for (var i = 0; i < 4; i++) {
            locSquareColors[i].r = locDisplayedColor.r;
            locSquareColors[i].g = locDisplayedColor.g;
            locSquareColors[i].b = locDisplayedColor.b;
            locSquareColors[i].a = locDisplayedOpacity;
        }
        this._bindLayerColorsBufferData();
    };
    proto._bindLayerVerticesBufferData = function(){
        var glContext = cc._renderContext;
        glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB, glContext.DYNAMIC_DRAW);
    };
    proto._bindLayerColorsBufferData = function(){
        var glContext = cc._renderContext;
        glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW);
    };
    proto.updateBlendFunc = function(blendFunc){};
})();
(function(){
    cc.LayerGradient.WebGLRenderCmd = function(renderable){
        cc.LayerColor.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._clipRect = new cc.Rect();
        this._clippingRectDirty = false;
    };
    var proto = cc.LayerGradient.WebGLRenderCmd.prototype = Object.create(cc.LayerColor.WebGLRenderCmd.prototype);
    proto.constructor = cc.LayerGradient.WebGLRenderCmd;
    proto.updateStatus = function () {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.gradientDirty) {
            this._dirtyFlag |= flags.colorDirty;
            this._updateVertex();
            this._dirtyFlag = locFlag & flags.gradientDirty ^ locFlag;
        }
        cc.Node.RenderCmd.prototype.updateStatus.call(this);
    };
    proto._syncStatus = function (parentCmd) {
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if (locFlag & flags.gradientDirty) {
            this._dirtyFlag |= flags.colorDirty;
            this._updateVertex();
            this._dirtyFlag = locFlag & flags.gradientDirty ^ locFlag;
        }
        cc.Node.RenderCmd.prototype._syncStatus.call(this, parentCmd);
    };
    proto.transform = function (parentCmd, recursive) {
        this.originTransform(parentCmd, recursive);
        this._updateVertex();
    };
    proto._updateVertex = function () {
        var node = this._node, stops = node._colorStops;
        if(!stops || stops.length < 2)
            return;
        this._clippingRectDirty = true;
        var stopsLen = stops.length, verticesLen = stopsLen * 2, i, contentSize = node._contentSize;
        var locVertices = this._squareVertices;
        if (locVertices.length < verticesLen) {
            this._squareVerticesAB = new ArrayBuffer(verticesLen * 12);
            locVertices.length = 0;
            var locSquareVerticesAB = this._squareVerticesAB;
            var locVertex3FLen = cc.Vertex3F.BYTES_PER_ELEMENT;
            for(i = 0; i < verticesLen; i++){
                locVertices.push(new cc.Vertex3F(0, 0, 0, locSquareVerticesAB, locVertex3FLen * i));
            }
        }
        var angle = Math.PI + cc.pAngleSigned(cc.p(0, -1), node._alongVector), locAnchor = cc.p(contentSize.width/2, contentSize.height /2);
        var degrees = Math.round(cc.radiansToDegrees(angle));
        var transMat = cc.affineTransformMake(1, 0, 0, 1, locAnchor.x, locAnchor.y);
        transMat = cc.affineTransformRotate(transMat, angle);
        var a, b;
        if(degrees < 90) {
            a = cc.p(-locAnchor.x, locAnchor.y);
            b = cc.p(locAnchor.x, locAnchor.y);
        } else if(degrees < 180) {
            a = cc.p(locAnchor.x, locAnchor.y);
            b = cc.p(locAnchor.x, -locAnchor.y);
        } else if(degrees < 270) {
            a = cc.p(locAnchor.x, -locAnchor.y);
            b = cc.p(-locAnchor.x, -locAnchor.y);
        } else {
            a = cc.p(-locAnchor.x, -locAnchor.y);
            b = cc.p(-locAnchor.x, locAnchor.y);
        }
        var sin = Math.sin(angle), cos = Math.cos(angle);
        var tx = Math.abs((a.x * cos - a.y * sin)/locAnchor.x), ty = Math.abs((b.x * sin + b.y * cos)/locAnchor.y);
        transMat = cc.affineTransformScale(transMat, tx, ty);
        for (i = 0; i < stopsLen; i++) {
            var stop = stops[i], y = stop.p * contentSize.height ;
            var p0 = cc.pointApplyAffineTransform(- locAnchor.x , y - locAnchor.y, transMat);
            locVertices[i * 2].x = p0.x;
            locVertices[i * 2].y = p0.y;
            locVertices[i * 2].z = node._vertexZ;
            var p1 = cc.pointApplyAffineTransform(contentSize.width - locAnchor.x, y - locAnchor.y, transMat);
            locVertices[i * 2 + 1].x = p1.x;
            locVertices[i * 2 + 1].y = p1.y;
            locVertices[i * 2 + 1].z = node._vertexZ;
        }
        this._bindLayerVerticesBufferData();
    };
    proto._updateColor = function() {
        var node = this._node, stops = node._colorStops;
        if(!stops || stops.length < 2)
            return;
        var stopsLen = stops.length;
        var locColors = this._squareColors, verticesLen = stopsLen * 2;
        if (locColors.length < verticesLen) {
            this._squareColorsAB = new ArrayBuffer(verticesLen * 4);
            locColors.length = 0;
            var locSquareColorsAB = this._squareColorsAB;
            var locColorLen = cc.Color.BYTES_PER_ELEMENT;
            for(i = 0; i < verticesLen; i++){
                locColors.push(cc.color(0, 0, 0, 255, locSquareColorsAB, locColorLen * i));
            }
        }
        var opacityf = this._displayedOpacity / 255.0;
        for(i = 0; i < stopsLen; i++){
            var stopColor = stops[i].color, locSquareColor0 = locColors[i * 2], locSquareColor1 = locColors[i * 2 + 1];
            locSquareColor0.r = stopColor.r;
            locSquareColor0.g = stopColor.g;
            locSquareColor0.b = stopColor.b;
            locSquareColor0.a = stopColor.a * opacityf;
            locSquareColor1.r = stopColor.r;
            locSquareColor1.g = stopColor.g;
            locSquareColor1.b = stopColor.b;
            locSquareColor1.a = stopColor.a * opacityf;
        }
        this._bindLayerColorsBufferData();
    };
    proto.rendering = function (ctx) {
        var context = ctx || cc._renderContext, node = this._node;
        var clippingRect = this._getClippingRect();
        context.enable(context.SCISSOR_TEST);
        cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
        cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
        context.bindBuffer(context.ARRAY_BUFFER, this._verticesFloat32Buffer);
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, context.FLOAT, false, 0, 0);
        context.bindBuffer(context.ARRAY_BUFFER, this._colorsUint8Buffer);
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, 0, 0);
        context.drawArrays(context.TRIANGLE_STRIP, 0, this._squareVertices.length);
        context.disable(context.SCISSOR_TEST);
    };
    proto._getClippingRect = function(){
        if(this._clippingRectDirty){
            var node = this._node;
            var rect = cc.rect(0, 0, node._contentSize.width, node._contentSize.height);
            var trans = node.getNodeToWorldTransform();
            this._clipRect = cc._rectApplyAffineTransformIn(rect, trans);
        }
        return this._clipRect;
    };
})();
(function() {
    cc.Sprite.WebGLRenderCmd = function (renderable) {
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._vertices = [
            {x: 0, y: 0, u: 0, v: 0},
            {x: 0, y: 0, u: 0, v: 0},
            {x: 0, y: 0, u: 0, v: 0},
            {x: 0, y: 0, u: 0, v: 0}
        ];
        this._color = new Uint32Array(1);
        this._dirty = false;
        this._recursiveDirty = false;
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
    };
    var proto = cc.Sprite.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.Sprite.WebGLRenderCmd;
    proto.updateBlendFunc = function (blendFunc) {};
    proto.setDirtyFlag = function(dirtyFlag){
        cc.Node.WebGLRenderCmd.prototype.setDirtyFlag.call(this, dirtyFlag);
        this._dirty = true;
    };
    proto.setDirtyRecursively = function (value) {
        this._recursiveDirty = value;
        this._dirty = value;
        var locChildren = this._node._children, child, l = locChildren ? locChildren.length : 0;
        for (var i = 0; i < l; i++) {
            child = locChildren[i];
            (child instanceof cc.Sprite) && child._renderCmd.setDirtyRecursively(value);
        }
    };
    proto._setBatchNodeForAddChild = function (child) {
        var node = this._node;
        if (node._batchNode) {
            if (!(child instanceof cc.Sprite)) {
                cc.log(cc._LogInfos.Sprite_addChild);
                return false;
            }
            if (child.texture._webTextureObj !== node.textureAtlas.texture._webTextureObj)
                cc.log(cc._LogInfos.Sprite_addChild_2);
            node._batchNode.appendChild(child);
            if (!node._reorderChildDirty)
                node._setReorderChildDirtyRecursively();
        }
        return true;
    };
    proto._handleTextureForRotatedTexture = function (texture) {
        return texture;
    };
    proto.isFrameDisplayed = function (frame) {
        var node = this._node;
        return (cc.rectEqualToRect(frame.getRect(), node._rect) && frame.getTexture().getName() === node._texture.getName()
        && cc.pointEqualToPoint(frame.getOffset(), node._unflippedOffsetPositionFromCenter));
    };
    proto._textureLoadedCallback = function (sender) {
        if (this._textureLoaded)
            return;
        this._textureLoaded = true;
        var locRect = this._rect;
        if (!locRect) {
            locRect = cc.rect(0, 0, sender.width, sender.height);
        } else if (cc._rectEqualToZero(locRect)) {
            locRect.width = sender.width;
            locRect.height = sender.height;
        }
        this.texture = sender;
        this.setTextureRect(locRect, this._rectRotated);
        this.setBatchNode(this._batchNode);
        this.dispatchEvent("load");
        cc.renderer.childrenOrderDirty = true;
    };
    proto._setTextureCoords = function (rect, needConvert) {
        if (needConvert === undefined)
            needConvert = true;
        if (needConvert)
            rect = cc.rectPointsToPixels(rect);
        var node = this._node;
        var tex = node._batchNode ? node.textureAtlas.texture : node._texture;
        var uvs = this._vertices;
        if (!tex)
            return;
        var atlasWidth = tex.pixelsWidth;
        var atlasHeight = tex.pixelsHeight;
        var left, right, top, bottom, tempSwap;
        if (node._rectRotated) {
            if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
                left = (2 * rect.x + 1) / (2 * atlasWidth);
                right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
                top = (2 * rect.y + 1) / (2 * atlasHeight);
                bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
            } else {
                left = rect.x / atlasWidth;
                right = (rect.x + rect.height) / atlasWidth;
                top = rect.y / atlasHeight;
                bottom = (rect.y + rect.width) / atlasHeight;
            }
            if (node._flippedX) {
                tempSwap = top;
                top = bottom;
                bottom = tempSwap;
            }
            if (node._flippedY) {
                tempSwap = left;
                left = right;
                right = tempSwap;
            }
            uvs[0].u = right;
            uvs[0].v = top;
            uvs[1].u = left;
            uvs[1].v = top;
            uvs[2].u = right;
            uvs[2].v = bottom;
            uvs[3].u = left;
            uvs[3].v = bottom;
        } else {
            if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
                left = (2 * rect.x + 1) / (2 * atlasWidth);
                right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
                top = (2 * rect.y + 1) / (2 * atlasHeight);
                bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
            } else {
                left = rect.x / atlasWidth;
                right = (rect.x + rect.width) / atlasWidth;
                top = rect.y / atlasHeight;
                bottom = (rect.y + rect.height) / atlasHeight;
            }
            if (node._flippedX) {
                tempSwap = left;
                left = right;
                right = tempSwap;
            }
            if (node._flippedY) {
                tempSwap = top;
                top = bottom;
                bottom = tempSwap;
            }
            uvs[0].u = left;
            uvs[0].v = top;
            uvs[1].u = left;
            uvs[1].v = bottom;
            uvs[2].u = right;
            uvs[2].v = top;
            uvs[3].u = right;
            uvs[3].v = bottom;
        }
    };
    proto._setColorDirty = function () {};
    proto._updateBlendFunc = function () {
        if (this._batchNode) {
            cc.log(cc._LogInfos.Sprite__updateBlendFunc);
            return;
        }
        var node = this._node,
            blendFunc = node._blendFunc;
        if (!node._texture || !node._texture.hasPremultipliedAlpha()) {
            if (blendFunc.src === cc.ONE && blendFunc.dst === cc.BLEND_DST) {
                blendFunc.src = cc.SRC_ALPHA;
            }
            node.opacityModifyRGB = false;
        } else {
            if (blendFunc.src === cc.SRC_ALPHA && blendFunc.dst === cc.BLEND_DST) {
                blendFunc.src = cc.ONE;
            }
            node.opacityModifyRGB = true;
        }
    };
    proto._setTexture = function (texture) {
        var node = this._node;
        if (node._batchNode) {
            if(node._batchNode.texture !== texture){
                cc.log(cc._LogInfos.Sprite_setTexture);
                return;
            }
        } else {
            if(node._texture !== texture){
                node._textureLoaded = texture ? texture._textureLoaded : false;
                node._texture = texture;
                this._updateBlendFunc();
                if (node._textureLoaded) {
                    cc.renderer.childrenOrderDirty = true;
                }
            }
        }
    };
    proto._checkTextureBoundary = function (texture, rect, rotated) {
        if (texture && texture.url) {
            var _x, _y;
            if (rotated) {
                _x = rect.x + rect.height;
                _y = rect.y + rect.width;
            } else {
                _x = rect.x + rect.width;
                _y = rect.y + rect.height;
            }
            if (_x > texture.width) {
                cc.error(cc._LogInfos.RectWidth, texture.url);
            }
            if (_y > texture.height) {
                cc.error(cc._LogInfos.RectHeight, texture.url);
            }
        }
    };
    proto.transform = function (parentCmd, recursive) {
        this.originTransform(parentCmd, recursive);
        var node = this._node,
            lx = node._offsetPosition.x, rx = lx + node._rect.width,
            by = node._offsetPosition.y, ty = by + node._rect.height,
            wt = this._worldTransform;
        var vertices = this._vertices;
        vertices[0].x = lx * wt.a + ty * wt.c + wt.tx;
        vertices[0].y = lx * wt.b + ty * wt.d + wt.ty;
        vertices[1].x = lx * wt.a + by * wt.c + wt.tx;
        vertices[1].y = lx * wt.b + by * wt.d + wt.ty;
        vertices[2].x = rx * wt.a + ty * wt.c + wt.tx;
        vertices[2].y = rx * wt.b + ty * wt.d + wt.ty;
        vertices[3].x = rx * wt.a + by * wt.c + wt.tx;
        vertices[3].y = rx * wt.b + by * wt.d + wt.ty;
    };
    proto.needDraw = function () {
        var node = this._node, locTexture = node._texture;
        return (this._needDraw && locTexture);
    };
    proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
        var node = this._node, locTexture = node._texture;
        if (!(locTexture && locTexture._textureLoaded && node._rect.width && node._rect.height) || !this._displayedOpacity)
            return false;
        var opacity = this._displayedOpacity;
        var r = this._displayedColor.r,
            g = this._displayedColor.g,
            b = this._displayedColor.b;
        if (node._opacityModifyRGB) {
            var a = opacity / 255;
            r *= a;
            g *= a;
            b *= a;
        }
        this._color[0] = ((opacity<<24) | (b<<16) | (g<<8) | r);
        var z = node._vertexZ;
        var vertices = this._vertices;
        var i, len = vertices.length, vertex, offset = vertexDataOffset;
        for (i = 0; i < len; ++i) {
            vertex = vertices[i];
            f32buffer[offset] = vertex.x;
            f32buffer[offset + 1] = vertex.y;
            f32buffer[offset + 2] = z;
            ui32buffer[offset + 3] = this._color[0];
            f32buffer[offset + 4] = vertex.u;
            f32buffer[offset + 5] = vertex.v;
            offset += 6;
        }
        return len;
    };
})();
(function() {
    cc.LabelTTF.WebGLRenderCmd = function (renderable) {
        cc.Sprite.WebGLRenderCmd.call(this, renderable);
        cc.LabelTTF.CacheRenderCmd.call(this);
    };
    var proto = cc.LabelTTF.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
    cc.inject(cc.LabelTTF.CacheRenderCmd.prototype, proto);
    proto.constructor = cc.LabelTTF.WebGLRenderCmd;
    proto._updateColor = function () {};
})();
cc.DrawingPrimitiveWebGL = cc.Class.extend({
    _renderContext:null,
    _initialized:false,
    _shader: null,
    _colorLocation: "u_color",
    _colorArray: null,
    _pointSizeLocation: "u_pointSize",
    _pointSize:-1,
    ctor:function (ctx) {
        if (ctx == null)
            ctx = cc._renderContext;
        if (!ctx instanceof  WebGLRenderingContext)
            throw new Error("Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext");
        this._renderContext = ctx;
        this._colorArray = new Float32Array([1.0, 1.0, 1.0, 1.0]);
    },
    lazy_init:function () {
        var _t = this;
        if (!_t._initialized) {
            _t._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR);
            _t._shader._addUniformLocation(this._colorLocation);
            _t._shader._addUniformLocation(this._pointSizeLocation);
            _t._initialized = true;
        }
    },
    drawInit:function () {
        this._initialized = false;
    },
    drawPoint:function (point) {
        this.lazy_init();
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([point.x, point.y]), glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.POINTS, 0, 1);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawPoints:function (points, numberOfPoints) {
        if (!points || points.length === 0)
            return;
        this.lazy_init();
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(points), glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.POINTS, 0, points.length);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    _pointsToTypeArray:function (points) {
        var typeArr = new Float32Array(points.length * 2);
        for (var i = 0; i < points.length; i++) {
            typeArr[i * 2] = points[i].x;
            typeArr[i * 2 + 1] = points[i].y;
        }
        return typeArr;
    },
    drawLine:function (origin, destination) {
        this.lazy_init();
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray([origin, destination]), glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.LINES, 0, 2);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawRect:function (origin, destination) {
        this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
        this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
        this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
        this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
    },
    drawSolidRect:function (origin, destination, color) {
        var vertices = [
            origin,
            cc.p(destination.x, origin.y),
            destination,
            cc.p(origin.x, destination.y)
        ];
        this.drawSolidPoly(vertices, 4, color);
    },
    drawPoly:function (vertices, numOfVertices, closePolygon) {
        this.lazy_init();
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(vertices), glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        if (closePolygon)
            glContext.drawArrays(glContext.LINE_LOOP, 0, vertices.length);
        else
            glContext.drawArrays(glContext.LINE_STRIP, 0, vertices.length);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawSolidPoly:function (poli, numberOfPoints, color) {
        this.lazy_init();
        if (color)
            this.setDrawColor(color.r, color.g, color.b, color.a);
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(poli), glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.TRIANGLE_FAN, 0, poli.length);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawCircle:function (center, radius, angle, segments, drawLineToCenter) {
        this.lazy_init();
        var additionalSegment = 1;
        if (drawLineToCenter)
            additionalSegment++;
        var coef = 2.0 * Math.PI / segments;
        var vertices = new Float32Array((segments + 2) * 2);
        if (!vertices)
            return;
        for (var i = 0; i <= segments; i++) {
            var rads = i * coef;
            var j = radius * Math.cos(rads + angle) + center.x;
            var k = radius * Math.sin(rads + angle) + center.y;
            vertices[i * 2] = j;
            vertices[i * 2 + 1] = k;
        }
        vertices[(segments + 1) * 2] = center.x;
        vertices[(segments + 1) * 2 + 1] = center.y;
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.LINE_STRIP, 0, segments + additionalSegment);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawQuadBezier:function (origin, control, destination, segments) {
        this.lazy_init();
        var vertices = new Float32Array((segments + 1) * 2);
        var t = 0.0;
        for (var i = 0; i < segments; i++) {
            vertices[i * 2] = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
            vertices[i * 2 + 1] = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
            t += 1.0 / segments;
        }
        vertices[segments * 2] = destination.x;
        vertices[segments * 2 + 1] = destination.y;
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawCubicBezier:function (origin, control1, control2, destination, segments) {
        this.lazy_init();
        var vertices = new Float32Array((segments + 1) * 2);
        var t = 0;
        for (var i = 0; i < segments; i++) {
            vertices[i * 2] = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
            vertices[i * 2 + 1] = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
            t += 1.0 / segments;
        }
        vertices[segments * 2] = destination.x;
        vertices[segments * 2 + 1] = destination.y;
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    drawCatmullRom:function (points, segments) {
        this.drawCardinalSpline(points, 0.5, segments);
    },
    drawCardinalSpline:function (config, tension, segments) {
        this.lazy_init();
        var vertices = new Float32Array((segments + 1) * 2);
        var p, lt, deltaT = 1.0 / config.length;
        for (var i = 0; i < segments + 1; i++) {
            var dt = i / segments;
            if (dt === 1) {
                p = config.length - 1;
                lt = 1;
            } else {
                p = 0 | (dt / deltaT);
                lt = (dt - deltaT * p) / deltaT;
            }
            var newPos = cc.cardinalSplineAt(
                cc.getControlPointAt(config, p - 1),
                cc.getControlPointAt(config, p),
                cc.getControlPointAt(config, p + 1),
                cc.getControlPointAt(config, p + 2),
                tension, lt);
            vertices[i * 2] = newPos.x;
            vertices[i * 2 + 1] = newPos.y;
        }
        var glContext = this._renderContext;
        this._shader.use();
        this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
        glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray);
        var pointBuffer = glContext.createBuffer();
        glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
        glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
        glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
        glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
        glContext.deleteBuffer(pointBuffer);
        cc.incrementGLDraws(1);
    },
    setDrawColor:function (r, g, b, a) {
        this._colorArray[0] = r / 255.0;
        this._colorArray[1] = g / 255.0;
        this._colorArray[2] = b / 255.0;
        this._colorArray[3] = a / 255.0;
    },
    setPointSize:function (pointSize) {
        this._pointSize = pointSize * cc.contentScaleFactor();
    },
    setLineWidth:function (width) {
        if(this._renderContext.lineWidth)
            this._renderContext.lineWidth(width);
    }
});
var _p = cc.inputManager;
_p.setAccelerometerEnabled = function(isEnable){
    var _t = this;
    if(_t._accelEnabled === isEnable)
        return;
    _t._accelEnabled = isEnable;
    var scheduler = cc.director.getScheduler();
    if(_t._accelEnabled){
        _t._accelCurTime = 0;
        scheduler.scheduleUpdate(_t);
    } else {
        _t._accelCurTime = 0;
        scheduler.scheduleUpdate(_t);
    }
};
_p.setAccelerometerInterval = function(interval){
    if (this._accelInterval !== interval) {
        this._accelInterval = interval;
    }
};
_p._registerKeyboardEvent = function(){
    cc._canvas.addEventListener("keydown", function (e) {
        cc.eventManager.dispatchEvent(new cc.EventKeyboard(e.keyCode, true));
        e.stopPropagation();
        e.preventDefault();
    }, false);
    cc._canvas.addEventListener("keyup", function (e) {
        cc.eventManager.dispatchEvent(new cc.EventKeyboard(e.keyCode, false));
        e.stopPropagation();
        e.preventDefault();
    }, false);
};
_p._registerAccelerometerEvent = function(){
    var w = window, _t = this;
    _t._acceleration = new cc.Acceleration();
    _t._accelDeviceEvent = w.DeviceMotionEvent || w.DeviceOrientationEvent;
    if (cc.sys.browserType === cc.sys.BROWSER_TYPE_MOBILE_QQ)
        _t._accelDeviceEvent = window.DeviceOrientationEvent;
    var _deviceEventType = (_t._accelDeviceEvent === w.DeviceMotionEvent) ? "devicemotion" : "deviceorientation";
    var ua = navigator.userAgent;
    if (/Android/.test(ua) || (/Adr/.test(ua) && cc.sys.browserType === cc.BROWSER_TYPE_UC)) {
        _t._minus = -1;
    }
    w.addEventListener(_deviceEventType, _t.didAccelerate.bind(_t), false);
};
_p.didAccelerate = function (eventData) {
    var _t = this, w = window;
    if (!_t._accelEnabled)
        return;
    var mAcceleration = _t._acceleration;
    var x, y, z;
    if (_t._accelDeviceEvent === window.DeviceMotionEvent) {
        var eventAcceleration = eventData["accelerationIncludingGravity"];
        x = _t._accelMinus * eventAcceleration.x * 0.1;
        y = _t._accelMinus * eventAcceleration.y * 0.1;
        z = eventAcceleration.z * 0.1;
    } else {
        x = (eventData["gamma"] / 90) * 0.981;
        y = -(eventData["beta"] / 90) * 0.981;
        z = (eventData["alpha"] / 90) * 0.981;
    }
    mAcceleration.x = x;
    mAcceleration.y = y;
    mAcceleration.z = z;
    mAcceleration.timestamp = eventData.timeStamp || Date.now();
    var tmpX = mAcceleration.x;
    if(w.orientation === cc.UIInterfaceOrientationLandscapeRight){
        mAcceleration.x = -mAcceleration.y;
        mAcceleration.y = tmpX;
    }else if(w.orientation === cc.UIInterfaceOrientationLandscapeLeft){
        mAcceleration.x = mAcceleration.y;
        mAcceleration.y = -tmpX;
    }else if(w.orientation === cc.UIInterfaceOrientationPortraitUpsideDown){
        mAcceleration.x = -mAcceleration.x;
        mAcceleration.y = -mAcceleration.y;
    }
};
delete _p;
cc.vertexLineToPolygon = function (points, stroke, vertices, offset, nuPoints) {
    nuPoints += offset;
    if (nuPoints <= 1)
        return;
    stroke *= 0.5;
    var idx;
    var nuPointsMinus = nuPoints - 1;
    for (var i = offset; i < nuPoints; i++) {
        idx = i * 2;
        var p1 = cc.p(points[i * 2], points[i * 2 + 1]);
        var perpVector;
        if (i === 0)
            perpVector = cc.pPerp(cc.pNormalize(cc.pSub(p1, cc.p(points[(i + 1) * 2], points[(i + 1) * 2 + 1]))));
        else if (i === nuPointsMinus)
            perpVector = cc.pPerp(cc.pNormalize(cc.pSub(cc.p(points[(i - 1) * 2], points[(i - 1) * 2 + 1]), p1)));
        else {
            var p0 = cc.p(points[(i - 1) * 2], points[(i - 1) * 2 + 1]);
            var p2 = cc.p(points[(i + 1) * 2], points[(i + 1) * 2 + 1]);
            var p2p1 = cc.pNormalize(cc.pSub(p2, p1));
            var p0p1 = cc.pNormalize(cc.pSub(p0, p1));
            var angle = Math.acos(cc.pDot(p2p1, p0p1));
            if (angle < cc.degreesToRadians(70))
                perpVector = cc.pPerp(cc.pNormalize(cc.pMidpoint(p2p1, p0p1)));
            else if (angle < cc.degreesToRadians(170))
                perpVector = cc.pNormalize(cc.pMidpoint(p2p1, p0p1));
            else
                perpVector = cc.pPerp(cc.pNormalize(cc.pSub(p2, p0)));
        }
        perpVector = cc.pMult(perpVector, stroke);
        vertices[idx * 2] = p1.x + perpVector.x;
        vertices[idx * 2 + 1] = p1.y + perpVector.y;
        vertices[(idx + 1) * 2] = p1.x - perpVector.x;
        vertices[(idx + 1) * 2 + 1] = p1.y - perpVector.y;
    }
    offset = (offset === 0) ? 0 : offset - 1;
    for (i = offset; i < nuPointsMinus; i++) {
        idx = i * 2;
        var idx1 = idx + 2;
        var v1 = cc.vertex2(vertices[idx * 2], vertices[idx * 2 + 1]);
        var v2 = cc.vertex2(vertices[(idx + 1) * 2], vertices[(idx + 1) * 2 + 1]);
        var v3 = cc.vertex2(vertices[idx1 * 2], vertices[idx1 * 2]);
        var v4 = cc.vertex2(vertices[(idx1 + 1) * 2], vertices[(idx1 + 1) * 2 + 1]);
        var fixVertexResult = !cc.vertexLineIntersect(v1.x, v1.y, v4.x, v4.y, v2.x, v2.y, v3.x, v3.y);
        if (!fixVertexResult.isSuccess)
            if (fixVertexResult.value < 0.0 || fixVertexResult.value > 1.0)
                fixVertexResult.isSuccess = true;
        if (fixVertexResult.isSuccess) {
            vertices[idx1 * 2] = v4.x;
            vertices[idx1 * 2 + 1] = v4.y;
            vertices[(idx1 + 1) * 2] = v3.x;
            vertices[(idx1 + 1) * 2 + 1] = v3.y;
        }
    }
};
cc.vertexLineIntersect = function (Ax, Ay, Bx, By, Cx, Cy, Dx, Dy) {
    var distAB, theCos, theSin, newX;
    if ((Ax === Bx && Ay === By) || (Cx === Dx && Cy === Dy))
        return {isSuccess:false, value:0};
    Bx -= Ax;
    By -= Ay;
    Cx -= Ax;
    Cy -= Ay;
    Dx -= Ax;
    Dy -= Ay;
    distAB = Math.sqrt(Bx * Bx + By * By);
    theCos = Bx / distAB;
    theSin = By / distAB;
    newX = Cx * theCos + Cy * theSin;
    Cy = Cy * theCos - Cx * theSin;
    Cx = newX;
    newX = Dx * theCos + Dy * theSin;
    Dy = Dy * theCos - Dx * theSin;
    Dx = newX;
    if (Cy === Dy) return {isSuccess:false, value:0};
    var t = (Dx + (Cx - Dx) * Dy / (Dy - Cy)) / distAB;
    return {isSuccess:true, value:t};
};
cc.vertexListIsClockwise = function(verts) {
    for (var i = 0, len = verts.length; i < len; i++) {
        var a = verts[i];
        var b = verts[(i + 1) % len];
        var c = verts[(i + 2) % len];
        if (cc.pCross(cc.pSub(b, a), cc.pSub(c, b)) > 0)
            return false;
    }
    return true;
};
cc.CGAffineToGL = function (trans, mat) {
    mat[2] = mat[3] = mat[6] = mat[7] = mat[8] = mat[9] = mat[11] = mat[14] = 0.0;
    mat[10] = mat[15] = 1.0;
    mat[0] = trans.a;
    mat[4] = trans.c;
    mat[12] = trans.tx;
    mat[1] = trans.b;
    mat[5] = trans.d;
    mat[13] = trans.ty;
};
cc.GLToCGAffine = function (mat, trans) {
    trans.a = mat[0];
    trans.c = mat[4];
    trans.tx = mat[12];
    trans.b = mat[1];
    trans.d = mat[5];
    trans.ty = mat[13];
};
cc.EventAcceleration = cc.Event.extend({
    _acc: null,
    ctor: function (acc) {
        cc.Event.prototype.ctor.call(this, cc.Event.ACCELERATION);
        this._acc = acc;
    }
});
cc.EventKeyboard = cc.Event.extend({
    _keyCode: 0,
    _isPressed: false,
    ctor: function (keyCode, isPressed) {
        cc.Event.prototype.ctor.call(this, cc.Event.KEYBOARD);
        this._keyCode = keyCode;
        this._isPressed = isPressed;
    }
});
cc._EventListenerAcceleration = cc.EventListener.extend({
    _onAccelerationEvent: null,
    ctor: function (callback) {
        this._onAccelerationEvent = callback;
        var selfPointer = this;
        var listener = function (event) {
            selfPointer._onAccelerationEvent(event._acc, event);
        };
        cc.EventListener.prototype.ctor.call(this, cc.EventListener.ACCELERATION, cc._EventListenerAcceleration.LISTENER_ID, listener);
    },
    checkAvailable: function () {
        cc.assert(this._onAccelerationEvent, cc._LogInfos._EventListenerAcceleration_checkAvailable);
        return true;
    },
    clone: function () {
        return new cc._EventListenerAcceleration(this._onAccelerationEvent);
    }
});
cc._EventListenerAcceleration.LISTENER_ID = "__cc_acceleration";
cc._EventListenerAcceleration.create = function (callback) {
    return new cc._EventListenerAcceleration(callback);
};
cc._EventListenerKeyboard = cc.EventListener.extend({
    onKeyPressed: null,
    onKeyReleased: null,
    ctor: function () {
        var selfPointer = this;
        var listener = function (event) {
            if (event._isPressed) {
                if (selfPointer.onKeyPressed)
                    selfPointer.onKeyPressed(event._keyCode, event);
            } else {
                if (selfPointer.onKeyReleased)
                    selfPointer.onKeyReleased(event._keyCode, event);
            }
        };
        cc.EventListener.prototype.ctor.call(this, cc.EventListener.KEYBOARD, cc._EventListenerKeyboard.LISTENER_ID, listener);
    },
    clone: function () {
        var eventListener = new cc._EventListenerKeyboard();
        eventListener.onKeyPressed = this.onKeyPressed;
        eventListener.onKeyReleased = this.onKeyReleased;
        return eventListener;
    },
    checkAvailable: function () {
        if (this.onKeyPressed === null && this.onKeyReleased === null) {
            cc.log(cc._LogInfos._EventListenerKeyboard_checkAvailable);
            return false;
        }
        return true;
    }
});
cc._EventListenerKeyboard.LISTENER_ID = "__cc_keyboard";
cc._EventListenerKeyboard.create = function () {
    return new cc._EventListenerKeyboard();
};
cc.AtlasNode = cc.Node.extend({
    textureAtlas: null,
    quadsToDraw: 0,
    _itemsPerRow: 0,
    _itemsPerColumn: 0,
    _itemWidth: 0,
    _itemHeight: 0,
    _opacityModifyRGB: false,
    _blendFunc: null,
    _ignoreContentScaleFactor: false,
    _className: "AtlasNode",
    _texture: null,
    _textureForCanvas: null,
    ctor: function (tile, tileWidth, tileHeight, itemsToRender) {
        cc.Node.prototype.ctor.call(this);
        this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
        this._ignoreContentScaleFactor = false;
        itemsToRender !== undefined && this.initWithTileFile(tile, tileWidth, tileHeight, itemsToRender);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            this._renderCmd = new cc.AtlasNode.CanvasRenderCmd(this);
        else
            this._renderCmd = new cc.AtlasNode.WebGLRenderCmd(this);
    },
    updateAtlasValues: function () {
        cc.log(cc._LogInfos.AtlasNode_updateAtlasValues);
    },
    getColor: function () {
        if (this._opacityModifyRGB)
            return this._renderCmd._colorUnmodified;
        return cc.Node.prototype.getColor.call(this);
    },
    setOpacityModifyRGB: function (value) {
        var oldColor = this.color;
        this._opacityModifyRGB = value;
        this.setColor(oldColor);
    },
    isOpacityModifyRGB: function () {
        return this._opacityModifyRGB;
    },
    getBlendFunc: function () {
        return this._blendFunc;
    },
    setBlendFunc: function (src, dst) {
        if (dst === undefined)
            this._blendFunc = src;
        else
            this._blendFunc = {src: src, dst: dst};
    },
    setTextureAtlas: function (value) {
        this.textureAtlas = value;
    },
    getTextureAtlas: function () {
        return this.textureAtlas;
    },
    getQuadsToDraw: function () {
        return this.quadsToDraw;
    },
    setQuadsToDraw: function (quadsToDraw) {
        this.quadsToDraw = quadsToDraw;
    },
    initWithTileFile: function (tile, tileWidth, tileHeight, itemsToRender) {
        if (!tile)
            throw new Error("cc.AtlasNode.initWithTileFile(): title should not be null");
        var texture = cc.textureCache.addImage(tile);
        return this.initWithTexture(texture, tileWidth, tileHeight, itemsToRender);
    },
    initWithTexture: function(texture, tileWidth, tileHeight, itemsToRender){
        return this._renderCmd.initWithTexture(texture, tileWidth, tileHeight, itemsToRender);
    },
    setColor: function(color){
        this._renderCmd.setColor(color);
    },
    setOpacity: function (opacity) {
        this._renderCmd.setOpacity(opacity);
    },
    getTexture: function(){
        return this._texture;
    },
    setTexture: function(texture){
        this._texture = texture;
    },
    _setIgnoreContentScaleFactor: function (ignoreContentScaleFactor) {
        this._ignoreContentScaleFactor = ignoreContentScaleFactor;
    }
});
var _p = cc.AtlasNode.prototype;
cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
_p.texture;
cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
_p.textureAtlas;
_p.quadsToDraw;
cc.EventHelper.prototype.apply(_p);
cc.AtlasNode.create = function (tile, tileWidth, tileHeight, itemsToRender) {
    return new cc.AtlasNode(tile, tileWidth, tileHeight, itemsToRender);
};
(function(){
    cc.AtlasNode.CanvasRenderCmd = function(renderableObject){
        cc.Node.CanvasRenderCmd.call(this, renderableObject);
        this._needDraw = false;
        this._colorUnmodified = cc.color.WHITE;
        this._textureToRender = null;
    };
    var proto = cc.AtlasNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.AtlasNode.CanvasRenderCmd;
    proto.initWithTexture = function(texture, tileWidth, tileHeight, itemsToRender){
        var node = this._node;
        node._itemWidth = tileWidth;
        node._itemHeight = tileHeight;
        node._opacityModifyRGB = true;
        node._texture = texture;
        if (!node._texture) {
            cc.log(cc._LogInfos.AtlasNode__initWithTexture);
            return false;
        }
        this._textureToRender = texture;
        this._calculateMaxItems();
        node.quadsToDraw = itemsToRender;
        return true;
    };
    proto.setColor = function(color3){
        var node = this._node;
        var locRealColor = node._realColor;
        if ((locRealColor.r === color3.r) && (locRealColor.g === color3.g) && (locRealColor.b === color3.b))
            return;
        this._colorUnmodified = color3;
        this._changeTextureColor();
    };
    proto._changeTextureColor = function(){
        var node = this._node;
        var texture = node._texture,
            color = this._colorUnmodified,
            element = texture.getHtmlElementObj();
        var textureRect = cc.rect(0, 0, element.width, element.height);
        if(texture === this._textureToRender)
            this._textureToRender = texture._generateColorTexture(color.r, color.g, color.b, textureRect);
        else
            texture._generateColorTexture(color.r, color.g, color.b, textureRect, this._textureToRender.getHtmlElementObj());
    };
    proto.setOpacity = function(opacity){
        var node = this._node;
        cc.Node.prototype.setOpacity.call(node, opacity);
    };
    proto._calculateMaxItems = function(){
        var node = this._node;
        var selTexture = node._texture;
        var size = selTexture.getContentSize();
        node._itemsPerColumn = 0 | (size.height / node._itemHeight);
        node._itemsPerRow = 0 | (size.width / node._itemWidth);
    };
})();
cc.TextureAtlas = cc.Class.extend({
    dirty: false,
    texture: null,
    _indices: null,
    _buffersVBO: null,
    _capacity: 0,
    _quads: null,
    _quadsArrayBuffer: null,
    _quadsWebBuffer: null,
    _quadsReader: null,
    ctor: function (fileName, capacity) {
        this._buffersVBO = [];
        if (cc.isString(fileName)) {
            this.initWithFile(fileName, capacity);
        } else if (fileName instanceof cc.Texture2D) {
            this.initWithTexture(fileName, capacity);
        }
    },
    getTotalQuads: function () {
        return this._totalQuads;
    },
    getCapacity: function () {
        return this._capacity;
    },
    getTexture: function () {
        return this.texture;
    },
    setTexture: function (texture) {
        this.texture = texture;
    },
    setDirty: function (dirty) {
        this.dirty = dirty;
    },
    isDirty: function () {
        return this.dirty;
    },
    getQuads: function () {
        return this._quads;
    },
    setQuads: function (quads) {
        this._quads = quads;
    },
    _copyQuadsToTextureAtlas: function (quads, index) {
        if (!quads)
            return;
        for (var i = 0; i < quads.length; i++)
            this._setQuadToArray(quads[i], index + i);
    },
    _setQuadToArray: function (quad, index) {
        var locQuads = this._quads;
        if (!locQuads[index]) {
            locQuads[index] = new cc.V3F_C4B_T2F_Quad(quad.tl, quad.bl, quad.tr, quad.br, this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT);
            return;
        }
        locQuads[index].bl = quad.bl;
        locQuads[index].br = quad.br;
        locQuads[index].tl = quad.tl;
        locQuads[index].tr = quad.tr;
    },
    description: function () {
        return '<cc.TextureAtlas | totalQuads =' + this._totalQuads + '>';
    },
    _setupIndices: function () {
        if (this._capacity === 0)
            return;
        var locIndices = this._indices, locCapacity = this._capacity;
        for (var i = 0; i < locCapacity; i++) {
            if (cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP) {
                locIndices[i * 6 + 0] = i * 4 + 0;
                locIndices[i * 6 + 1] = i * 4 + 0;
                locIndices[i * 6 + 2] = i * 4 + 2;
                locIndices[i * 6 + 3] = i * 4 + 1;
                locIndices[i * 6 + 4] = i * 4 + 3;
                locIndices[i * 6 + 5] = i * 4 + 3;
            } else {
                locIndices[i * 6 + 0] = i * 4 + 0;
                locIndices[i * 6 + 1] = i * 4 + 1;
                locIndices[i * 6 + 2] = i * 4 + 2;
                locIndices[i * 6 + 3] = i * 4 + 3;
                locIndices[i * 6 + 4] = i * 4 + 2;
                locIndices[i * 6 + 5] = i * 4 + 1;
            }
        }
    },
    _setupVBO: function () {
        var gl = cc._renderContext;
        this._buffersVBO[0] = gl.createBuffer();
        this._buffersVBO[1] = gl.createBuffer();
        this._quadsWebBuffer = gl.createBuffer();
        this._mapBuffers();
    },
    _mapBuffers: function () {
        var gl = cc._renderContext;
        gl.bindBuffer(gl.ARRAY_BUFFER, this._quadsWebBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
    },
    initWithFile: function (file, capacity) {
        var texture = cc.textureCache.addImage(file);
        if (texture)
            return this.initWithTexture(texture, capacity);
        else {
            cc.log(cc._LogInfos.TextureAtlas_initWithFile, file);
            return false;
        }
    },
    initWithTexture: function (texture, capacity) {
        cc.assert(texture, cc._LogInfos.TextureAtlas_initWithTexture);
        capacity = 0 | (capacity);
        this._capacity = capacity;
        this._totalQuads = 0;
        this.texture = texture;
        this._quads = [];
        this._indices = new Uint16Array(capacity * 6);
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        this._quadsArrayBuffer = new ArrayBuffer(quadSize * capacity);
        this._quadsReader = new Uint8Array(this._quadsArrayBuffer);
        if (!( this._quads && this._indices) && capacity > 0)
            return false;
        var locQuads = this._quads;
        for (var i = 0; i < capacity; i++)
            locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize);
        this._setupIndices();
        this._setupVBO();
        this.dirty = true;
        return true;
    },
    updateQuad: function (quad, index) {
        cc.assert(quad, cc._LogInfos.TextureAtlas_updateQuad);
        cc.assert(index >= 0 && index < this._capacity, cc._LogInfos.TextureAtlas_updateQuad_2);
        this._totalQuads = Math.max(index + 1, this._totalQuads);
        this._setQuadToArray(quad, index);
        this.dirty = true;
    },
    insertQuad: function (quad, index) {
        cc.assert(index < this._capacity, cc._LogInfos.TextureAtlas_insertQuad_2);
        this._totalQuads++;
        if (this._totalQuads > this._capacity) {
            cc.log(cc._LogInfos.TextureAtlas_insertQuad);
            return;
        }
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        var remaining = (this._totalQuads - 1) - index;
        var startOffset = index * quadSize;
        var moveLength = remaining * quadSize;
        this._quads[this._totalQuads - 1] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads - 1) * quadSize);
        this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize);
        this._setQuadToArray(quad, index);
        this.dirty = true;
    },
    insertQuads: function (quads, index, amount) {
        amount = amount || quads.length;
        cc.assert((index + amount) <= this._capacity, cc._LogInfos.TextureAtlas_insertQuads);
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        this._totalQuads += amount;
        if (this._totalQuads > this._capacity) {
            cc.log(cc._LogInfos.TextureAtlas_insertQuad);
            return;
        }
        var remaining = (this._totalQuads - 1) - index - amount;
        var startOffset = index * quadSize;
        var moveLength = remaining * quadSize;
        var lastIndex = (this._totalQuads - 1) - amount;
        var i;
        for (i = 0; i < amount; i++)
            this._quads[lastIndex + i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads - 1) * quadSize);
        this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize * amount);
        for (i = 0; i < amount; i++)
            this._setQuadToArray(quads[i], index + i);
        this.dirty = true;
    },
    insertQuadFromIndex: function (fromIndex, newIndex) {
        if (fromIndex === newIndex)
            return;
        cc.assert(newIndex >= 0 || newIndex < this._totalQuads, cc._LogInfos.TextureAtlas_insertQuadFromIndex);
        cc.assert(fromIndex >= 0 || fromIndex < this._totalQuads, cc._LogInfos.TextureAtlas_insertQuadFromIndex_2);
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        var locQuadsReader = this._quadsReader;
        var sourceArr = locQuadsReader.subarray(fromIndex * quadSize, quadSize);
        var startOffset, moveLength;
        if (fromIndex > newIndex) {
            startOffset = newIndex * quadSize;
            moveLength = (fromIndex - newIndex) * quadSize;
            locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize);
            locQuadsReader.set(sourceArr, startOffset);
        } else {
            startOffset = (fromIndex + 1) * quadSize;
            moveLength = (newIndex - fromIndex) * quadSize;
            locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength), startOffset - quadSize);
            locQuadsReader.set(sourceArr, newIndex * quadSize);
        }
        this.dirty = true;
    },
    removeQuadAtIndex: function (index) {
        cc.assert(index < this._totalQuads, cc._LogInfos.TextureAtlas_removeQuadAtIndex);
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        this._totalQuads--;
        this._quads.length = this._totalQuads;
        if (index !== this._totalQuads) {
            var startOffset = (index + 1) * quadSize;
            var moveLength = (this._totalQuads - index) * quadSize;
            this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset - quadSize);
        }
        this.dirty = true;
    },
    removeQuadsAtIndex: function (index, amount) {
        cc.assert(index + amount <= this._totalQuads, cc._LogInfos.TextureAtlas_removeQuadsAtIndex);
        this._totalQuads -= amount;
        if (index !== this._totalQuads) {
            var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
            var srcOffset = (index + amount) * quadSize;
            var moveLength = (this._totalQuads - index) * quadSize;
            var dstOffset = index * quadSize;
            this._quadsReader.set(this._quadsReader.subarray(srcOffset, srcOffset + moveLength), dstOffset);
        }
        this.dirty = true;
    },
    removeAllQuads: function () {
        this._quads.length = 0;
        this._totalQuads = 0;
    },
    _setDirty: function (dirty) {
        this.dirty = dirty;
    },
    resizeCapacity: function (newCapacity) {
        if (newCapacity === this._capacity)
            return true;
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        var oldCapacity = this._capacity;
        this._totalQuads = Math.min(this._totalQuads, newCapacity);
        this._capacity = 0 | newCapacity;
        var i, capacity = this._capacity, locTotalQuads = this._totalQuads;
        if (this._quads === null) {
            this._quads = [];
            this._quadsArrayBuffer = new ArrayBuffer(quadSize * capacity);
            this._quadsReader = new Uint8Array(this._quadsArrayBuffer);
            for (i = 0; i < capacity; i++)
                this._quads = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize);
        } else {
            var newQuads, newArrayBuffer, quads = this._quads;
            if (capacity > oldCapacity) {
                newQuads = [];
                newArrayBuffer = new ArrayBuffer(quadSize * capacity);
                for (i = 0; i < locTotalQuads; i++) {
                    newQuads[i] = new cc.V3F_C4B_T2F_Quad(quads[i].tl, quads[i].bl, quads[i].tr, quads[i].br,
                        newArrayBuffer, i * quadSize);
                }
                for (; i < capacity; i++)
                    newQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, newArrayBuffer, i * quadSize);
                this._quadsReader = new Uint8Array(newArrayBuffer);
                this._quads = newQuads;
                this._quadsArrayBuffer = newArrayBuffer;
            } else {
                var count = Math.max(locTotalQuads, capacity);
                newQuads = [];
                newArrayBuffer = new ArrayBuffer(quadSize * capacity);
                for (i = 0; i < count; i++) {
                    newQuads[i] = new cc.V3F_C4B_T2F_Quad(quads[i].tl, quads[i].bl, quads[i].tr, quads[i].br,
                        newArrayBuffer, i * quadSize);
                }
                this._quadsReader = new Uint8Array(newArrayBuffer);
                this._quads = newQuads;
                this._quadsArrayBuffer = newArrayBuffer;
            }
        }
        if (this._indices === null) {
            this._indices = new Uint16Array(capacity * 6);
        } else {
            if (capacity > oldCapacity) {
                var tempIndices = new Uint16Array(capacity * 6);
                tempIndices.set(this._indices, 0);
                this._indices = tempIndices;
            } else {
                this._indices = this._indices.subarray(0, capacity * 6);
            }
        }
        this._setupIndices();
        this._mapBuffers();
        this.dirty = true;
        return true;
    },
    increaseTotalQuadsWith: function (amount) {
        this._totalQuads += amount;
    },
    moveQuadsFromIndex: function (oldIndex, amount, newIndex) {
        if (newIndex === undefined) {
            newIndex = amount;
            amount = this._totalQuads - oldIndex;
            cc.assert((newIndex + (this._totalQuads - oldIndex)) <= this._capacity, cc._LogInfos.TextureAtlas_moveQuadsFromIndex);
            if (amount === 0)
                return;
        } else {
            cc.assert((newIndex + amount) <= this._totalQuads, cc._LogInfos.TextureAtlas_moveQuadsFromIndex_2);
            cc.assert(oldIndex < this._totalQuads, cc._LogInfos.TextureAtlas_moveQuadsFromIndex_3);
            if (oldIndex === newIndex)
                return;
        }
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        var srcOffset = oldIndex * quadSize;
        var srcLength = amount * quadSize;
        var locQuadsReader = this._quadsReader;
        var sourceArr = locQuadsReader.subarray(srcOffset, srcOffset + srcLength);
        var dstOffset = newIndex * quadSize;
        var moveLength, moveStart;
        if (newIndex < oldIndex) {
            moveLength = (oldIndex - newIndex) * quadSize;
            moveStart = newIndex * quadSize;
            locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), moveStart + srcLength)
        } else {
            moveLength = (newIndex - oldIndex) * quadSize;
            moveStart = (oldIndex + amount) * quadSize;
            locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), srcOffset);
        }
        locQuadsReader.set(sourceArr, dstOffset);
        this.dirty = true;
    },
    fillWithEmptyQuadsFromIndex: function (index, amount) {
        var count = amount * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        var clearReader = new Uint8Array(this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT, count);
        for (var i = 0; i < count; i++)
            clearReader[i] = 0;
    },
    drawQuads: function () {
        this.drawNumberOfQuads(this._totalQuads, 0);
    },
    _releaseBuffer: function () {
        var gl = cc._renderContext;
        if (this._buffersVBO) {
            if (this._buffersVBO[0])
                gl.deleteBuffer(this._buffersVBO[0]);
            if (this._buffersVBO[1])
                gl.deleteBuffer(this._buffersVBO[1])
        }
        if (this._quadsWebBuffer)
            gl.deleteBuffer(this._quadsWebBuffer);
    }
});
var _p = cc.TextureAtlas.prototype;
_p.totalQuads;
cc.defineGetterSetter(_p, "totalQuads", _p.getTotalQuads);
_p.capacity;
cc.defineGetterSetter(_p, "capacity", _p.getCapacity);
_p.quads;
cc.defineGetterSetter(_p, "quads", _p.getQuads, _p.setQuads);
cc.TextureAtlas.create = function (fileName, capacity) {
    return new cc.TextureAtlas(fileName, capacity);
};
cc.TextureAtlas.createWithTexture = cc.TextureAtlas.create;
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        cc.assert(cc.isFunction(cc._tmp.WebGLTextureAtlas), cc._LogInfos.MissingFile, "TexturesWebGL.js");
        cc._tmp.WebGLTextureAtlas();
        delete cc._tmp.WebGLTextureAtlas;
    }
});
cc.assert(cc.isFunction(cc._tmp.PrototypeTextureAtlas), cc._LogInfos.MissingFile, "TexturesPropertyDefine.js");
cc._tmp.PrototypeTextureAtlas();
delete cc._tmp.PrototypeTextureAtlas;
cc.PI2 = Math.PI * 2;
cc.DrawingPrimitiveCanvas = cc.Class.extend({
    _cacheArray:[],
    _renderContext:null,
    ctor:function (renderContext) {
        this._renderContext = renderContext;
    },
    drawPoint:function (point, size) {
        if (!size) {
            size = 1;
        }
        var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
        var newPoint = cc.p(point.x  * locScaleX, point.y * locScaleY);
        var ctx = this._renderContext.getContext();
        ctx.beginPath();
        ctx.arc(newPoint.x, -newPoint.y, size * locScaleX, 0, Math.PI * 2, false);
        ctx.closePath();
        ctx.fill();
    },
    drawPoints:function (points, numberOfPoints, size) {
        if (points == null)
            return;
        if (!size) {
            size = 1;
        }
        var locContext = this._renderContext.getContext(),locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
        locContext.beginPath();
        for (var i = 0, len = points.length; i < len; i++)
            locContext.arc(points[i].x * locScaleX, -points[i].y * locScaleY, size * locScaleX, 0, Math.PI * 2, false);
        locContext.closePath();
        locContext.fill();
    },
    drawLine:function (origin, destination) {
        var locContext = this._renderContext.getContext(), locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
        locContext.beginPath();
        locContext.moveTo(origin.x , -origin.y );
        locContext.lineTo(destination.x, -destination.y );
        locContext.closePath();
        locContext.stroke();
    },
    drawRect:function (origin, destination) {
        this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
        this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
        this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
        this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
    },
    drawSolidRect:function (origin, destination, color) {
        var vertices = [
            origin,
            cc.p(destination.x, origin.y),
            destination,
            cc.p(origin.x, destination.y)
        ];
        this.drawSolidPoly(vertices, 4, color);
    },
    drawPoly:function (vertices, numOfVertices, closePolygon, fill) {
        fill = fill || false;
        if (vertices == null)
            return;
        if (vertices.length < 3)
            throw new Error("Polygon's point must greater than 2");
        var firstPoint = vertices[0], locContext = this._renderContext.getContext();
        var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
        locContext.beginPath();
        locContext.moveTo(firstPoint.x , -firstPoint.y );
        for (var i = 1, len = vertices.length; i < len; i++)
            locContext.lineTo(vertices[i].x , -vertices[i].y );
        if (closePolygon)
            locContext.closePath();
        if (fill)
            locContext.fill();
        else
            locContext.stroke();
    },
    drawSolidPoly:function (polygons, numberOfPoints, color) {
        this.setDrawColor(color.r, color.g, color.b, color.a);
        this.drawPoly(polygons, numberOfPoints, true, true);
    },
    drawCircle: function (center, radius, angle, segments, drawLineToCenter) {
        drawLineToCenter = drawLineToCenter || false;
        var locContext = this._renderContext.getContext();
        var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
        locContext.beginPath();
        var endAngle = angle - Math.PI * 2;
        locContext.arc(0 | (center.x ), 0 | -(center.y ), radius , -angle, -endAngle, false);
        if (drawLineToCenter) {
            locContext.lineTo(0 | (center.x ), 0 | -(center.y ));
        }
        locContext.stroke();
    },
    drawQuadBezier:function (origin, control, destination, segments) {
        var vertices = this._cacheArray;
        vertices.length =0;
        var t = 0.0;
        for (var i = 0; i < segments; i++) {
            var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
            var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
            vertices.push(cc.p(x, y));
            t += 1.0 / segments;
        }
        vertices.push(cc.p(destination.x, destination.y));
        this.drawPoly(vertices, segments + 1, false, false);
    },
    drawCubicBezier:function (origin, control1, control2, destination, segments) {
        var vertices = this._cacheArray;
        vertices.length =0;
        var t = 0;
        for (var i = 0; i < segments; i++) {
            var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
            var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
            vertices.push(cc.p(x , y ));
            t += 1.0 / segments;
        }
        vertices.push(cc.p(destination.x , destination.y));
        this.drawPoly(vertices, segments + 1, false, false);
    },
    drawCatmullRom:function (points, segments) {
        this.drawCardinalSpline(points, 0.5, segments);
    },
    drawCardinalSpline:function (config, tension, segments) {
        cc._renderContext.setStrokeStyle("rgba(255,255,255,1)");
        var points = this._cacheArray;
        points.length = 0;
        var p, lt;
        var deltaT = 1.0 / config.length;
        for (var i = 0; i < segments + 1; i++) {
            var dt = i / segments;
            if (dt === 1) {
                p = config.length - 1;
                lt = 1;
            } else {
                p = 0 | (dt / deltaT);
                lt = (dt - deltaT * p) / deltaT;
            }
            var newPos = cc.CardinalSplineAt(
                cc.getControlPointAt(config, p - 1),
                cc.getControlPointAt(config, p - 0),
                cc.getControlPointAt(config, p + 1),
                cc.getControlPointAt(config, p + 2),
                tension, lt);
            points.push(newPos);
        }
        this.drawPoly(points, segments + 1, false, false);
    },
    drawImage:function (image, sourcePoint, sourceSize, destPoint, destSize) {
        var len = arguments.length;
        var ctx = this._renderContext.getContext();
        switch (len) {
            case 2:
                var height = image.height;
                ctx.drawImage(image, sourcePoint.x, -(sourcePoint.y + height));
                break;
            case 3:
                ctx.drawImage(image, sourcePoint.x, -(sourcePoint.y + sourceSize.height), sourceSize.width, sourceSize.height);
                break;
            case 5:
                ctx.drawImage(image, sourcePoint.x, sourcePoint.y, sourceSize.width, sourceSize.height, destPoint.x, -(destPoint.y + destSize.height),
                    destSize.width, destSize.height);
                break;
            default:
                throw new Error("Argument must be non-nil");
                break;
        }
    },
    drawStar:function (ctx, radius, color) {
        var wrapper = ctx || this._renderContext;
        var context = wrapper.getContext();
        var colorStr = "rgba(" + (0 | color.r) + "," + (0 | color.g) + "," + (0 | color.b);
        wrapper.setFillStyle(colorStr + ",1)");
        var subRadius = radius / 10;
        context.beginPath();
        context.moveTo(-radius, radius);
        context.lineTo(0, subRadius);
        context.lineTo(radius, radius);
        context.lineTo(subRadius, 0);
        context.lineTo(radius, -radius);
        context.lineTo(0, -subRadius);
        context.lineTo(-radius, -radius);
        context.lineTo(-subRadius, 0);
        context.lineTo(-radius, radius);
        context.closePath();
        context.fill();
        var rg = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
        rg.addColorStop(0, colorStr + ", 1)");
        rg.addColorStop(0.3, colorStr + ", 0.8)");
        rg.addColorStop(1.0, colorStr + ", 0.0)");
        wrapper.setFillStyle(rg);
        context.beginPath();
        var startAngle_1 = 0;
        var endAngle_1 = cc.PI2;
        context.arc(0, 0, radius - subRadius, startAngle_1, endAngle_1, false);
        context.closePath();
        context.fill();
    },
    drawColorBall:function (ctx, radius, color) {
        var wrapper = ctx || this._renderContext;
        var context = wrapper.getContext();
        radius *= cc.view.getScaleX();
        var colorStr = "rgba(" +(0|color.r) + "," + (0|color.g) + "," + (0|color.b);
        var subRadius = radius / 10;
        var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
        g1.addColorStop(0, colorStr + ", 1)");
        g1.addColorStop(0.3, colorStr + ", 0.8)");
        g1.addColorStop(0.6, colorStr + ", 0.4)");
        g1.addColorStop(1.0, colorStr + ", 0.0)");
        wrapper.setFillStyle(g1);
        context.beginPath();
        var startAngle_1 = 0;
        var endAngle_1 = cc.PI2;
        context.arc(0, 0, radius, startAngle_1, endAngle_1, false);
        context.closePath();
        context.fill();
    },
    fillText:function (strText, x, y) {
        this._renderContext.getContext().fillText(strText, x, -y);
    },
    setDrawColor:function (r, g, b, a) {
        this._renderContext.setFillStyle("rgba(" + r + "," + g + "," + b + "," + a / 255 + ")");
        this._renderContext.setStrokeStyle("rgba(" + r + "," + g + "," + b + "," + a / 255 + ")");
    },
    setPointSize:function (pointSize) {
    },
    setLineWidth:function (width) {
        this._renderContext.getContext().lineWidth = width * cc.view.getScaleX();
    }
});
(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;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR);
        this._uniformColor = cc._renderContext.getUniformLocation(this._shaderProgram.getProgram(), "u_color");
    };
    var proto = cc.AtlasNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.AtlasNode.WebGLRenderCmd;
    proto._updateBlendFunc = function () {
        var node = this._node;
        if (!this._textureAtlas.texture.hasPremultipliedAlpha()) {
            node._blendFunc.src = cc.SRC_ALPHA;
            node._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
        }
    };
    proto._updateOpacityModifyRGB = function () {
        this._node._opacityModifyRGB = this._textureAtlas.texture.hasPremultipliedAlpha();
    };
    proto.rendering = function (ctx) {
        var context = ctx || cc._renderContext, node = this._node;
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
        if (this._uniformColor && this._colorF32Array) {
            context.uniform4fv(this._uniformColor, this._colorF32Array);
            this._textureAtlas.drawNumberOfQuads(node.quadsToDraw, 0);
        }
    };
    proto.initWithTexture = function(texture, tileWidth, tileHeight, itemsToRender){
        var node = this._node;
        node._itemWidth = tileWidth;
        node._itemHeight = tileHeight;
        this._colorUnmodified = cc.color.WHITE;
        node._opacityModifyRGB = true;
        node._blendFunc.src = cc.BLEND_SRC;
        node._blendFunc.dst = cc.BLEND_DST;
        var locRealColor = node._realColor;
        this._colorF32Array = new Float32Array([locRealColor.r / 255.0, locRealColor.g / 255.0, locRealColor.b / 255.0, node._realOpacity / 255.0]);
        this._textureAtlas = new cc.TextureAtlas();
        this._textureAtlas.initWithTexture(texture, itemsToRender);
        if (!this._textureAtlas) {
            cc.log(cc._LogInfos.AtlasNode__initWithTexture);
            return false;
        }
        this._updateBlendFunc();
        this._updateOpacityModifyRGB();
        this._calculateMaxItems();
        node.quadsToDraw = itemsToRender;
        return true;
    };
    proto.setColor = function(color3){
        var temp = cc.color(color3.r, color3.g, color3.b), node = this._node;
        this._colorUnmodified = color3;
        var locDisplayedOpacity = this._displayedOpacity;
        if (node._opacityModifyRGB) {
            temp.r = temp.r * locDisplayedOpacity / 255;
            temp.g = temp.g * locDisplayedOpacity / 255;
            temp.b = temp.b * locDisplayedOpacity / 255;
        }
        cc.Node.prototype.setColor.call(node, temp);
    };
    proto.setOpacity = function(opacity){
        var node = this._node;
        cc.Node.prototype.setOpacity.call(node, opacity);
        if (node._opacityModifyRGB) {
            node.color = this._colorUnmodified;
        }
    };
    proto._updateColor = function () {
        if (this._colorF32Array) {
            var locDisplayedColor = this._displayedColor;
            this._colorF32Array[0] = locDisplayedColor.r / 255.0;
            this._colorF32Array[1] = locDisplayedColor.g / 255.0;
            this._colorF32Array[2] = locDisplayedColor.b / 255.0;
            this._colorF32Array[3] = this._displayedOpacity / 255.0;
        }
    };
    proto.getTexture = function(){
        return this._textureAtlas.texture;
    };
    proto.setTexture = function(texture){
        this._textureAtlas.texture = texture;
        this._updateBlendFunc();
        this._updateOpacityModifyRGB();
    };
    proto._calculateMaxItems = function(){
        var node = this._node;
        var selTexture = this._textureAtlas.texture;
        var size = selTexture.getContentSize();
        if (node._ignoreContentScaleFactor)
            size = selTexture.getContentSizeInPixels();
        node._itemsPerColumn = 0 | (size.height / node._itemHeight);
        node._itemsPerRow = 0 | (size.width / node._itemWidth);
    };
})();
cc._LogInfos = {
    ActionManager_addAction: "cc.ActionManager.addAction(): action must be non-null",
    ActionManager_removeAction: "cocos2d: removeAction: Target not found",
    ActionManager_removeActionByTag: "cc.ActionManager.removeActionByTag(): an invalid tag",
    ActionManager_removeActionByTag_2: "cc.ActionManager.removeActionByTag(): target must be non-null",
    ActionManager_getActionByTag: "cc.ActionManager.getActionByTag(): an invalid tag",
    ActionManager_getActionByTag_2: "cocos2d : getActionByTag(tag = %s): Action not found",
    configuration_dumpInfo: "cocos2d: **** WARNING **** CC_ENABLE_PROFILERS is defined. Disable it when you finish profiling (from ccConfig.js)",
    configuration_loadConfigFile: "Expected 'data' dict, but not found. Config file: %s",
    configuration_loadConfigFile_2: "Please load the resource first : %s",
    Director_resume: "cocos2d: Director: Error in gettimeofday",
    Director_setProjection: "cocos2d: Director: unrecognized projection",
    Director_popToSceneStackLevel: "cocos2d: Director: unrecognized projection",
    Director_popToSceneStackLevel_2: "cocos2d: Director: Error in gettimeofday",
    Director_popScene: "running scene should not null",
    Director_pushScene: "the scene should not null",
    arrayVerifyType: "element type is wrong!",
    Scheduler_scheduleCallbackForTarget: "CCSheduler#scheduleCallback. Callback already scheduled. Updating interval from:%s to %s",
    Scheduler_scheduleCallbackForTarget_2: "cc.scheduler.scheduleCallbackForTarget(): callback_fn should be non-null.",
    Scheduler_scheduleCallbackForTarget_3: "cc.scheduler.scheduleCallbackForTarget(): target should be non-null.",
    Scheduler_pauseTarget: "cc.Scheduler.pauseTarget():target should be non-null",
    Scheduler_resumeTarget: "cc.Scheduler.resumeTarget():target should be non-null",
    Scheduler_isTargetPaused: "cc.Scheduler.isTargetPaused():target should be non-null",
    Node_getZOrder: "getZOrder is deprecated. Please use getLocalZOrder instead.",
    Node_setZOrder: "setZOrder is deprecated. Please use setLocalZOrder instead.",
    Node_getRotation: "RotationX != RotationY. Don't know which one to return",
    Node_getScale: "ScaleX != ScaleY. Don't know which one to return",
    Node_addChild: "An Node can't be added as a child of itself.",
    Node_addChild_2: "child already added. It can't be added again",
    Node_addChild_3: "child must be non-null",
    Node_removeFromParentAndCleanup: "removeFromParentAndCleanup is deprecated. Use removeFromParent instead",
    Node_boundingBox: "boundingBox is deprecated. Use getBoundingBox instead",
    Node_removeChildByTag: "argument tag is an invalid tag",
    Node_removeChildByTag_2: "cocos2d: removeChildByTag(tag = %s): child not found!",
    Node_removeAllChildrenWithCleanup: "removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead",
    Node_stopActionByTag: "cc.Node.stopActionBy(): argument tag an invalid tag",
    Node_getActionByTag: "cc.Node.getActionByTag(): argument tag is an invalid tag",
    Node_resumeSchedulerAndActions: "resumeSchedulerAndActions is deprecated, please use resume instead.",
    Node_pauseSchedulerAndActions: "pauseSchedulerAndActions is deprecated, please use pause instead.",
    Node__arrayMakeObjectsPerformSelector: "Unknown callback function",
    Node_reorderChild: "child must be non-null",
    Node_runAction: "cc.Node.runAction(): action must be non-null",
    Node_schedule: "callback function must be non-null",
    Node_schedule_2: "interval must be positive",
    Node_initWithTexture: "cocos2d: Could not initialize cc.AtlasNode. Invalid Texture.",
    AtlasNode_updateAtlasValues: "cc.AtlasNode.updateAtlasValues(): Shall be overridden in subclasses",
    AtlasNode_initWithTileFile: "",
    AtlasNode__initWithTexture: "cocos2d: Could not initialize cc.AtlasNode. Invalid Texture.",
    _EventListenerKeyboard_checkAvailable: "cc._EventListenerKeyboard.checkAvailable(): Invalid EventListenerKeyboard!",
    _EventListenerTouchOneByOne_checkAvailable: "cc._EventListenerTouchOneByOne.checkAvailable(): Invalid EventListenerTouchOneByOne!",
    _EventListenerTouchAllAtOnce_checkAvailable: "cc._EventListenerTouchAllAtOnce.checkAvailable(): Invalid EventListenerTouchAllAtOnce!",
    _EventListenerAcceleration_checkAvailable: "cc._EventListenerAcceleration.checkAvailable(): _onAccelerationEvent must be non-nil",
    EventListener_create: "Invalid parameter.",
    __getListenerID: "Don't call this method if the event is for touch.",
    eventManager__forceAddEventListener: "Invalid scene graph priority!",
    eventManager_addListener: "0 priority is forbidden for fixed priority since it's used for scene graph based priority.",
    eventManager_removeListeners: "Invalid listener type!",
    eventManager_setPriority: "Can't set fixed priority with scene graph based listener.",
    eventManager_addListener_2: "Invalid parameters.",
    eventManager_addListener_3: "listener must be a cc.EventListener object when adding a fixed priority listener",
    eventManager_addListener_4: "The listener has been registered, please don't register it again.",
    LayerMultiplex_initWithLayers: "parameters should not be ending with null in Javascript",
    LayerMultiplex_switchTo: "Invalid index in MultiplexLayer switchTo message",
    LayerMultiplex_switchToAndReleaseMe: "Invalid index in MultiplexLayer switchTo message",
    LayerMultiplex_addLayer: "cc.Layer.addLayer(): layer should be non-null",
    EGLView_setDesignResolutionSize: "Resolution not valid",
    EGLView_setDesignResolutionSize_2: "should set resolutionPolicy",
    inputManager_handleTouchesBegin: "The touches is more than MAX_TOUCHES, nUnusedIndex = %s",
    swap: "cc.swap is being modified from original macro, please check usage",
    checkGLErrorDebug: "WebGL error %s",
    animationCache__addAnimationsWithDictionary: "cocos2d: cc.AnimationCache: No animations were found in provided dictionary.",
    animationCache__addAnimationsWithDictionary_2: "cc.AnimationCache. Invalid animation format",
    animationCache_addAnimations: "cc.AnimationCache.addAnimations(): File could not be found",
    animationCache__parseVersion1: "cocos2d: cc.AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache.",
    animationCache__parseVersion1_2: "cocos2d: cc.AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation.",
    animationCache__parseVersion1_3: "cocos2d: cc.AnimationCache: None of the frames for animation '%s' were found in the cc.SpriteFrameCache. Animation is not being added to the Animation Cache.",
    animationCache__parseVersion1_4: "cocos2d: cc.AnimationCache: An animation in your dictionary refers to a frame which is not in the cc.SpriteFrameCache. Some or all of the frames for the animation '%s' may be missing.",
    animationCache__parseVersion2: "cocos2d: CCAnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache.",
    animationCache__parseVersion2_2: "cocos2d: cc.AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation.",
    animationCache_addAnimations_2: "cc.AnimationCache.addAnimations(): Invalid texture file name",
    Sprite_reorderChild: "cc.Sprite.reorderChild(): this child is not in children list",
    Sprite_ignoreAnchorPointForPosition: "cc.Sprite.ignoreAnchorPointForPosition(): it is invalid in cc.Sprite when using SpriteBatchNode",
    Sprite_setDisplayFrameWithAnimationName: "cc.Sprite.setDisplayFrameWithAnimationName(): Frame not found",
    Sprite_setDisplayFrameWithAnimationName_2: "cc.Sprite.setDisplayFrameWithAnimationName(): Invalid frame index",
    Sprite_setDisplayFrame: "setDisplayFrame is deprecated, please use setSpriteFrame instead.",
    Sprite__updateBlendFunc: "cc.Sprite._updateBlendFunc(): _updateBlendFunc doesn't work when the sprite is rendered using a cc.CCSpriteBatchNode",
    Sprite_initWithSpriteFrame: "cc.Sprite.initWithSpriteFrame(): spriteFrame should be non-null",
    Sprite_initWithSpriteFrameName: "cc.Sprite.initWithSpriteFrameName(): spriteFrameName should be non-null",
    Sprite_initWithSpriteFrameName1: " is null, please check.",
    Sprite_initWithFile: "cc.Sprite.initWithFile(): filename should be non-null",
    Sprite_setDisplayFrameWithAnimationName_3: "cc.Sprite.setDisplayFrameWithAnimationName(): animationName must be non-null",
    Sprite_reorderChild_2: "cc.Sprite.reorderChild(): child should be non-null",
    Sprite_addChild: "cc.Sprite.addChild(): cc.Sprite only supports cc.Sprites as children when using cc.SpriteBatchNode",
    Sprite_addChild_2: "cc.Sprite.addChild(): cc.Sprite only supports a sprite using same texture as children when using cc.SpriteBatchNode",
    Sprite_addChild_3: "cc.Sprite.addChild(): child should be non-null",
    Sprite_setTexture: "cc.Sprite.texture setter: Batched sprites should use the same texture as the batchnode",
    Sprite_updateQuadFromSprite: "cc.SpriteBatchNode.updateQuadFromSprite(): cc.SpriteBatchNode only supports cc.Sprites as children",
    Sprite_insertQuadFromSprite: "cc.SpriteBatchNode.insertQuadFromSprite(): cc.SpriteBatchNode only supports cc.Sprites as children",
    Sprite_addChild_4: "cc.SpriteBatchNode.addChild(): cc.SpriteBatchNode only supports cc.Sprites as children",
    Sprite_addChild_5: "cc.SpriteBatchNode.addChild(): cc.Sprite is not using the same texture",
    Sprite_initWithTexture: "Sprite.initWithTexture(): Argument must be non-nil ",
    Sprite_setSpriteFrame: "Invalid spriteFrameName",
    Sprite_setTexture_2: "Invalid argument: cc.Sprite.texture setter expects a CCTexture2D.",
    Sprite_updateQuadFromSprite_2: "cc.SpriteBatchNode.updateQuadFromSprite(): sprite should be non-null",
    Sprite_insertQuadFromSprite_2: "cc.SpriteBatchNode.insertQuadFromSprite(): sprite should be non-null",
    SpriteBatchNode_addSpriteWithoutQuad: "cc.SpriteBatchNode.addQuadFromSprite(): SpriteBatchNode only supports cc.Sprites as children",
    SpriteBatchNode_increaseAtlasCapacity: "cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from %s to %s.",
    SpriteBatchNode_increaseAtlasCapacity_2: "cocos2d: WARNING: Not enough memory to resize the atlas",
    SpriteBatchNode_reorderChild: "cc.SpriteBatchNode.addChild(): Child doesn't belong to Sprite",
    SpriteBatchNode_removeChild: "cc.SpriteBatchNode.addChild(): sprite batch node should contain the child",
    SpriteBatchNode_addSpriteWithoutQuad_2: "cc.SpriteBatchNode.addQuadFromSprite(): child should be non-null",
    SpriteBatchNode_reorderChild_2: "cc.SpriteBatchNode.addChild(): child should be non-null",
    spriteFrameCache__getFrameConfig: "cocos2d: WARNING: originalWidth/Height not found on the cc.SpriteFrame. AnchorPoint won't work as expected. Regenrate the .plist",
    spriteFrameCache_addSpriteFrames: "cocos2d: WARNING: an alias with name %s already exists",
    spriteFrameCache__checkConflict: "cocos2d: WARNING: Sprite frame: %s has already been added by another source, please fix name conflit",
    spriteFrameCache_getSpriteFrame: "cocos2d: cc.SpriteFrameCahce: Frame %s not found",
    spriteFrameCache__getFrameConfig_2: "Please load the resource first : %s",
    spriteFrameCache_addSpriteFrames_2: "cc.SpriteFrameCache.addSpriteFrames(): plist should be non-null",
    spriteFrameCache_addSpriteFrames_3: "Argument must be non-nil",
    CCSpriteBatchNode_updateQuadFromSprite: "cc.SpriteBatchNode.updateQuadFromSprite(): cc.SpriteBatchNode only supports cc.Sprites as children",
    CCSpriteBatchNode_insertQuadFromSprite: "cc.SpriteBatchNode.insertQuadFromSprite(): cc.SpriteBatchNode only supports cc.Sprites as children",
    CCSpriteBatchNode_addChild: "cc.SpriteBatchNode.addChild(): cc.SpriteBatchNode only supports cc.Sprites as children",
    CCSpriteBatchNode_initWithTexture: "Sprite.initWithTexture(): Argument must be non-nil ",
    CCSpriteBatchNode_addChild_2: "cc.Sprite.addChild(): child should be non-null",
    CCSpriteBatchNode_setSpriteFrame: "Invalid spriteFrameName",
    CCSpriteBatchNode_setTexture: "Invalid argument: cc.Sprite texture setter expects a CCTexture2D.",
    CCSpriteBatchNode_updateQuadFromSprite_2: "cc.SpriteBatchNode.updateQuadFromSprite(): sprite should be non-null",
    CCSpriteBatchNode_insertQuadFromSprite_2: "cc.SpriteBatchNode.insertQuadFromSprite(): sprite should be non-null",
    CCSpriteBatchNode_addChild_3: "cc.SpriteBatchNode.addChild(): child should be non-null",
    TextureAtlas_initWithFile: "cocos2d: Could not open file: %s",
    TextureAtlas_insertQuad: "cc.TextureAtlas.insertQuad(): invalid totalQuads",
    TextureAtlas_initWithTexture: "cc.TextureAtlas.initWithTexture():texture should be non-null",
    TextureAtlas_updateQuad: "cc.TextureAtlas.updateQuad(): quad should be non-null",
    TextureAtlas_updateQuad_2: "cc.TextureAtlas.updateQuad(): Invalid index",
    TextureAtlas_insertQuad_2: "cc.TextureAtlas.insertQuad(): Invalid index",
    TextureAtlas_insertQuads: "cc.TextureAtlas.insertQuad(): Invalid index + amount",
    TextureAtlas_insertQuadFromIndex: "cc.TextureAtlas.insertQuadFromIndex(): Invalid newIndex",
    TextureAtlas_insertQuadFromIndex_2: "cc.TextureAtlas.insertQuadFromIndex(): Invalid fromIndex",
    TextureAtlas_removeQuadAtIndex: "cc.TextureAtlas.removeQuadAtIndex(): Invalid index",
    TextureAtlas_removeQuadsAtIndex: "cc.TextureAtlas.removeQuadsAtIndex(): index + amount out of bounds",
    TextureAtlas_moveQuadsFromIndex: "cc.TextureAtlas.moveQuadsFromIndex(): move is out of bounds",
    TextureAtlas_moveQuadsFromIndex_2: "cc.TextureAtlas.moveQuadsFromIndex(): Invalid newIndex",
    TextureAtlas_moveQuadsFromIndex_3: "cc.TextureAtlas.moveQuadsFromIndex(): Invalid oldIndex",
    textureCache_addPVRTCImage: "TextureCache:addPVRTCImage does not support on HTML5",
    textureCache_addETCImage: "TextureCache:addPVRTCImage does not support on HTML5",
    textureCache_textureForKey: "textureForKey is deprecated. Please use getTextureForKey instead.",
    textureCache_addPVRImage: "addPVRImage does not support on HTML5",
    textureCache_addUIImage: "cocos2d: Couldn't add UIImage in TextureCache",
    textureCache_dumpCachedTextureInfo: "cocos2d: '%s' id=%s %s x %s",
    textureCache_dumpCachedTextureInfo_2: "cocos2d: '%s' id= HTMLCanvasElement %s x %s",
    textureCache_dumpCachedTextureInfo_3: "cocos2d: TextureCache dumpDebugInfo: %s textures, HTMLCanvasElement for %s KB (%s MB)",
    textureCache_addUIImage_2: "cc.Texture.addUIImage(): image should be non-null",
    Texture2D_initWithETCFile: "initWithETCFile does not support on HTML5",
    Texture2D_initWithPVRFile: "initWithPVRFile does not support on HTML5",
    Texture2D_initWithPVRTCData: "initWithPVRTCData does not support on HTML5",
    Texture2D_addImage: "cc.Texture.addImage(): path should be non-null",
    Texture2D_initWithImage: "cocos2d: cc.Texture2D. Can't create Texture. UIImage is nil",
    Texture2D_initWithImage_2: "cocos2d: WARNING: Image (%s x %s) is bigger than the supported %s x %s",
    Texture2D_initWithString: "initWithString isn't supported on cocos2d-html5",
    Texture2D_initWithETCFile_2: "initWithETCFile does not support on HTML5",
    Texture2D_initWithPVRFile_2: "initWithPVRFile does not support on HTML5",
    Texture2D_initWithPVRTCData_2: "initWithPVRTCData does not support on HTML5",
    Texture2D_bitsPerPixelForFormat: "bitsPerPixelForFormat: %s, cannot give useful result, it's a illegal pixel format",
    Texture2D__initPremultipliedATextureWithImage: "cocos2d: cc.Texture2D: Using RGB565 texture since image has no alpha",
    Texture2D_addImage_2: "cc.Texture.addImage(): path should be non-null",
    Texture2D_initWithData: "NSInternalInconsistencyException",
    MissingFile: "Missing file: %s",
    radiansToDegress: "cc.radiansToDegress() should be called cc.radiansToDegrees()",
    RectWidth: "Rect width exceeds maximum margin: %s",
    RectHeight: "Rect height exceeds maximum margin: %s",
    EventManager__updateListeners: "If program goes here, there should be event in dispatch.",
    EventManager__updateListeners_2: "_inDispatch should be 1 here."
};
cc._logToWebPage = function (msg) {
    if (!cc._canvas)
        return;
    var logList = cc._logList;
    var doc = document;
    if (!logList) {
        var logDiv = doc.createElement("Div");
        var logDivStyle = logDiv.style;
        logDiv.setAttribute("id", "logInfoDiv");
        cc._canvas.parentNode.appendChild(logDiv);
        logDiv.setAttribute("width", "200");
        logDiv.setAttribute("height", cc._canvas.height);
        logDivStyle.zIndex = "99999";
        logDivStyle.position = "absolute";
        logDivStyle.top = "0";
        logDivStyle.left = "0";
        logList = cc._logList = doc.createElement("textarea");
        var logListStyle = logList.style;
        logList.setAttribute("rows", "20");
        logList.setAttribute("cols", "30");
        logList.setAttribute("disabled", true);
        logDiv.appendChild(logList);
        logListStyle.backgroundColor = "transparent";
        logListStyle.borderBottom = "1px solid #cccccc";
        logListStyle.borderRightWidth = "0px";
        logListStyle.borderLeftWidth = "0px";
        logListStyle.borderTopWidth = "0px";
        logListStyle.borderTopStyle = "none";
        logListStyle.borderRightStyle = "none";
        logListStyle.borderLeftStyle = "none";
        logListStyle.padding = "0px";
        logListStyle.margin = 0;
    }
    logList.value = logList.value + msg + "\r\n";
    logList.scrollTop = logList.scrollHeight;
};
cc._formatString = function (arg) {
    if (cc.isObject(arg)) {
        try {
            return JSON.stringify(arg);
        } catch (err) {
            return "";
        }
    } else
        return arg;
};
cc._initDebugSetting = function (mode) {
    var ccGame = cc.game;
    if(mode === ccGame.DEBUG_MODE_NONE)
        return;
    var locLog;
    if(mode > ccGame.DEBUG_MODE_ERROR){
        locLog = cc._logToWebPage.bind(cc);
        cc.error = function(){
            locLog("ERROR :  " + cc.formatStr.apply(cc, arguments));
        };
        cc.assert = function(cond, msg) {
            if (!cond && msg) {
                for (var i = 2; i < arguments.length; i++)
                    msg = msg.replace(/(%s)|(%d)/, cc._formatString(arguments[i]));
                locLog("Assert: " + msg);
            }
        };
        if(mode !== ccGame.DEBUG_MODE_ERROR_FOR_WEB_PAGE){
            cc.warn = function(){
                locLog("WARN :  " + cc.formatStr.apply(cc, arguments));
            };
        }
        if(mode === ccGame.DEBUG_MODE_INFO_FOR_WEB_PAGE){
            cc.log = function(){
                locLog(cc.formatStr.apply(cc, arguments));
            };
        }
    } else if(console && console.log.apply){//console is null when user doesn't open dev tool on IE9
        cc.error = Function.prototype.bind.call(console.error, console);
        if (console.assert) {
            cc.assert = Function.prototype.bind.call(console.assert, console);
        } else {
            cc.assert = function (cond, msg) {
                if (!cond && msg) {
                    for (var i = 2; i < arguments.length; i++)
                        msg = msg.replace(/(%s)|(%d)/, cc._formatString(arguments[i]));
                    throw new Error(msg);
                }
            };
        }
        if (mode !== ccGame.DEBUG_MODE_ERROR)
            cc.warn = Function.prototype.bind.call(console.warn, console);
        if (mode === ccGame.DEBUG_MODE_INFO)
            cc.log = Function.prototype.bind.call(console.log, console);
    }
};
cc.HashElement = cc.Class.extend({
    actions:null,
    target:null,
    actionIndex:0,
    currentAction:null,
    currentActionSalvaged:false,
    paused:false,
    hh:null,
    ctor:function () {
        this.actions = [];
        this.target = null;
        this.actionIndex = 0;
        this.currentAction = null;
        this.currentActionSalvaged = false;
        this.paused = false;
        this.hh = null;
    }
});
cc.ActionManager = cc.Class.extend({
    _hashTargets:null,
    _arrayTargets:null,
    _currentTarget:null,
    _currentTargetSalvaged:false,
    _searchElementByTarget:function (arr, target) {
        for (var k = 0; k < arr.length; k++) {
            if (target === arr[k].target)
                return arr[k];
        }
        return null;
    },
    ctor:function () {
        this._hashTargets = {};
        this._arrayTargets = [];
        this._currentTarget = null;
        this._currentTargetSalvaged = false;
    },
    addAction:function (action, target, paused) {
        if(!action)
            throw new Error("cc.ActionManager.addAction(): action must be non-null");
        if(!target)
            throw new Error("cc.ActionManager.addAction(): action must be non-null");
        var element = this._hashTargets[target.__instanceId];
        if (!element) {
            element = new cc.HashElement();
            element.paused = paused;
            element.target = target;
            this._hashTargets[target.__instanceId] = element;
            this._arrayTargets.push(element);
        }
        this._actionAllocWithHashElement(element);
        element.actions.push(action);
        action.startWithTarget(target);
    },
    removeAllActions:function () {
        var locTargets = this._arrayTargets;
        for (var i = 0; i < locTargets.length; i++) {
            var element = locTargets[i];
            if (element)
                this.removeAllActionsFromTarget(element.target, true);
        }
    },
    removeAllActionsFromTarget:function (target, forceDelete) {
        if (target == null)
            return;
        var element = this._hashTargets[target.__instanceId];
        if (element) {
            if (element.actions.indexOf(element.currentAction) !== -1 && !(element.currentActionSalvaged))
                element.currentActionSalvaged = true;
            element.actions.length = 0;
            if (this._currentTarget === element && !forceDelete) {
                this._currentTargetSalvaged = true;
            } else {
                this._deleteHashElement(element);
            }
        }
    },
    removeAction:function (action) {
        if (action == null)
            return;
        var target = action.getOriginalTarget();
        var element = this._hashTargets[target.__instanceId];
        if (element) {
            for (var i = 0; i < element.actions.length; i++) {
                if (element.actions[i] === action) {
                    element.actions.splice(i, 1);
                    break;
                }
            }
        } else {
            cc.log(cc._LogInfos.ActionManager_removeAction);
        }
    },
    removeActionByTag:function (tag, target) {
        if(tag === cc.ACTION_TAG_INVALID)
            cc.log(cc._LogInfos.ActionManager_addAction);
        cc.assert(target, cc._LogInfos.ActionManager_addAction);
        var element = this._hashTargets[target.__instanceId];
        if (element) {
            var limit = element.actions.length;
            for (var i = 0; i < limit; ++i) {
                var action = element.actions[i];
                if (action && action.getTag() === tag && action.getOriginalTarget() === target) {
                    this._removeActionAtIndex(i, element);
                    break;
                }
            }
        }
    },
    getActionByTag:function (tag, target) {
        if(tag === cc.ACTION_TAG_INVALID)
            cc.log(cc._LogInfos.ActionManager_getActionByTag);
        var element = this._hashTargets[target.__instanceId];
        if (element) {
            if (element.actions != null) {
                for (var i = 0; i < element.actions.length; ++i) {
                    var action = element.actions[i];
                    if (action && action.getTag() === tag)
                        return action;
                }
            }
            cc.log(cc._LogInfos.ActionManager_getActionByTag_2, tag);
        }
        return null;
    },
    numberOfRunningActionsInTarget:function (target) {
        var element = this._hashTargets[target.__instanceId];
        if (element)
            return (element.actions) ? element.actions.length : 0;
        return 0;
    },
    pauseTarget:function (target) {
        var element = this._hashTargets[target.__instanceId];
        if (element)
            element.paused = true;
    },
    resumeTarget:function (target) {
        var element = this._hashTargets[target.__instanceId];
        if (element)
            element.paused = false;
    },
    pauseAllRunningActions:function(){
        var idsWithActions = [];
        var locTargets = this._arrayTargets;
        for(var i = 0; i< locTargets.length; i++){
            var element = locTargets[i];
            if(element && !element.paused){
                element.paused = true;
                idsWithActions.push(element.target);
            }
        }
        return idsWithActions;
    },
    resumeTargets:function(targetsToResume){
        if(!targetsToResume)
            return;
        for(var i = 0 ; i< targetsToResume.length; i++){
            if(targetsToResume[i])
                this.resumeTarget(targetsToResume[i]);
        }
    },
    purgeSharedManager:function () {
        cc.director.getScheduler().unscheduleUpdate(this);
    },
    _removeActionAtIndex:function (index, element) {
        var action = element.actions[index];
        if ((action === element.currentAction) && (!element.currentActionSalvaged))
            element.currentActionSalvaged = true;
        element.actions.splice(index, 1);
        if (element.actionIndex >= index)
            element.actionIndex--;
        if (element.actions.length === 0) {
            if (this._currentTarget === element) {
                this._currentTargetSalvaged = true;
            } else {
                this._deleteHashElement(element);
            }
        }
    },
    _deleteHashElement:function (element) {
        var ret = false;
        if (element) {
            if(this._hashTargets[element.target.__instanceId]){
                delete this._hashTargets[element.target.__instanceId];
                cc.arrayRemoveObject(this._arrayTargets, element);
                ret = true;
            }
            element.actions = null;
            element.target = null;
        }
        return ret;
    },
    _actionAllocWithHashElement:function (element) {
        if (element.actions == null) {
            element.actions = [];
        }
    },
    update:function (dt) {
        var locTargets = this._arrayTargets , locCurrTarget;
        for (var elt = 0; elt < locTargets.length; elt++) {
            this._currentTarget = locTargets[elt];
            locCurrTarget = this._currentTarget;
            if (!locCurrTarget.paused) {
                for (locCurrTarget.actionIndex = 0;
                     locCurrTarget.actionIndex < (locCurrTarget.actions ? locCurrTarget.actions.length : 0);
                     locCurrTarget.actionIndex++) {
                    locCurrTarget.currentAction = locCurrTarget.actions[locCurrTarget.actionIndex];
                    if (!locCurrTarget.currentAction)
                        continue;
                    locCurrTarget.currentActionSalvaged = false;
                    locCurrTarget.currentAction.step(dt * ( locCurrTarget.currentAction._speedMethod ? locCurrTarget.currentAction._speed : 1 ) );
                    if (locCurrTarget.currentActionSalvaged) {
                        locCurrTarget.currentAction = null;//release
                    } else if (locCurrTarget.currentAction.isDone()) {
                        locCurrTarget.currentAction.stop();
                        var action = locCurrTarget.currentAction;
                        locCurrTarget.currentAction = null;
                        this.removeAction(action);
                    }
                    locCurrTarget.currentAction = null;
                }
            }
            if (this._currentTargetSalvaged && locCurrTarget.actions.length === 0) {
                this._deleteHashElement(locCurrTarget) && elt--;
            }
        }
    }
});
cc.ACTION_TAG_INVALID = -1;
cc.Action = cc.Class.extend({
    originalTarget:null,
    target:null,
    tag:cc.ACTION_TAG_INVALID,
    ctor:function () {
        this.originalTarget = null;
        this.target = null;
        this.tag = cc.ACTION_TAG_INVALID;
    },
    copy:function () {
        cc.log("copy is deprecated. Please use clone instead.");
        return this.clone();
    },
    clone:function () {
        var action = new cc.Action();
        action.originalTarget = null;
        action.target = null;
        action.tag = this.tag;
        return action;
    },
    isDone:function () {
        return true;
    },
    startWithTarget:function (target) {
        this.originalTarget = target;
        this.target = target;
    },
    stop:function () {
        this.target = null;
    },
    step:function (dt) {
        cc.log("[Action step]. override me");
    },
    update:function (dt) {
        cc.log("[Action update]. override me");
    },
    getTarget:function () {
        return this.target;
    },
    setTarget:function (target) {
        this.target = target;
    },
    getOriginalTarget:function () {
        return this.originalTarget;
    },
    setOriginalTarget:function (originalTarget) {
        this.originalTarget = originalTarget;
    },
    getTag:function () {
        return this.tag;
    },
    setTag:function (tag) {
        this.tag = tag;
    },
    retain:function () {
    },
    release:function () {
    }
});
cc.action = function () {
    return new cc.Action();
};
cc.Action.create = cc.action;
cc.FiniteTimeAction = cc.Action.extend({
    _duration:0,
    ctor:function () {
        cc.Action.prototype.ctor.call(this);
        this._duration = 0;
    },
    getDuration:function () {
        return this._duration * (this._timesForRepeat || 1);
    },
    setDuration:function (duration) {
        this._duration = duration;
    },
    reverse:function () {
        cc.log("cocos2d: FiniteTimeAction#reverse: Implement me");
        return null;
    },
    clone:function () {
        return new cc.FiniteTimeAction();
    }
});
cc.Speed = cc.Action.extend({
    _speed:0.0,
    _innerAction:null,
    ctor:function (action, speed) {
        cc.Action.prototype.ctor.call(this);
        this._speed = 0;
        this._innerAction = null;
        action && this.initWithAction(action, speed);
    },
    getSpeed:function () {
        return this._speed;
    },
    setSpeed:function (speed) {
        this._speed = speed;
    },
    initWithAction:function (action, speed) {
        if(!action)
            throw new Error("cc.Speed.initWithAction(): action must be non nil");
        this._innerAction = action;
        this._speed = speed;
        return true;
    },
    clone:function () {
        var action = new cc.Speed();
        action.initWithAction(this._innerAction.clone(), this._speed);
        return action;
    },
    startWithTarget:function (target) {
        cc.Action.prototype.startWithTarget.call(this, target);
        this._innerAction.startWithTarget(target);
    },
    stop:function () {
        this._innerAction.stop();
        cc.Action.prototype.stop.call(this);
    },
    step:function (dt) {
        this._innerAction.step(dt * this._speed);
    },
    isDone:function () {
        return this._innerAction.isDone();
    },
    reverse:function () {
        return new cc.Speed(this._innerAction.reverse(), this._speed);
    },
    setInnerAction:function (action) {
        if (this._innerAction !== action) {
            this._innerAction = action;
        }
    },
    getInnerAction:function () {
        return this._innerAction;
    }
});
cc.speed = function (action, speed) {
    return new cc.Speed(action, speed);
};
cc.Speed.create = cc.speed;
cc.Follow = cc.Action.extend({
    _followedNode:null,
    _boundarySet:false,
    _boundaryFullyCovered:false,
    _halfScreenSize:null,
    _fullScreenSize:null,
    _worldRect:null,
    leftBoundary:0.0,
    rightBoundary:0.0,
    topBoundary:0.0,
    bottomBoundary:0.0,
    ctor:function (followedNode, rect) {
        cc.Action.prototype.ctor.call(this);
        this._followedNode = null;
        this._boundarySet = false;
        this._boundaryFullyCovered = false;
        this._halfScreenSize = null;
        this._fullScreenSize = null;
        this.leftBoundary = 0.0;
        this.rightBoundary = 0.0;
        this.topBoundary = 0.0;
        this.bottomBoundary = 0.0;
        this._worldRect = cc.rect(0, 0, 0, 0);
        if(followedNode)
            rect ? this.initWithTarget(followedNode, rect)
                 : this.initWithTarget(followedNode);
    },
    clone:function () {
        var action = new cc.Follow();
        var locRect = this._worldRect;
        var rect = new cc.Rect(locRect.x, locRect.y, locRect.width, locRect.height);
        action.initWithTarget(this._followedNode, rect);
        return action;
    },
    isBoundarySet:function () {
        return this._boundarySet;
    },
    setBoudarySet:function (value) {
        this._boundarySet = value;
    },
    initWithTarget:function (followedNode, rect) {
        if(!followedNode)
            throw new Error("cc.Follow.initWithAction(): followedNode must be non nil");
        var _this = this;
        rect = rect || cc.rect(0, 0, 0, 0);
        _this._followedNode = followedNode;
        _this._worldRect = rect;
        _this._boundarySet = !cc._rectEqualToZero(rect);
        _this._boundaryFullyCovered = false;
        var winSize = cc.director.getWinSize();
        _this._fullScreenSize = cc.p(winSize.width, winSize.height);
        _this._halfScreenSize = cc.pMult(_this._fullScreenSize, 0.5);
        if (_this._boundarySet) {
            _this.leftBoundary = -((rect.x + rect.width) - _this._fullScreenSize.x);
            _this.rightBoundary = -rect.x;
            _this.topBoundary = -rect.y;
            _this.bottomBoundary = -((rect.y + rect.height) - _this._fullScreenSize.y);
            if (_this.rightBoundary < _this.leftBoundary) {
                _this.rightBoundary = _this.leftBoundary = (_this.leftBoundary + _this.rightBoundary) / 2;
            }
            if (_this.topBoundary < _this.bottomBoundary) {
                _this.topBoundary = _this.bottomBoundary = (_this.topBoundary + _this.bottomBoundary) / 2;
            }
            if ((_this.topBoundary === _this.bottomBoundary) && (_this.leftBoundary === _this.rightBoundary))
                _this._boundaryFullyCovered = true;
        }
        return true;
    },
    step:function (dt) {
        var tempPosX = this._followedNode.x;
        var tempPosY = this._followedNode.y;
        tempPosX = this._halfScreenSize.x - tempPosX;
        tempPosY = this._halfScreenSize.y - tempPosY;
        this.target._renderCmd._dirtyFlag = 0;
        if (this._boundarySet) {
            if (this._boundaryFullyCovered)
                return;
            this.target.setPosition(cc.clampf(tempPosX, this.leftBoundary, this.rightBoundary), cc.clampf(tempPosY, this.bottomBoundary, this.topBoundary));
        } else {
            this.target.setPosition(tempPosX, tempPosY);
        }
    },
    isDone:function () {
        return ( !this._followedNode.running );
    },
    stop:function () {
        this.target = null;
        cc.Action.prototype.stop.call(this);
    }
});
cc.follow = function (followedNode, rect) {
    return new cc.Follow(followedNode, rect);
};
cc.Follow.create = cc.follow;
cc.ActionInterval = cc.FiniteTimeAction.extend({
    _elapsed:0,
    _firstTick:false,
    _easeList: null,
    _timesForRepeat:1,
    _repeatForever: false,
    _repeatMethod: false,//Compatible with repeat class, Discard after can be deleted
    _speed: 1,
    _speedMethod: false,//Compatible with speed class, Discard after can be deleted
    ctor:function (d) {
        this._speed = 1;
        this._timesForRepeat = 1;
        this._repeatForever = false;
        this.MAX_VALUE = 2;
        this._repeatMethod = false;//Compatible with repeat class, Discard after can be deleted
        this._speedMethod = false;//Compatible with repeat class, Discard after can be deleted
        cc.FiniteTimeAction.prototype.ctor.call(this);
        d !== undefined && this.initWithDuration(d);
    },
    getElapsed:function () {
        return this._elapsed;
    },
    initWithDuration:function (d) {
        this._duration = (d === 0) ? cc.FLT_EPSILON : d;
        this._elapsed = 0;
        this._firstTick = true;
        return true;
    },
    isDone:function () {
        return (this._elapsed >= this._duration);
    },
    _cloneDecoration: function(action){
        action._repeatForever = this._repeatForever;
        action._speed = this._speed;
        action._timesForRepeat = this._timesForRepeat;
        action._easeList = this._easeList;
        action._speedMethod = this._speedMethod;
        action._repeatMethod = this._repeatMethod;
    },
    _reverseEaseList: function(action){
        if(this._easeList){
            action._easeList = [];
            for(var i=0; i<this._easeList.length; i++){
                action._easeList.push(this._easeList[i].reverse());
            }
        }
    },
    clone:function () {
        var action = new cc.ActionInterval(this._duration);
        this._cloneDecoration(action);
        return action;
    },
    easing: function (easeObj) {
        if (this._easeList)
            this._easeList.length = 0;
        else
            this._easeList = [];
        for (var i = 0; i < arguments.length; i++)
            this._easeList.push(arguments[i]);
        return this;
    },
    _computeEaseTime: function (dt) {
        var locList = this._easeList;
        if ((!locList) || (locList.length === 0))
            return dt;
        for (var i = 0, n = locList.length; i < n; i++)
            dt = locList[i].easing(dt);
        return dt;
    },
    step:function (dt) {
        if (this._firstTick) {
            this._firstTick = false;
            this._elapsed = 0;
        } else
            this._elapsed += dt;
        var t = this._elapsed / (this._duration > 0.0000001192092896 ? this._duration : 0.0000001192092896);
        t = (1 > t ? t : 1);
        this.update(t > 0 ? t : 0);
        if(this._repeatMethod && this._timesForRepeat > 1 && this.isDone()){
            if(!this._repeatForever){
                this._timesForRepeat--;
            }
            this.startWithTarget(this.target);
            this.step(this._elapsed - this._duration);
        }
    },
    startWithTarget:function (target) {
        cc.Action.prototype.startWithTarget.call(this, target);
        this._elapsed = 0;
        this._firstTick = true;
    },
    reverse:function () {
        cc.log("cc.IntervalAction: reverse not implemented.");
        return null;
    },
    setAmplitudeRate:function (amp) {
        cc.log("cc.ActionInterval.setAmplitudeRate(): it should be overridden in subclass.");
    },
    getAmplitudeRate:function () {
        cc.log("cc.ActionInterval.getAmplitudeRate(): it should be overridden in subclass.");
        return 0;
    },
    speed: function(speed){
        if(speed <= 0){
            cc.log("The speed parameter error");
            return this;
        }
        this._speedMethod = true;//Compatible with repeat class, Discard after can be deleted
        this._speed *= speed;
        return this;
    },
    getSpeed: function(){
        return this._speed;
    },
    setSpeed: function(speed){
        this._speed = speed;
        return this;
    },
    repeat: function(times){
        times = Math.round(times);
        if(isNaN(times) || times < 1){
            cc.log("The repeat parameter error");
            return this;
        }
        this._repeatMethod = true;//Compatible with repeat class, Discard after can be deleted
        this._timesForRepeat *= times;
        return this;
    },
    repeatForever: function(){
        this._repeatMethod = true;//Compatible with repeat class, Discard after can be deleted
        this._timesForRepeat = this.MAX_VALUE;
        this._repeatForever = true;
        return this;
    }
});
cc.actionInterval = function (d) {
    return new cc.ActionInterval(d);
};
cc.ActionInterval.create = cc.actionInterval;
cc.Sequence = cc.ActionInterval.extend({
    _actions:null,
    _split:null,
    _last:0,
    ctor:function (tempArray) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._actions = [];
        var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
        var last = paramArray.length - 1;
        if ((last >= 0) && (paramArray[last] == null))
            cc.log("parameters should not be ending with null in Javascript");
        if (last >= 0) {
            var prev = paramArray[0], action1;
            for (var i = 1; i < last; i++) {
                if (paramArray[i]) {
                    action1 = prev;
                    prev = cc.Sequence._actionOneTwo(action1, paramArray[i]);
                }
            }
            this.initWithTwoActions(prev, paramArray[last]);
        }
    },
    initWithTwoActions:function (actionOne, actionTwo) {
        if(!actionOne || !actionTwo)
            throw new Error("cc.Sequence.initWithTwoActions(): arguments must all be non nil");
        var d = actionOne._duration + actionTwo._duration;
        this.initWithDuration(d);
        this._actions[0] = actionOne;
        this._actions[1] = actionTwo;
        return true;
    },
    clone:function () {
        var action = new cc.Sequence();
        this._cloneDecoration(action);
        action.initWithTwoActions(this._actions[0].clone(), this._actions[1].clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._split = this._actions[0]._duration / this._duration;
        this._last = -1;
    },
    stop:function () {
        if (this._last !== -1)
            this._actions[this._last].stop();
        cc.Action.prototype.stop.call(this);
    },
    update:function (dt) {
        var new_t, found = 0;
        var locSplit = this._split, locActions = this._actions, locLast = this._last, actionFound;
        dt = this._computeEaseTime(dt);
        if (dt < locSplit) {
            new_t = (locSplit !== 0) ? dt / locSplit : 1;
            if (found === 0 && locLast === 1) {
                locActions[1].update(0);
                locActions[1].stop();
            }
        } else {
            found = 1;
            new_t = (locSplit === 1) ? 1 : (dt - locSplit) / (1 - locSplit);
            if (locLast === -1) {
                locActions[0].startWithTarget(this.target);
                locActions[0].update(1);
                locActions[0].stop();
            }
            if (!locLast) {
                locActions[0].update(1);
                locActions[0].stop();
            }
        }
        actionFound = locActions[found];
        if (locLast === found && actionFound.isDone())
            return;
        if (locLast !== found)
            actionFound.startWithTarget(this.target);
        new_t = new_t * actionFound._timesForRepeat;
        actionFound.update(new_t > 1 ? new_t % 1 : new_t);
        this._last = found;
    },
    reverse:function () {
        var action = cc.Sequence._actionOneTwo(this._actions[1].reverse(), this._actions[0].reverse());
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.sequence = function (tempArray) {
    var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
    if ((paramArray.length > 0) && (paramArray[paramArray.length - 1] == null))
        cc.log("parameters should not be ending with null in Javascript");
    var result, current, i, repeat;
    while(paramArray && paramArray.length > 0){
        current = Array.prototype.shift.call(paramArray);
        repeat = current._timesForRepeat || 1;
        current._repeatMethod = false;
        current._timesForRepeat = 1;
        i = 0;
        if(!result){
            result = current;
            i = 1;
        }
        for(i; i<repeat; i++){
            result = cc.Sequence._actionOneTwo(result, current);
        }
    }
    return result;
};
cc.Sequence.create = cc.sequence;
cc.Sequence._actionOneTwo = function (actionOne, actionTwo) {
    var sequence = new cc.Sequence();
    sequence.initWithTwoActions(actionOne, actionTwo);
    return sequence;
};
cc.Repeat = cc.ActionInterval.extend({
    _times:0,
    _total:0,
    _nextDt:0,
    _actionInstant:false,
    _innerAction:null,
    ctor: function (action, times) {
        cc.ActionInterval.prototype.ctor.call(this);
        times !== undefined && this.initWithAction(action, times);
    },
    initWithAction:function (action, times) {
        var duration = action._duration * times;
        if (this.initWithDuration(duration)) {
            this._times = times;
            this._innerAction = action;
            if (action instanceof cc.ActionInstant){
                this._actionInstant = true;
                this._times -= 1;
            }
            this._total = 0;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.Repeat();
        this._cloneDecoration(action);
        action.initWithAction(this._innerAction.clone(), this._times);
        return action;
    },
    startWithTarget:function (target) {
        this._total = 0;
        this._nextDt = this._innerAction._duration / this._duration;
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._innerAction.startWithTarget(target);
    },
    stop:function () {
        this._innerAction.stop();
        cc.Action.prototype.stop.call(this);
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        var locInnerAction = this._innerAction;
        var locDuration = this._duration;
        var locTimes = this._times;
        var locNextDt = this._nextDt;
        if (dt >= locNextDt) {
            while (dt > locNextDt && this._total < locTimes) {
                locInnerAction.update(1);
                this._total++;
                locInnerAction.stop();
                locInnerAction.startWithTarget(this.target);
                locNextDt += locInnerAction._duration / locDuration;
                this._nextDt = locNextDt;
            }
            if (dt >= 1.0 && this._total < locTimes)
                this._total++;
            if (!this._actionInstant) {
                if (this._total === locTimes) {
                    locInnerAction.update(1);
                    locInnerAction.stop();
                } else {
                    locInnerAction.update(dt - (locNextDt - locInnerAction._duration / locDuration));
                }
            }
        } else {
            locInnerAction.update((dt * locTimes) % 1.0);
        }
    },
    isDone:function () {
        return this._total === this._times;
    },
    reverse:function () {
        var action = new cc.Repeat(this._innerAction.reverse(), this._times);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    setInnerAction:function (action) {
        if (this._innerAction !== action) {
            this._innerAction = action;
        }
    },
    getInnerAction:function () {
        return this._innerAction;
    }
});
cc.repeat = function (action, times) {
    return new cc.Repeat(action, times);
};
cc.Repeat.create = cc.repeat;
cc.RepeatForever = cc.ActionInterval.extend({
    _innerAction:null,
    ctor:function (action) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._innerAction = null;
        action && this.initWithAction(action);
    },
    initWithAction:function (action) {
        if(!action)
            throw new Error("cc.RepeatForever.initWithAction(): action must be non null");
        this._innerAction = action;
        return true;
    },
    clone:function () {
        var action = new cc.RepeatForever();
        this._cloneDecoration(action);
        action.initWithAction(this._innerAction.clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._innerAction.startWithTarget(target);
    },
    step:function (dt) {
        var locInnerAction = this._innerAction;
        locInnerAction.step(dt);
        if (locInnerAction.isDone()) {
            locInnerAction.startWithTarget(this.target);
            locInnerAction.step(locInnerAction.getElapsed() - locInnerAction._duration);
        }
    },
    isDone:function () {
        return false;
    },
    reverse:function () {
        var action = new cc.RepeatForever(this._innerAction.reverse());
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    setInnerAction:function (action) {
        if (this._innerAction !== action) {
            this._innerAction = action;
        }
    },
    getInnerAction:function () {
        return this._innerAction;
    }
});
cc.repeatForever = function (action) {
    return new cc.RepeatForever(action);
};
cc.RepeatForever.create = cc.repeatForever;
cc.Spawn = cc.ActionInterval.extend({
    _one:null,
    _two:null,
    ctor:function (tempArray) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._one = null;
        this._two = null;
        var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
        var last = paramArray.length - 1;
        if ((last >= 0) && (paramArray[last] == null))
            cc.log("parameters should not be ending with null in Javascript");
        if (last >= 0) {
            var prev = paramArray[0], action1;
            for (var i = 1; i < last; i++) {
                if (paramArray[i]) {
                    action1 = prev;
                    prev = cc.Spawn._actionOneTwo(action1, paramArray[i]);
                }
            }
            this.initWithTwoActions(prev, paramArray[last]);
        }
    },
    initWithTwoActions:function (action1, action2) {
        if(!action1 || !action2)
            throw new Error("cc.Spawn.initWithTwoActions(): arguments must all be non null");
        var ret = false;
        var d1 = action1._duration;
        var d2 = action2._duration;
        if (this.initWithDuration(Math.max(d1, d2))) {
            this._one = action1;
            this._two = action2;
            if (d1 > d2) {
                this._two = cc.Sequence._actionOneTwo(action2, cc.delayTime(d1 - d2));
            } else if (d1 < d2) {
                this._one = cc.Sequence._actionOneTwo(action1, cc.delayTime(d2 - d1));
            }
            ret = true;
        }
        return ret;
    },
    clone:function () {
        var action = new cc.Spawn();
        this._cloneDecoration(action);
        action.initWithTwoActions(this._one.clone(), this._two.clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._one.startWithTarget(target);
        this._two.startWithTarget(target);
    },
    stop:function () {
        this._one.stop();
        this._two.stop();
        cc.Action.prototype.stop.call(this);
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this._one)
            this._one.update(dt);
        if (this._two)
            this._two.update(dt);
    },
    reverse:function () {
        var action = cc.Spawn._actionOneTwo(this._one.reverse(), this._two.reverse());
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.spawn = function (tempArray) {
    var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
    if ((paramArray.length > 0) && (paramArray[paramArray.length - 1] == null))
        cc.log("parameters should not be ending with null in Javascript");
    var prev = paramArray[0];
    for (var i = 1; i < paramArray.length; i++) {
        if (paramArray[i] != null)
            prev = cc.Spawn._actionOneTwo(prev, paramArray[i]);
    }
    return prev;
};
cc.Spawn.create = cc.spawn;
cc.Spawn._actionOneTwo = function (action1, action2) {
    var pSpawn = new cc.Spawn();
    pSpawn.initWithTwoActions(action1, action2);
    return pSpawn;
};
cc.RotateTo = cc.ActionInterval.extend({
    _dstAngleX:0,
    _startAngleX:0,
    _diffAngleX:0,
    _dstAngleY:0,
    _startAngleY:0,
    _diffAngleY:0,
    ctor:function (duration, deltaAngleX, deltaAngleY) {
        cc.ActionInterval.prototype.ctor.call(this);
        deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY);
    },
    initWithDuration:function (duration, deltaAngleX, deltaAngleY) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._dstAngleX = deltaAngleX || 0;
            this._dstAngleY = deltaAngleY || this._dstAngleX;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.RotateTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._dstAngleX, this._dstAngleY);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        var locStartAngleX = target.rotationX % 360.0;
        var locDiffAngleX = this._dstAngleX - locStartAngleX;
        if (locDiffAngleX > 180)
            locDiffAngleX -= 360;
        if (locDiffAngleX < -180)
            locDiffAngleX += 360;
        this._startAngleX = locStartAngleX;
        this._diffAngleX = locDiffAngleX;
        this._startAngleY = target.rotationY % 360.0;
        var locDiffAngleY = this._dstAngleY - this._startAngleY;
        if (locDiffAngleY > 180)
            locDiffAngleY -= 360;
        if (locDiffAngleY < -180)
            locDiffAngleY += 360;
        this._diffAngleY = locDiffAngleY;
    },
    reverse:function () {
        cc.log("cc.RotateTo.reverse(): it should be overridden in subclass.");
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            this.target.rotationX = this._startAngleX + this._diffAngleX * dt;
            this.target.rotationY = this._startAngleY + this._diffAngleY * dt;
        }
    }
});
cc.rotateTo = function (duration, deltaAngleX, deltaAngleY) {
    return new cc.RotateTo(duration, deltaAngleX, deltaAngleY);
};
cc.RotateTo.create = cc.rotateTo;
cc.RotateBy = cc.ActionInterval.extend({
    _angleX:0,
    _startAngleX:0,
    _angleY:0,
    _startAngleY:0,
    ctor: function (duration, deltaAngleX, deltaAngleY) {
        cc.ActionInterval.prototype.ctor.call(this);
        deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY);
    },
    initWithDuration:function (duration, deltaAngleX, deltaAngleY) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._angleX = deltaAngleX || 0;
            this._angleY = deltaAngleY || this._angleX;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.RotateBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._angleX, this._angleY);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._startAngleX = target.rotationX;
        this._startAngleY = target.rotationY;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            this.target.rotationX = this._startAngleX + this._angleX * dt;
            this.target.rotationY = this._startAngleY + this._angleY * dt;
        }
    },
    reverse:function () {
        var action = new cc.RotateBy(this._duration, -this._angleX, -this._angleY);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.rotateBy = function (duration, deltaAngleX, deltaAngleY) {
    return new cc.RotateBy(duration, deltaAngleX, deltaAngleY);
};
cc.RotateBy.create = cc.rotateBy;
cc.MoveBy = cc.ActionInterval.extend({
    _positionDelta:null,
    _startPosition:null,
    _previousPosition:null,
    ctor:function (duration, deltaPos, deltaY) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._positionDelta = cc.p(0, 0);
        this._startPosition = cc.p(0, 0);
        this._previousPosition = cc.p(0, 0);
        deltaPos !== undefined && this.initWithDuration(duration, deltaPos, deltaY);
    },
    initWithDuration:function (duration, position, y) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            if(position.x !== undefined) {
                y = position.y;
                position = position.x;
            }
            this._positionDelta.x = position;
            this._positionDelta.y = y;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.MoveBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._positionDelta);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        var locPosX = target.getPositionX();
        var locPosY = target.getPositionY();
        this._previousPosition.x = locPosX;
        this._previousPosition.y = locPosY;
        this._startPosition.x = locPosX;
        this._startPosition.y = locPosY;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            var x = this._positionDelta.x * dt;
            var y = this._positionDelta.y * dt;
            var locStartPosition = this._startPosition;
            if (cc.ENABLE_STACKABLE_ACTIONS) {
                var targetX = this.target.getPositionX();
                var targetY = this.target.getPositionY();
                var locPreviousPosition = this._previousPosition;
                locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
                locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
                x = x + locStartPosition.x;
                y = y + locStartPosition.y;
                locPreviousPosition.x = x;
                locPreviousPosition.y = y;
                this.target.setPosition(x, y);
            } else {
                this.target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
            }
        }
    },
    reverse:function () {
        var action = new cc.MoveBy(this._duration, cc.p(-this._positionDelta.x, -this._positionDelta.y));
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.moveBy = function (duration, deltaPos, deltaY) {
    return new cc.MoveBy(duration, deltaPos, deltaY);
};
cc.MoveBy.create = cc.moveBy;
cc.MoveTo = cc.MoveBy.extend({
    _endPosition:null,
    ctor:function (duration, position, y) {
        cc.MoveBy.prototype.ctor.call(this);
        this._endPosition = cc.p(0, 0);
        position !== undefined && this.initWithDuration(duration, position, y);
    },
    initWithDuration:function (duration, position, y) {
        if (cc.MoveBy.prototype.initWithDuration.call(this, duration, position, y)) {
            if(position.x !== undefined) {
                y = position.y;
                position = position.x;
            }
            this._endPosition.x = position;
            this._endPosition.y = y;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.MoveTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._endPosition);
        return action;
    },
    startWithTarget:function (target) {
        cc.MoveBy.prototype.startWithTarget.call(this, target);
        this._positionDelta.x = this._endPosition.x - target.getPositionX();
        this._positionDelta.y = this._endPosition.y - target.getPositionY();
    }
});
cc.moveTo = function (duration, position, y) {
    return new cc.MoveTo(duration, position, y);
};
cc.MoveTo.create = cc.moveTo;
cc.SkewTo = cc.ActionInterval.extend({
    _skewX:0,
    _skewY:0,
    _startSkewX:0,
    _startSkewY:0,
    _endSkewX:0,
    _endSkewY:0,
    _deltaX:0,
    _deltaY:0,
    ctor: function (t, sx, sy) {
        cc.ActionInterval.prototype.ctor.call(this);
        sy !== undefined && this.initWithDuration(t, sx, sy);
    },
    initWithDuration:function (t, sx, sy) {
        var ret = false;
        if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
            this._endSkewX = sx;
            this._endSkewY = sy;
            ret = true;
        }
        return ret;
    },
    clone:function () {
        var action = new cc.SkewTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._endSkewX, this._endSkewY);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._startSkewX = target.skewX % 180;
        this._deltaX = this._endSkewX - this._startSkewX;
        if (this._deltaX > 180)
            this._deltaX -= 360;
        if (this._deltaX < -180)
            this._deltaX += 360;
        this._startSkewY = target.skewY % 360;
        this._deltaY = this._endSkewY - this._startSkewY;
        if (this._deltaY > 180)
            this._deltaY -= 360;
        if (this._deltaY < -180)
            this._deltaY += 360;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        this.target.skewX = this._startSkewX + this._deltaX * dt;
        this.target.skewY = this._startSkewY + this._deltaY * dt;
    }
});
cc.skewTo = function (t, sx, sy) {
    return new cc.SkewTo(t, sx, sy);
};
cc.SkewTo.create = cc.skewTo;
cc.SkewBy = cc.SkewTo.extend({
    ctor: function(t, sx, sy) {
        cc.SkewTo.prototype.ctor.call(this);
        sy !== undefined && this.initWithDuration(t, sx, sy);
    },
    initWithDuration:function (t, deltaSkewX, deltaSkewY) {
        var ret = false;
        if (cc.SkewTo.prototype.initWithDuration.call(this, t, deltaSkewX, deltaSkewY)) {
            this._skewX = deltaSkewX;
            this._skewY = deltaSkewY;
            ret = true;
        }
        return ret;
    },
    clone:function () {
        var action = new cc.SkewBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._skewX, this._skewY);
        return action;
    },
    startWithTarget:function (target) {
        cc.SkewTo.prototype.startWithTarget.call(this, target);
        this._deltaX = this._skewX;
        this._deltaY = this._skewY;
        this._endSkewX = this._startSkewX + this._deltaX;
        this._endSkewY = this._startSkewY + this._deltaY;
    },
    reverse:function () {
        var action = new cc.SkewBy(this._duration, -this._skewX, -this._skewY);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.skewBy = function (t, sx, sy) {
    return new cc.SkewBy(t, sx, sy);
};
cc.SkewBy.create = cc.skewBy;
cc.JumpBy = cc.ActionInterval.extend({
    _startPosition:null,
    _delta:null,
    _height:0,
    _jumps:0,
    _previousPosition:null,
    ctor:function (duration, position, y, height, jumps) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._startPosition = cc.p(0, 0);
        this._previousPosition = cc.p(0, 0);
        this._delta = cc.p(0, 0);
        height !== undefined && this.initWithDuration(duration, position, y, height, jumps);
    },
    initWithDuration:function (duration, position, y, height, jumps) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            if (jumps === undefined) {
                jumps = height;
                height = y;
                y = position.y;
                position = position.x;
            }
            this._delta.x = position;
            this._delta.y = y;
            this._height = height;
            this._jumps = jumps;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.JumpBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._delta, this._height, this._jumps);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        var locPosX = target.getPositionX();
        var locPosY = target.getPositionY();
        this._previousPosition.x = locPosX;
        this._previousPosition.y = locPosY;
        this._startPosition.x = locPosX;
        this._startPosition.y = locPosY;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            var frac = dt * this._jumps % 1.0;
            var y = this._height * 4 * frac * (1 - frac);
            y += this._delta.y * dt;
            var x = this._delta.x * dt;
            var locStartPosition = this._startPosition;
            if (cc.ENABLE_STACKABLE_ACTIONS) {
                var targetX = this.target.getPositionX();
                var targetY = this.target.getPositionY();
                var locPreviousPosition = this._previousPosition;
                locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
                locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
                x = x + locStartPosition.x;
                y = y + locStartPosition.y;
                locPreviousPosition.x = x;
                locPreviousPosition.y = y;
                this.target.setPosition(x, y);
            } else {
                this.target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
            }
        }
    },
    reverse:function () {
        var action = new cc.JumpBy(this._duration, cc.p(-this._delta.x, -this._delta.y), this._height, this._jumps);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.jumpBy = function (duration, position, y, height, jumps) {
    return new cc.JumpBy(duration, position, y, height, jumps);
};
cc.JumpBy.create = cc.jumpBy;
cc.JumpTo = cc.JumpBy.extend({
    _endPosition:null,
    ctor:function (duration, position, y, height, jumps) {
        cc.JumpBy.prototype.ctor.call(this);
        this._endPosition = cc.p(0, 0);
        height !== undefined && this.initWithDuration(duration, position, y, height, jumps);
    },
    initWithDuration:function (duration, position, y, height, jumps) {
        if (cc.JumpBy.prototype.initWithDuration.call(this, duration, position, y, height, jumps)) {
            if (jumps === undefined) {
                y = position.y;
                position = position.x;
            }
            this._endPosition.x = position;
            this._endPosition.y = y;
            return true;
        }
        return false;
    },
    startWithTarget:function (target) {
        cc.JumpBy.prototype.startWithTarget.call(this, target);
        this._delta.x = this._endPosition.x - this._startPosition.x;
        this._delta.y = this._endPosition.y - this._startPosition.y;
    },
    clone:function () {
        var action = new cc.JumpTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._endPosition, this._height, this._jumps);
        return action;
    }
});
cc.jumpTo = function (duration, position, y, height, jumps) {
    return new cc.JumpTo(duration, position, y, height, jumps);
};
cc.JumpTo.create = cc.jumpTo;
cc.bezierAt = 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 );
};
cc.BezierBy = cc.ActionInterval.extend({
    _config:null,
    _startPosition:null,
    _previousPosition:null,
    ctor:function (t, c) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._config = [];
        this._startPosition = cc.p(0, 0);
        this._previousPosition = cc.p(0, 0);
        c && this.initWithDuration(t, c);
    },
    initWithDuration:function (t, c) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
            this._config = c;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.BezierBy();
        this._cloneDecoration(action);
        var newConfigs = [];
        for (var i = 0; i < this._config.length; i++) {
            var selConf = this._config[i];
            newConfigs.push(cc.p(selConf.x, selConf.y));
        }
        action.initWithDuration(this._duration, newConfigs);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        var locPosX = target.getPositionX();
        var locPosY = target.getPositionY();
        this._previousPosition.x = locPosX;
        this._previousPosition.y = locPosY;
        this._startPosition.x = locPosX;
        this._startPosition.y = locPosY;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            var locConfig = this._config;
            var xa = 0;
            var xb = locConfig[0].x;
            var xc = locConfig[1].x;
            var xd = locConfig[2].x;
            var ya = 0;
            var yb = locConfig[0].y;
            var yc = locConfig[1].y;
            var yd = locConfig[2].y;
            var x = cc.bezierAt(xa, xb, xc, xd, dt);
            var y = cc.bezierAt(ya, yb, yc, yd, dt);
            var locStartPosition = this._startPosition;
            if (cc.ENABLE_STACKABLE_ACTIONS) {
                var targetX = this.target.getPositionX();
                var targetY = this.target.getPositionY();
                var locPreviousPosition = this._previousPosition;
                locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x;
                locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y;
                x = x + locStartPosition.x;
                y = y + locStartPosition.y;
                locPreviousPosition.x = x;
                locPreviousPosition.y = y;
                this.target.setPosition(x, y);
            } else {
                this.target.setPosition(locStartPosition.x + x, locStartPosition.y + y);
            }
        }
    },
    reverse:function () {
        var locConfig = this._config;
        var r = [
            cc.pAdd(locConfig[1], cc.pNeg(locConfig[2])),
            cc.pAdd(locConfig[0], cc.pNeg(locConfig[2])),
            cc.pNeg(locConfig[2]) ];
        var action = new cc.BezierBy(this._duration, r);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.bezierBy = function (t, c) {
    return new cc.BezierBy(t, c);
};
cc.BezierBy.create = cc.bezierBy;
cc.BezierTo = cc.BezierBy.extend({
    _toConfig:null,
    ctor:function (t, c) {
        cc.BezierBy.prototype.ctor.call(this);
        this._toConfig = [];
        c && this.initWithDuration(t, c);
    },
    initWithDuration:function (t, c) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) {
            this._toConfig = c;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.BezierTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._toConfig);
        return action;
    },
    startWithTarget:function (target) {
        cc.BezierBy.prototype.startWithTarget.call(this, target);
        var locStartPos = this._startPosition;
        var locToConfig = this._toConfig;
        var locConfig = this._config;
        locConfig[0] = cc.pSub(locToConfig[0], locStartPos);
        locConfig[1] = cc.pSub(locToConfig[1], locStartPos);
        locConfig[2] = cc.pSub(locToConfig[2], locStartPos);
    }
});
cc.bezierTo = function (t, c) {
    return new cc.BezierTo(t, c);
};
cc.BezierTo.create = cc.bezierTo;
cc.ScaleTo = cc.ActionInterval.extend({
    _scaleX:1,
    _scaleY:1,
    _startScaleX:1,
    _startScaleY:1,
    _endScaleX:0,
    _endScaleY:0,
    _deltaX:0,
    _deltaY:0,
    ctor:function (duration, sx, sy) {
        cc.ActionInterval.prototype.ctor.call(this);
        sx !== undefined && this.initWithDuration(duration, sx, sy);
    },
    initWithDuration:function (duration, sx, sy) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._endScaleX = sx;
            this._endScaleY = (sy != null) ? sy : sx;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.ScaleTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._endScaleX, this._endScaleY);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._startScaleX = target.scaleX;
        this._startScaleY = target.scaleY;
        this._deltaX = this._endScaleX - this._startScaleX;
        this._deltaY = this._endScaleY - this._startScaleY;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            this.target.scaleX = this._startScaleX + this._deltaX * dt;
            this.target.scaleY = this._startScaleY + this._deltaY * dt;
        }
    }
});
cc.scaleTo = function (duration, sx, sy) {
    return new cc.ScaleTo(duration, sx, sy);
};
cc.ScaleTo.create = cc.scaleTo;
cc.ScaleBy = cc.ScaleTo.extend({
    startWithTarget:function (target) {
        cc.ScaleTo.prototype.startWithTarget.call(this, target);
        this._deltaX = this._startScaleX * this._endScaleX - this._startScaleX;
        this._deltaY = this._startScaleY * this._endScaleY - this._startScaleY;
    },
    reverse:function () {
        var action = new cc.ScaleBy(this._duration, 1 / this._endScaleX, 1 / this._endScaleY);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    clone:function () {
        var action = new cc.ScaleBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._endScaleX, this._endScaleY);
        return action;
    }
});
cc.scaleBy = function (duration, sx, sy) {
    return new cc.ScaleBy(duration, sx, sy);
};
cc.ScaleBy.create = cc.scaleBy;
cc.Blink = cc.ActionInterval.extend({
    _times:0,
    _originalState:false,
    ctor:function (duration, blinks) {
        cc.ActionInterval.prototype.ctor.call(this);
        blinks !== undefined && this.initWithDuration(duration, blinks);
    },
    initWithDuration:function (duration, blinks) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._times = blinks;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.Blink();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._times);
        return action;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target && !this.isDone()) {
            var slice = 1.0 / this._times;
            var m = dt % slice;
            this.target.visible = (m > (slice / 2));
        }
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._originalState = target.visible;
    },
    stop:function () {
        this.target.visible = this._originalState;
        cc.ActionInterval.prototype.stop.call(this);
    },
    reverse:function () {
        var action = new cc.Blink(this._duration, this._times);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.blink = function (duration, blinks) {
    return new cc.Blink(duration, blinks);
};
cc.Blink.create = cc.blink;
cc.FadeTo = cc.ActionInterval.extend({
    _toOpacity:0,
    _fromOpacity:0,
    ctor:function (duration, opacity) {
        cc.ActionInterval.prototype.ctor.call(this);
        opacity !== undefined && this.initWithDuration(duration, opacity);
    },
    initWithDuration:function (duration, opacity) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._toOpacity = opacity;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.FadeTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._toOpacity);
        return action;
    },
    update:function (time) {
        time = this._computeEaseTime(time);
        var fromOpacity = this._fromOpacity !== undefined ? this._fromOpacity : 255;
        this.target.opacity = fromOpacity + (this._toOpacity - fromOpacity) * time;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._fromOpacity = target.opacity;
    }
});
cc.fadeTo = function (duration, opacity) {
    return new cc.FadeTo(duration, opacity);
};
cc.FadeTo.create = cc.fadeTo;
cc.FadeIn = cc.FadeTo.extend({
    _reverseAction: null,
    ctor:function (duration) {
        cc.FadeTo.prototype.ctor.call(this);
        if (duration == null)
            duration = 0;
        this.initWithDuration(duration, 255);
    },
    reverse:function () {
        var action = new cc.FadeOut();
        action.initWithDuration(this._duration, 0);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    clone:function () {
        var action = new cc.FadeIn();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._toOpacity);
        return action;
    },
    startWithTarget:function (target) {
        if(this._reverseAction)
            this._toOpacity = this._reverseAction._fromOpacity;
        cc.FadeTo.prototype.startWithTarget.call(this, target);
    }
});
cc.fadeIn = function (duration) {
    return new cc.FadeIn(duration);
};
cc.FadeIn.create = cc.fadeIn;
cc.FadeOut = cc.FadeTo.extend({
    ctor:function (duration) {
        cc.FadeTo.prototype.ctor.call(this);
        if (duration == null)
            duration = 0;
        this.initWithDuration(duration, 0);
    },
    reverse:function () {
        var action = new cc.FadeIn();
        action._reverseAction = this;
        action.initWithDuration(this._duration, 255);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    clone:function () {
        var action = new cc.FadeOut();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._toOpacity);
        return action;
    }
});
cc.fadeOut = function (d) {
    return new cc.FadeOut(d);
};
cc.FadeOut.create = cc.fadeOut;
cc.TintTo = cc.ActionInterval.extend({
    _to:null,
    _from:null,
    ctor:function (duration, red, green, blue) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._to = cc.color(0, 0, 0);
        this._from = cc.color(0, 0, 0);
        blue !== undefined && this.initWithDuration(duration, red, green, blue);
    },
    initWithDuration:function (duration, red, green, blue) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._to = cc.color(red, green, blue);
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.TintTo();
        this._cloneDecoration(action);
        var locTo = this._to;
        action.initWithDuration(this._duration, locTo.r, locTo.g, locTo.b);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._from = this.target.color;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        var locFrom = this._from, locTo = this._to;
        if (locFrom) {
            this.target.setColor(
                cc.color(
                    locFrom.r + (locTo.r - locFrom.r) * dt,
                    locFrom.g + (locTo.g - locFrom.g) * dt,
                    locFrom.b + (locTo.b - locFrom.b) * dt)
            );
        }
    }
});
cc.tintTo = function (duration, red, green, blue) {
    return new cc.TintTo(duration, red, green, blue);
};
cc.TintTo.create = cc.tintTo;
cc.TintBy = cc.ActionInterval.extend({
    _deltaR:0,
    _deltaG:0,
    _deltaB:0,
    _fromR:0,
    _fromG:0,
    _fromB:0,
    ctor:function (duration, deltaRed, deltaGreen, deltaBlue) {
        cc.ActionInterval.prototype.ctor.call(this);
        deltaBlue !== undefined && this.initWithDuration(duration, deltaRed, deltaGreen, deltaBlue);
    },
    initWithDuration:function (duration, deltaRed, deltaGreen, deltaBlue) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._deltaR = deltaRed;
            this._deltaG = deltaGreen;
            this._deltaB = deltaBlue;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.TintBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._deltaR, this._deltaG, this._deltaB);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        var color = target.color;
        this._fromR = color.r;
        this._fromG = color.g;
        this._fromB = color.b;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        this.target.color = cc.color(this._fromR + this._deltaR * dt,
                                    this._fromG + this._deltaG * dt,
                                    this._fromB + this._deltaB * dt);
    },
    reverse:function () {
        var action = new cc.TintBy(this._duration, -this._deltaR, -this._deltaG, -this._deltaB);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    }
});
cc.tintBy = function (duration, deltaRed, deltaGreen, deltaBlue) {
    return new cc.TintBy(duration, deltaRed, deltaGreen, deltaBlue);
};
cc.TintBy.create = cc.tintBy;
cc.DelayTime = cc.ActionInterval.extend({
    update:function (dt) {},
    reverse:function () {
        var action = new cc.DelayTime(this._duration);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    clone:function () {
        var action = new cc.DelayTime();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration);
        return action;
    }
});
cc.delayTime = function (d) {
    return new cc.DelayTime(d);
};
cc.DelayTime.create = cc.delayTime;
cc.ReverseTime = cc.ActionInterval.extend({
    _other:null,
    ctor:function (action) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._other = null;
        action && this.initWithAction(action);
    },
    initWithAction:function (action) {
        if(!action)
            throw new Error("cc.ReverseTime.initWithAction(): action must be non null");
        if(action === this._other)
            throw new Error("cc.ReverseTime.initWithAction(): the action was already passed in.");
        if (cc.ActionInterval.prototype.initWithDuration.call(this, action._duration)) {
            this._other = action;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.ReverseTime();
        this._cloneDecoration(action);
        action.initWithAction(this._other.clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._other.startWithTarget(target);
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (this._other)
            this._other.update(1 - dt);
    },
    reverse:function () {
        return this._other.clone();
    },
    stop:function () {
        this._other.stop();
        cc.Action.prototype.stop.call(this);
    }
});
cc.reverseTime = function (action) {
    return new cc.ReverseTime(action);
};
cc.ReverseTime.create = cc.reverseTime;
cc.Animate = cc.ActionInterval.extend({
    _animation:null,
    _nextFrame:0,
    _origFrame:null,
    _executedLoops:0,
    _splitTimes: null,
    _currFrameIndex:0,
    ctor:function (animation) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._splitTimes = [];
        animation && this.initWithAnimation(animation);
    },
    getAnimation:function () {
        return this._animation;
    },
    setAnimation:function (animation) {
        this._animation = animation;
    },
    getCurrentFrameIndex: function () {
        return this._currFrameIndex;
    },
    initWithAnimation:function (animation) {
        if(!animation)
            throw new Error("cc.Animate.initWithAnimation(): animation must be non-NULL");
        var singleDuration = animation.getDuration();
        if (this.initWithDuration(singleDuration * animation.getLoops())) {
            this._nextFrame = 0;
            this.setAnimation(animation);
            this._origFrame = null;
            this._executedLoops = 0;
            var locTimes = this._splitTimes;
            locTimes.length = 0;
            var accumUnitsOfTime = 0;
            var newUnitOfTimeValue = singleDuration / animation.getTotalDelayUnits();
            var frames = animation.getFrames();
            cc.arrayVerifyType(frames, cc.AnimationFrame);
            for (var i = 0; i < frames.length; i++) {
                var frame = frames[i];
                var value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration;
                accumUnitsOfTime += frame.getDelayUnits();
                locTimes.push(value);
            }
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.Animate();
        this._cloneDecoration(action);
        action.initWithAnimation(this._animation.clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        if (this._animation.getRestoreOriginalFrame())
            this._origFrame = target.displayFrame();
        this._nextFrame = 0;
        this._executedLoops = 0;
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        if (dt < 1.0) {
            dt *= this._animation.getLoops();
            var loopNumber = 0 | dt;
            if (loopNumber > this._executedLoops) {
                this._nextFrame = 0;
                this._executedLoops++;
            }
            dt = dt % 1.0;
        }
        var frames = this._animation.getFrames();
        var numberOfFrames = frames.length, locSplitTimes = this._splitTimes;
        for (var i = this._nextFrame; i < numberOfFrames; i++) {
            if (locSplitTimes[i] <= dt) {
                _currFrameIndex = i;
                this.target.setSpriteFrame(frames[_currFrameIndex].getSpriteFrame());
                this._nextFrame = i + 1;
            } else {
                break;
            }
        }
    },
    reverse:function () {
        var locAnimation = this._animation;
        var oldArray = locAnimation.getFrames();
        var newArray = [];
        cc.arrayVerifyType(oldArray, cc.AnimationFrame);
        if (oldArray.length > 0) {
            for (var i = oldArray.length - 1; i >= 0; i--) {
                var element = oldArray[i];
                if (!element)
                    break;
                newArray.push(element.clone());
            }
        }
        var newAnim = new cc.Animation(newArray, locAnimation.getDelayPerUnit(), locAnimation.getLoops());
        newAnim.setRestoreOriginalFrame(locAnimation.getRestoreOriginalFrame());
        var action = new cc.Animate(newAnim);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
    stop:function () {
        if (this._animation.getRestoreOriginalFrame() && this.target)
            this.target.setSpriteFrame(this._origFrame);
        cc.Action.prototype.stop.call(this);
    }
});
cc.animate = function (animation) {
    return new cc.Animate(animation);
};
cc.Animate.create = cc.animate;
cc.TargetedAction = cc.ActionInterval.extend({
    _action:null,
    _forcedTarget:null,
    ctor: function (target, action) {
        cc.ActionInterval.prototype.ctor.call(this);
        action && this.initWithTarget(target, action);
    },
    initWithTarget:function (target, action) {
        if (this.initWithDuration(action._duration)) {
            this._forcedTarget = target;
            this._action = action;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.TargetedAction();
        this._cloneDecoration(action);
        action.initWithTarget(this._forcedTarget, this._action.clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._action.startWithTarget(this._forcedTarget);
    },
    stop:function () {
        this._action.stop();
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        this._action.update(dt);
    },
    getForcedTarget:function () {
        return this._forcedTarget;
    },
    setForcedTarget:function (forcedTarget) {
        if (this._forcedTarget !== forcedTarget)
            this._forcedTarget = forcedTarget;
    }
});
cc.targetedAction = function (target, action) {
    return new cc.TargetedAction(target, action);
};
cc.TargetedAction.create = cc.targetedAction;
cc.ActionInstant = cc.FiniteTimeAction.extend({
    isDone:function () {
        return true;
    },
    step:function (dt) {
        this.update(1);
    },
    update:function (dt) {
    },
    reverse:function(){
        return this.clone();
    },
    clone:function(){
        return new cc.ActionInstant();
    }
});
cc.Show = cc.ActionInstant.extend({
    update:function (dt) {
        this.target.visible = true;
    },
    reverse:function () {
        return new cc.Hide();
    },
    clone:function(){
        return new cc.Show();
    }
});
cc.show = function () {
    return new cc.Show();
};
cc.Show.create = cc.show;
cc.Hide = cc.ActionInstant.extend({
    update:function (dt) {
        this.target.visible = false;
    },
    reverse:function () {
        return new cc.Show();
    },
    clone:function(){
        return new cc.Hide();
    }
});
cc.hide = function () {
    return new cc.Hide();
};
cc.Hide.create = cc.hide;
cc.ToggleVisibility = cc.ActionInstant.extend({
    update:function (dt) {
        this.target.visible = !this.target.visible;
    },
    reverse:function () {
        return new cc.ToggleVisibility();
    },
    clone:function(){
        return new cc.ToggleVisibility();
    }
});
cc.toggleVisibility = function () {
    return new cc.ToggleVisibility();
};
cc.ToggleVisibility.create = cc.toggleVisibility;
cc.RemoveSelf = cc.ActionInstant.extend({
     _isNeedCleanUp: true,
    ctor:function(isNeedCleanUp){
        cc.FiniteTimeAction.prototype.ctor.call(this);
        isNeedCleanUp !== undefined && this.init(isNeedCleanUp);
    },
    update:function(dt){
        this.target.removeFromParent(this._isNeedCleanUp);
    },
    /**
     * Initialization of the node, please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
     * @param isNeedCleanUp
     * @returns {boolean}
     */
    init:function(isNeedCleanUp){
        this._isNeedCleanUp = isNeedCleanUp;
        return true;
    },
    reverse:function(){
        return new cc.RemoveSelf(this._isNeedCleanUp);
    },
    clone:function(){
        return new cc.RemoveSelf(this._isNeedCleanUp);
    }
});
cc.removeSelf = function(isNeedCleanUp){
    return new cc.RemoveSelf(isNeedCleanUp);
};
cc.RemoveSelf.create = cc.removeSelf;
cc.FlipX = cc.ActionInstant.extend({
    _flippedX:false,
    ctor:function(flip){
        cc.FiniteTimeAction.prototype.ctor.call(this);
        this._flippedX = false;
        flip !== undefined && this.initWithFlipX(flip);
    },
    initWithFlipX:function (flip) {
        this._flippedX = flip;
        return true;
    },
    update:function (dt) {
        this.target.flippedX = this._flippedX;
    },
    reverse:function () {
        return new cc.FlipX(!this._flippedX);
    },
    clone:function(){
        var action = new cc.FlipX();
        action.initWithFlipX(this._flippedX);
        return action;
    }
});
cc.flipX = function (flip) {
    return new cc.FlipX(flip);
};
cc.FlipX.create = cc.flipX;
cc.FlipY = cc.ActionInstant.extend({
    _flippedY:false,
    ctor: function(flip){
        cc.FiniteTimeAction.prototype.ctor.call(this);
        this._flippedY = false;
        flip !== undefined && this.initWithFlipY(flip);
    },
    initWithFlipY:function (flip) {
        this._flippedY = flip;
        return true;
    },
    update:function (dt) {
        this.target.flippedY = this._flippedY;
    },
    reverse:function () {
        return new cc.FlipY(!this._flippedY);
    },
    clone:function(){
        var action = new cc.FlipY();
        action.initWithFlipY(this._flippedY);
        return action;
    }
});
cc.flipY = function (flip) {
    return new cc.FlipY(flip);
};
cc.FlipY.create = cc.flipY;
cc.Place = cc.ActionInstant.extend({
    _x: 0,
    _y: 0,
    ctor:function(pos, y){
        cc.FiniteTimeAction.prototype.ctor.call(this);
        this._x = 0;
        this._y = 0;
        if (pos !== undefined) {
            if (pos.x !== undefined) {
                y = pos.y;
                pos = pos.x;
            }
            this.initWithPosition(pos, y);
        }
    },
    initWithPosition: function (x, y) {
        this._x = x;
        this._y = y;
        return true;
    },
    update:function (dt) {
        this.target.setPosition(this._x, this._y);
    },
    clone:function(){
        var action = new cc.Place();
        action.initWithPosition(this._x, this._y);
        return action;
    }
});
cc.place = function (pos, y) {
    return new cc.Place(pos, y);
};
cc.Place.create = cc.place;
cc.CallFunc = cc.ActionInstant.extend({
    _selectorTarget:null,
    _function:null,
    _data:null,
    ctor:function(selector, selectorTarget, data){
        cc.FiniteTimeAction.prototype.ctor.call(this);
        this.initWithFunction(selector, selectorTarget, data);
    },
    initWithFunction:function (selector, selectorTarget, data) {
        if (selector) {
            this._function = selector;
        }
        if (selectorTarget) {
            this._selectorTarget = selectorTarget;
        }
        if (data !== undefined) {
            this._data = data;
        }
        return true;
    },
    execute:function () {
        if (this._function) {
            this._function.call(this._selectorTarget, this.target, this._data);
        }
    },
    update:function (dt) {
        this.execute();
    },
    getTargetCallback:function () {
        return this._selectorTarget;
    },
    setTargetCallback:function (sel) {
        if (sel !== this._selectorTarget) {
            if (this._selectorTarget)
                this._selectorTarget = null;
            this._selectorTarget = sel;
        }
    },
    clone:function(){
        var action = new cc.CallFunc();
        action.initWithFunction(this._function, this._selectorTarget, this._data);
        return action;
    }
});
cc.callFunc = function (selector, selectorTarget, data) {
    return new cc.CallFunc(selector, selectorTarget, data);
};
cc.CallFunc.create = cc.callFunc;
cc.ActionEase = cc.ActionInterval.extend({
    _inner:null,
    ctor: function (action) {
        cc.ActionInterval.prototype.ctor.call(this);
        action && this.initWithAction(action);
    },
    initWithAction:function (action) {
        if(!action)
            throw new Error("cc.ActionEase.initWithAction(): action must be non nil");
        if (this.initWithDuration(action.getDuration())) {
            this._inner = action;
            return true;
        }
        return false;
    },
    clone:function(){
       var action = new cc.ActionEase();
        action.initWithAction(this._inner.clone());
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._inner.startWithTarget(this.target);
    },
    stop:function () {
        this._inner.stop();
        cc.ActionInterval.prototype.stop.call(this);
    },
    update:function (dt) {
        this._inner.update(dt);
    },
    reverse:function () {
        return new cc.ActionEase(this._inner.reverse());
    },
    getInnerAction:function(){
       return this._inner;
    }
});
cc.actionEase = function (action) {
    return new cc.ActionEase(action);
};
cc.ActionEase.create = cc.actionEase;
cc.EaseRateAction = cc.ActionEase.extend({
    _rate:0,
    ctor: function(action, rate){
        cc.ActionEase.prototype.ctor.call(this);
        rate !== undefined && this.initWithAction(action, rate);
    },
    setRate:function (rate) {
        this._rate = rate;
    },
    getRate:function () {
        return this._rate;
    },
    initWithAction:function (action, rate) {
        if (cc.ActionEase.prototype.initWithAction.call(this, action)) {
            this._rate = rate;
            return true;
        }
        return false;
    },
    clone:function(){
        var action = new cc.EaseRateAction();
        action.initWithAction(this._inner.clone(), this._rate);
        return action;
    },
    reverse:function () {
        return new cc.EaseRateAction(this._inner.reverse(), 1 / this._rate);
    }
});
cc.easeRateAction = function (action, rate) {
    return new cc.EaseRateAction(action, rate);
};
cc.EaseRateAction.create = cc.easeRateAction;
cc.EaseIn = cc.EaseRateAction.extend({
    update:function (dt) {
        this._inner.update(Math.pow(dt, this._rate));
    },
    reverse:function () {
        return new cc.EaseIn(this._inner.reverse(), 1 / this._rate);
    },
    clone:function(){
        var action = new cc.EaseIn();
        action.initWithAction(this._inner.clone(), this._rate);
        return action;
    }
});
cc.EaseIn.create = function (action, rate) {
    return new cc.EaseIn(action, rate);
};
cc.easeIn = function (rate) {
    return {
        _rate: rate,
        easing: function (dt) {
            return Math.pow(dt, this._rate);
        },
        reverse: function(){
            return cc.easeIn(1 / this._rate);
        }
    };
};
cc.EaseOut = cc.EaseRateAction.extend({
    update:function (dt) {
        this._inner.update(Math.pow(dt, 1 / this._rate));
    },
    reverse:function () {
        return new cc.EaseOut(this._inner.reverse(), 1 / this._rate);
    },
    clone:function(){
        var action = new cc.EaseOut();
        action.initWithAction(this._inner.clone(),this._rate);
        return action;
    }
});
cc.EaseOut.create = function (action, rate) {
    return new cc.EaseOut(action, rate);
};
cc.easeOut = function (rate) {
    return {
        _rate: rate,
        easing: function (dt) {
            return Math.pow(dt, 1 / this._rate);
        },
        reverse: function(){
            return cc.easeOut(1 / this._rate)
        }
    };
};
cc.EaseInOut = cc.EaseRateAction.extend({
    update:function (dt) {
        dt *= 2;
        if (dt < 1)
            this._inner.update(0.5 * Math.pow(dt, this._rate));
        else
            this._inner.update(1.0 - 0.5 * Math.pow(2 - dt, this._rate));
    },
    clone:function(){
        var action = new cc.EaseInOut();
        action.initWithAction(this._inner.clone(), this._rate);
        return action;
    },
    reverse:function () {
        return new cc.EaseInOut(this._inner.reverse(), this._rate);
    }
});
cc.EaseInOut.create = function (action, rate) {
    return new cc.EaseInOut(action, rate);
};
cc.easeInOut = function (rate) {
    return {
        _rate: rate,
        easing: function (dt) {
            dt *= 2;
            if (dt < 1)
                return 0.5 * Math.pow(dt, this._rate);
            else
                return 1.0 - 0.5 * Math.pow(2 - dt, this._rate);
        },
        reverse: function(){
            return cc.easeInOut(this._rate);
        }
    };
};
cc.EaseExponentialIn = cc.ActionEase.extend({
    update:function (dt) {
        this._inner.update(dt === 0 ? 0 : Math.pow(2, 10 * (dt - 1)));
    },
    reverse:function () {
        return new cc.EaseExponentialOut(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseExponentialIn();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseExponentialIn.create = function (action) {
    return new cc.EaseExponentialIn(action);
};
cc._easeExponentialInObj = {
    easing: function(dt){
        return dt === 0 ? 0 : Math.pow(2, 10 * (dt - 1));
    },
    reverse: function(){
        return cc._easeExponentialOutObj;
    }
};
cc.easeExponentialIn = function(){
    return cc._easeExponentialInObj;
};
cc.EaseExponentialOut = cc.ActionEase.extend({
    update:function (dt) {
        this._inner.update(dt === 1 ? 1 : (-(Math.pow(2, -10 * dt)) + 1));
    },
    reverse:function () {
        return new cc.EaseExponentialIn(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseExponentialOut();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseExponentialOut.create = function (action) {
    return new cc.EaseExponentialOut(action);
};
cc._easeExponentialOutObj = {
    easing: function(dt){
        return dt === 1 ? 1 : (-(Math.pow(2, -10 * dt)) + 1);
    },
    reverse: function(){
        return cc._easeExponentialInObj;
    }
};
cc.easeExponentialOut = function(){
    return cc._easeExponentialOutObj;
};
cc.EaseExponentialInOut = cc.ActionEase.extend({
    update:function (dt) {
        if( dt !== 1 && dt !== 0) {
            dt *= 2;
            if (dt < 1)
                dt = 0.5 * Math.pow(2, 10 * (dt - 1));
            else
                dt = 0.5 * (-Math.pow(2, -10 * (dt - 1)) + 2);
        }
        this._inner.update(dt);
    },
    reverse:function () {
        return new cc.EaseExponentialInOut(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseExponentialInOut();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseExponentialInOut.create = function (action) {
    return new cc.EaseExponentialInOut(action);
};
cc._easeExponentialInOutObj = {
    easing: function(dt){
        if( dt !== 1 && dt !== 0) {
            dt *= 2;
            if (dt < 1)
                return 0.5 * Math.pow(2, 10 * (dt - 1));
            else
                return 0.5 * (-Math.pow(2, -10 * (dt - 1)) + 2);
        }
        return dt;
    },
    reverse: function(){
        return cc._easeExponentialInOutObj;
    }
};
cc.easeExponentialInOut = function(){
    return cc._easeExponentialInOutObj;
};
cc.EaseSineIn = cc.ActionEase.extend({
    update:function (dt) {
        dt = dt===0 || dt===1 ? dt : -1 * Math.cos(dt * Math.PI / 2) + 1;
        this._inner.update(dt);
    },
    reverse:function () {
        return new cc.EaseSineOut(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseSineIn();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseSineIn.create = function (action) {
    return new cc.EaseSineIn(action);
};
cc._easeSineInObj = {
    easing: function(dt){
        return (dt===0 || dt===1) ? dt : -1 * Math.cos(dt * Math.PI / 2) + 1;
    },
    reverse: function(){
        return cc._easeSineOutObj;
    }
};
cc.easeSineIn = function(){
    return cc._easeSineInObj;
};
cc.EaseSineOut = cc.ActionEase.extend({
    update:function (dt) {
        dt = dt===0 || dt===1 ? dt : Math.sin(dt * Math.PI / 2);
        this._inner.update(dt);
    },
    reverse:function () {
        return new cc.EaseSineIn(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseSineOut();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseSineOut.create = function (action) {
    return new cc.EaseSineOut(action);
};
cc._easeSineOutObj = {
    easing: function(dt){
        return (dt===0 || dt===1) ? dt : Math.sin(dt * Math.PI / 2);
    },
    reverse: function(){
        return cc._easeSineInObj;
    }
};
cc.easeSineOut = function(){
    return cc._easeSineOutObj;
};
cc.EaseSineInOut = cc.ActionEase.extend({
    update:function (dt) {
        dt = dt===0 || dt===1 ? dt : -0.5 * (Math.cos(Math.PI * dt) - 1);
        this._inner.update(dt);
    },
    clone:function(){
        var action = new cc.EaseSineInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse:function () {
        return new cc.EaseSineInOut(this._inner.reverse());
    }
});
cc.EaseSineInOut.create = function (action) {
    return new cc.EaseSineInOut(action);
};
cc._easeSineInOutObj = {
    easing: function(dt){
        return (dt === 0 || dt === 1) ? dt : -0.5 * (Math.cos(Math.PI * dt) - 1);
    },
    reverse: function(){
        return cc._easeSineInOutObj;
    }
};
cc.easeSineInOut = function(){
    return cc._easeSineInOutObj;
};
cc.EaseElastic = cc.ActionEase.extend({
    _period: 0.3,
    ctor:function(action, period){
        cc.ActionEase.prototype.ctor.call(this);
        action && this.initWithAction(action, period);
    },
    getPeriod:function () {
        return this._period;
    },
    setPeriod:function (period) {
        this._period = period;
    },
    initWithAction:function (action, period) {
        cc.ActionEase.prototype.initWithAction.call(this, action);
        this._period = (period == null) ? 0.3 : period;
        return true;
    },
    reverse:function () {
        cc.log("cc.EaseElastic.reverse(): it should be overridden in subclass.");
        return null;
    },
    clone:function(){
        var action = new cc.EaseElastic();
        action.initWithAction(this._inner.clone(), this._period);
        return action;
    }
});
cc.EaseElastic.create = function (action, period) {
    return new cc.EaseElastic(action, period);
};
cc.EaseElasticIn = cc.EaseElastic.extend({
    update:function (dt) {
        var newT = 0;
        if (dt === 0 || dt === 1) {
            newT = dt;
        } else {
            var s = this._period / 4;
            dt = dt - 1;
            newT = -Math.pow(2, 10 * dt) * Math.sin((dt - s) * Math.PI * 2 / this._period);
        }
        this._inner.update(newT);
    },
    reverse:function () {
        return new cc.EaseElasticOut(this._inner.reverse(), this._period);
    },
    clone:function(){
        var action = new cc.EaseElasticIn();
        action.initWithAction(this._inner.clone(), this._period);
        return action;
    }
});
cc.EaseElasticIn.create = function (action, period) {
    return new cc.EaseElasticIn(action, period);
};
cc._easeElasticInObj = {
   easing:function(dt){
       if (dt === 0 || dt === 1)
           return dt;
       dt = dt - 1;
       return -Math.pow(2, 10 * dt) * Math.sin((dt - (0.3 / 4)) * Math.PI * 2 / 0.3);
   },
    reverse:function(){
        return cc._easeElasticOutObj;
    }
};
cc.easeElasticIn = function (period) {
    if(period && period !== 0.3){
        return {
            _period: period,
            easing: function (dt) {
                if (dt === 0 || dt === 1)
                    return dt;
                dt = dt - 1;
                return -Math.pow(2, 10 * dt) * Math.sin((dt - (this._period / 4)) * Math.PI * 2 / this._period);
            },
            reverse:function () {
                return cc.easeElasticOut(this._period);
            }
        };
    }
    return cc._easeElasticInObj;
};
cc.EaseElasticOut = cc.EaseElastic.extend({
    update:function (dt) {
        var newT = 0;
        if (dt === 0 || dt === 1) {
            newT = dt;
        } else {
            var s = this._period / 4;
            newT = Math.pow(2, -10 * dt) * Math.sin((dt - s) * Math.PI * 2 / this._period) + 1;
        }
        this._inner.update(newT);
    },
    reverse:function () {
        return new cc.EaseElasticIn(this._inner.reverse(), this._period);
    },
    clone:function(){
        var action = new cc.EaseElasticOut();
        action.initWithAction(this._inner.clone(), this._period);
        return action;
    }
});
cc.EaseElasticOut.create = function (action, period) {
    return new cc.EaseElasticOut(action, period);
};
cc._easeElasticOutObj = {
    easing: function (dt) {
        return (dt === 0 || dt === 1) ? dt : Math.pow(2, -10 * dt) * Math.sin((dt - (0.3 / 4)) * Math.PI * 2 / 0.3) + 1;
    },
    reverse:function(){
        return cc._easeElasticInObj;
    }
};
cc.easeElasticOut = function (period) {
    if(period && period !== 0.3){
        return {
            _period: period,
            easing: function (dt) {
                return (dt === 0 || dt === 1) ? dt : Math.pow(2, -10 * dt) * Math.sin((dt - (this._period / 4)) * Math.PI * 2 / this._period) + 1;
            },
            reverse:function(){
                return cc.easeElasticIn(this._period);
            }
        };
    }
    return cc._easeElasticOutObj;
};
cc.EaseElasticInOut = cc.EaseElastic.extend({
    update:function (dt) {
        var newT = 0;
        var locPeriod = this._period;
        if (dt === 0 || dt === 1) {
            newT = dt;
        } else {
            dt = dt * 2;
            if (!locPeriod)
                locPeriod = this._period = 0.3 * 1.5;
            var s = locPeriod / 4;
            dt = dt - 1;
            if (dt < 0)
                newT = -0.5 * Math.pow(2, 10 * dt) * Math.sin((dt - s) * Math.PI * 2 / locPeriod);
            else
                newT = Math.pow(2, -10 * dt) * Math.sin((dt - s) * Math.PI * 2 / locPeriod) * 0.5 + 1;
        }
        this._inner.update(newT);
    },
    reverse:function () {
        return new cc.EaseElasticInOut(this._inner.reverse(), this._period);
    },
    clone:function(){
        var action = new cc.EaseElasticInOut();
        action.initWithAction(this._inner.clone(), this._period);
        return action;
    }
});
cc.EaseElasticInOut.create = function (action, period) {
    return new cc.EaseElasticInOut(action, period);
};
cc.easeElasticInOut = function (period) {
    period = period || 0.3;
    return {
        _period: period,
        easing: function (dt) {
            var newT = 0;
            var locPeriod = this._period;
            if (dt === 0 || dt === 1) {
                newT = dt;
            } else {
                dt = dt * 2;
                if (!locPeriod)
                    locPeriod = this._period = 0.3 * 1.5;
                var s = locPeriod / 4;
                dt = dt - 1;
                if (dt < 0)
                    newT = -0.5 * Math.pow(2, 10 * dt) * Math.sin((dt - s) * Math.PI * 2 / locPeriod);
                else
                    newT = Math.pow(2, -10 * dt) * Math.sin((dt - s) * Math.PI * 2 / locPeriod) * 0.5 + 1;
            }
            return newT;
        },
        reverse: function(){
            return cc.easeElasticInOut(this._period);
        }
    };
};
cc.EaseBounce = cc.ActionEase.extend({
    bounceTime:function (time1) {
        if (time1 < 1 / 2.75) {
            return 7.5625 * time1 * time1;
        } else if (time1 < 2 / 2.75) {
            time1 -= 1.5 / 2.75;
            return 7.5625 * time1 * time1 + 0.75;
        } else if (time1 < 2.5 / 2.75) {
            time1 -= 2.25 / 2.75;
            return 7.5625 * time1 * time1 + 0.9375;
        }
        time1 -= 2.625 / 2.75;
        return 7.5625 * time1 * time1 + 0.984375;
    },
    clone:function(){
        var action = new cc.EaseBounce();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse:function () {
        return new cc.EaseBounce(this._inner.reverse());
    }
});
cc.EaseBounce.create = function (action) {
    return new cc.EaseBounce(action);
};
cc.EaseBounceIn = cc.EaseBounce.extend({
    update:function (dt) {
        var newT = 1 - this.bounceTime(1 - dt);
        this._inner.update(newT);
    },
    reverse:function () {
        return new cc.EaseBounceOut(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseBounceIn();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseBounceIn.create = function (action) {
    return new cc.EaseBounceIn(action);
};
cc._bounceTime = function (time1) {
    if (time1 < 1 / 2.75) {
        return 7.5625 * time1 * time1;
    } else if (time1 < 2 / 2.75) {
        time1 -= 1.5 / 2.75;
        return 7.5625 * time1 * time1 + 0.75;
    } else if (time1 < 2.5 / 2.75) {
        time1 -= 2.25 / 2.75;
        return 7.5625 * time1 * time1 + 0.9375;
    }
    time1 -= 2.625 / 2.75;
    return 7.5625 * time1 * time1 + 0.984375;
};
cc._easeBounceInObj = {
    easing: function(dt){
        return 1 - cc._bounceTime(1 - dt);
    },
    reverse: function(){
        return cc._easeBounceOutObj;
    }
};
cc.easeBounceIn = function(){
    return cc._easeBounceInObj;
};
cc.EaseBounceOut = cc.EaseBounce.extend({
    update:function (dt) {
        var newT = this.bounceTime(dt);
        this._inner.update(newT);
    },
    reverse:function () {
        return new cc.EaseBounceIn(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseBounceOut();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseBounceOut.create = function (action) {
    return new cc.EaseBounceOut(action);
};
cc._easeBounceOutObj = {
    easing: function(dt){
        return cc._bounceTime(dt);
    },
    reverse:function () {
        return cc._easeBounceInObj;
    }
};
cc.easeBounceOut = function(){
    return cc._easeBounceOutObj;
};
cc.EaseBounceInOut = cc.EaseBounce.extend({
    update:function (dt) {
        var newT = 0;
        if (dt < 0.5) {
            dt = dt * 2;
            newT = (1 - this.bounceTime(1 - dt)) * 0.5;
        } else {
            newT = this.bounceTime(dt * 2 - 1) * 0.5 + 0.5;
        }
        this._inner.update(newT);
    },
    clone:function(){
        var action = new cc.EaseBounceInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse:function () {
        return new cc.EaseBounceInOut(this._inner.reverse());
    }
});
cc.EaseBounceInOut.create = function (action) {
    return new cc.EaseBounceInOut(action);
};
cc._easeBounceInOutObj = {
    easing: function (time1) {
        var newT;
        if (time1 < 0.5) {
            time1 = time1 * 2;
            newT = (1 - cc._bounceTime(1 - time1)) * 0.5;
        } else {
            newT = cc._bounceTime(time1 * 2 - 1) * 0.5 + 0.5;
        }
        return newT;
    },
    reverse: function(){
        return cc._easeBounceInOutObj;
    }
};
cc.easeBounceInOut = function(){
    return cc._easeBounceInOutObj;
};
cc.EaseBackIn = cc.ActionEase.extend({
    update:function (dt) {
        var overshoot = 1.70158;
        dt = dt===0 || dt===1 ? dt : dt * dt * ((overshoot + 1) * dt - overshoot);
        this._inner.update(dt);
    },
    reverse:function () {
        return new cc.EaseBackOut(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseBackIn();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseBackIn.create = function (action) {
    return new cc.EaseBackIn(action);
};
cc._easeBackInObj = {
    easing: function (time1) {
        var overshoot = 1.70158;
        return (time1===0 || time1===1) ? time1 : time1 * time1 * ((overshoot + 1) * time1 - overshoot);
    },
    reverse: function(){
        return cc._easeBackOutObj;
    }
};
cc.easeBackIn = function(){
    return cc._easeBackInObj;
};
cc.EaseBackOut = cc.ActionEase.extend({
    update:function (dt) {
        var overshoot = 1.70158;
        dt = dt - 1;
        this._inner.update(dt * dt * ((overshoot + 1) * dt + overshoot) + 1);
    },
    reverse:function () {
        return new cc.EaseBackIn(this._inner.reverse());
    },
    clone:function(){
        var action = new cc.EaseBackOut();
        action.initWithAction(this._inner.clone());
        return action;
    }
});
cc.EaseBackOut.create = function (action) {
    return new cc.EaseBackOut(action);
};
cc._easeBackOutObj = {
    easing: function (time1) {
        var overshoot = 1.70158;
        time1 = time1 - 1;
        return time1 * time1 * ((overshoot + 1) * time1 + overshoot) + 1;
    },
    reverse: function(){
        return cc._easeBackInObj;
    }
};
cc.easeBackOut = function(){
    return cc._easeBackOutObj;
};
cc.EaseBackInOut = cc.ActionEase.extend({
    update:function (dt) {
        var overshoot = 1.70158 * 1.525;
        dt = dt * 2;
        if (dt < 1) {
            this._inner.update((dt * dt * ((overshoot + 1) * dt - overshoot)) / 2);
        } else {
            dt = dt - 2;
            this._inner.update((dt * dt * ((overshoot + 1) * dt + overshoot)) / 2 + 1);
        }
    },
    clone:function(){
        var action = new cc.EaseBackInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse:function () {
        return new cc.EaseBackInOut(this._inner.reverse());
    }
});
cc.EaseBackInOut.create = function (action) {
    return new cc.EaseBackInOut(action);
};
cc._easeBackInOutObj = {
    easing: function (time1) {
        var overshoot = 1.70158 * 1.525;
        time1 = time1 * 2;
        if (time1 < 1) {
            return (time1 * time1 * ((overshoot + 1) * time1 - overshoot)) / 2;
        } else {
            time1 = time1 - 2;
            return (time1 * time1 * ((overshoot + 1) * time1 + overshoot)) / 2 + 1;
        }
    },
    reverse: function(){
        return cc._easeBackInOutObj;
    }
};
cc.easeBackInOut = function(){
    return cc._easeBackInOutObj;
};
cc.EaseBezierAction = cc.ActionEase.extend({
    _p0: null,
    _p1: null,
    _p2: null,
    _p3: null,
    ctor: function(action){
        cc.ActionEase.prototype.ctor.call(this, action);
    },
    _updateTime: 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 );
    },
    update: function(dt){
        var t = this._updateTime(this._p0, this._p1, this._p2, this._p3, dt);
        this._inner.update(t);
    },
    clone: function(){
        var action = new cc.EaseBezierAction();
        action.initWithAction(this._inner.clone());
        action.setBezierParamer(this._p0, this._p1, this._p2, this._p3);
        return action;
    },
    reverse: function(){
        var action = new cc.EaseBezierAction(this._inner.reverse());
        action.setBezierParamer(this._p3, this._p2, this._p1, this._p0);
        return action;
    },
    setBezierParamer: function(p0, p1, p2, p3){
        this._p0 = p0 || 0;
        this._p1 = p1 || 0;
        this._p2 = p2 || 0;
        this._p3 = p3 || 0;
    }
});
cc.EaseBezierAction.create = function(action){
    return new cc.EaseBezierAction(action);
};
cc.easeBezierAction = function(p0, p1, p2, p3){
    return {
        easing: function(time){
            return cc.EaseBezierAction.prototype._updateTime(p0, p1, p2, p3, time);
        },
        reverse: function(){
            return cc.easeBezierAction(p3, p2, p1, p0);
        }
    };
};
cc.EaseQuadraticActionIn = cc.ActionEase.extend({
    _updateTime: function(time){
        return Math.pow(time, 2);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuadraticActionIn();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuadraticActionIn(this._inner.reverse());
    }
});
cc.EaseQuadraticActionIn.create = function(action){
    return new cc.EaseQuadraticActionIn(action);
};
cc._easeQuadraticActionIn = {
    easing: cc.EaseQuadraticActionIn.prototype._updateTime,
    reverse: function(){
        return cc._easeQuadraticActionIn;
    }
};
cc.easeQuadraticActionIn = function(){
    return cc._easeQuadraticActionIn;
};
cc.EaseQuadraticActionOut = cc.ActionEase.extend({
    _updateTime: function(time){
        return -time*(time-2);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuadraticActionOut();
        action.initWithAction();
        return action;
    },
    reverse: function(){
        return new cc.EaseQuadraticActionOut(this._inner.reverse());
    }
});
cc.EaseQuadraticActionOut.create = function(action){
    return new cc.EaseQuadraticActionOut(action);
};
cc._easeQuadraticActionOut = {
    easing: cc.EaseQuadraticActionOut.prototype._updateTime,
    reverse: function(){
        return cc._easeQuadraticActionOut;
    }
};
cc.easeQuadraticActionOut = function(){
    return cc._easeQuadraticActionOut;
};
cc.EaseQuadraticActionInOut = cc.ActionEase.extend({
    _updateTime: function(time){
        var resultTime = time;
        time *= 2;
        if(time < 1){
            resultTime = time * time * 0.5;
        }else{
            --time;
            resultTime = -0.5 * ( time * ( time - 2 ) - 1)
        }
        return resultTime;
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuadraticActionInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuadraticActionInOut(this._inner.reverse());
    }
});
cc.EaseQuadraticActionInOut.create = function(action){
    return new cc.EaseQuadraticActionInOut(action);
};
cc._easeQuadraticActionInOut = {
    easing: cc.EaseQuadraticActionInOut.prototype._updateTime,
    reverse: function(){
        return cc._easeQuadraticActionInOut;
    }
};
cc.easeQuadraticActionInOut = function(){
    return cc._easeQuadraticActionInOut;
};
cc.EaseQuarticActionIn = cc.ActionEase.extend({
    _updateTime: function(time){
        return time * time * time * time;
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuarticActionIn();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuarticActionIn(this._inner.reverse());
    }
});
cc.EaseQuarticActionIn.create = function(action){
    return new cc.EaseQuarticActionIn(action);
};
cc._easeQuarticActionIn = {
    easing: cc.EaseQuarticActionIn.prototype._updateTime,
    reverse: function(){
        return cc._easeQuarticActionIn;
    }
};
cc.easeQuarticActionIn = function(){
    return cc._easeQuarticActionIn;
};
cc.EaseQuarticActionOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time -= 1;
        return -(time * time * time * time - 1);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuarticActionOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuarticActionOut(this._inner.reverse());
    }
});
cc.EaseQuarticActionOut.create = function(action){
    return new cc.EaseQuarticActionOut(action);
};
cc._easeQuarticActionOut = {
    easing: cc.EaseQuarticActionOut.prototype._updateTime,
    reverse: function(){
        return cc._easeQuarticActionOut;
    }
};
cc.easeQuarticActionOut = function(){
    return cc._easeQuarticActionOut;
};
cc.EaseQuarticActionInOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time = time*2;
        if (time < 1)
            return 0.5 * time * time * time * time;
        time -= 2;
        return -0.5 * (time * time * time * time - 2);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuarticActionInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuarticActionInOut(this._inner.reverse());
    }
});
cc.EaseQuarticActionInOut.create = function(action){
    return new cc.EaseQuarticActionInOut(action);
};
cc._easeQuarticActionInOut = {
    easing: cc.EaseQuarticActionInOut.prototype._updateTime,
    reverse: function(){
        return cc._easeQuarticActionInOut;
    }
};
cc.easeQuarticActionInOut = function(){
    return cc._easeQuarticActionInOut;
};
cc.EaseQuinticActionIn = cc.ActionEase.extend({
    _updateTime: function(time){
        return time * time * time * time * time;
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuinticActionIn();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuinticActionIn(this._inner.reverse());
    }
});
cc.EaseQuinticActionIn.create = function(action){
    return new cc.EaseQuinticActionIn(action);
};
cc._easeQuinticActionIn = {
    easing: cc.EaseQuinticActionIn.prototype._updateTime,
    reverse: function(){
        return cc._easeQuinticActionIn;
    }
};
cc.easeQuinticActionIn = function(){
    return cc._easeQuinticActionIn;
};
cc.EaseQuinticActionOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time -=1;
        return (time * time * time * time * time + 1);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuinticActionOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuinticActionOut(this._inner.reverse());
    }
});
cc.EaseQuinticActionOut.create = function(action){
    return new cc.EaseQuinticActionOut(action);
};
cc._easeQuinticActionOut = {
    easing: cc.EaseQuinticActionOut.prototype._updateTime,
    reverse: function(){
        return cc._easeQuinticActionOut;
    }
};
cc.easeQuinticActionOut = function(){
    return cc._easeQuinticActionOut;
};
cc.EaseQuinticActionInOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time = time*2;
        if (time < 1)
            return 0.5 * time * time * time * time * time;
        time -= 2;
        return 0.5 * (time * time * time * time * time + 2);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseQuinticActionInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseQuinticActionInOut(this._inner.reverse());
    }
});
cc.EaseQuinticActionInOut.create = function(action){
    return new cc.EaseQuinticActionInOut(action);
};
cc._easeQuinticActionInOut = {
    easing: cc.EaseQuinticActionInOut.prototype._updateTime,
    reverse: function(){
        return cc._easeQuinticActionInOut;
    }
};
cc.easeQuinticActionInOut = function(){
    return cc._easeQuinticActionInOut;
};
cc.EaseCircleActionIn = cc.ActionEase.extend({
    _updateTime: function(time){
        return -1 * (Math.sqrt(1 - time * time) - 1);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseCircleActionIn();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseCircleActionIn(this._inner.reverse());
    }
});
cc.EaseCircleActionIn.create = function(action){
    return new cc.EaseCircleActionIn(action);
};
cc._easeCircleActionIn = {
    easing: cc.EaseCircleActionIn.prototype._updateTime,
    reverse: function(){
        return cc._easeCircleActionIn;
    }
};
cc.easeCircleActionIn = function(){
    return cc._easeCircleActionIn;
};
cc.EaseCircleActionOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time = time - 1;
        return Math.sqrt(1 - time * time);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseCircleActionOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseCircleActionOut(this._inner.reverse());
    }
});
cc.EaseCircleActionOut.create = function(action){
    return new cc.EaseCircleActionOut(action);
};
cc._easeCircleActionOut = {
    easing: cc.EaseCircleActionOut.prototype._updateTime,
    reverse: function(){
        return cc._easeCircleActionOut;
    }
};
cc.easeCircleActionOut = function(){
    return cc._easeCircleActionOut;
};
cc.EaseCircleActionInOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time = time * 2;
        if (time < 1)
            return -0.5 * (Math.sqrt(1 - time * time) - 1);
        time -= 2;
        return 0.5 * (Math.sqrt(1 - time * time) + 1);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseCircleActionInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseCircleActionInOut(this._inner.reverse());
    }
});
cc.EaseCircleActionInOut.create = function(action){
    return new cc.EaseCircleActionInOut(action);
};
cc._easeCircleActionInOut = {
    easing: cc.EaseCircleActionInOut.prototype._updateTime,
    reverse: function(){
        return cc._easeCircleActionInOut;
    }
};
cc.easeCircleActionInOut = function(){
    return cc._easeCircleActionInOut;
};
cc.EaseCubicActionIn = cc.ActionEase.extend({
    _updateTime: function(time){
        return time * time * time;
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseCubicActionIn();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseCubicActionIn(this._inner.reverse());
    }
});
cc.EaseCubicActionIn.create = function(action){
    return new cc.EaseCubicActionIn(action);
};
cc._easeCubicActionIn = {
    easing: cc.EaseCubicActionIn.prototype._updateTime,
    reverse: function(){
        return cc._easeCubicActionIn;
    }
};
cc.easeCubicActionIn = function(){
    return cc._easeCubicActionIn;
};
cc.EaseCubicActionOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time -= 1;
        return (time * time * time + 1);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseCubicActionOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseCubicActionOut(this._inner.reverse());
    }
});
cc.EaseCubicActionOut.create = function(action){
    return new cc.EaseCubicActionOut(action);
};
cc._easeCubicActionOut = {
    easing: cc.EaseCubicActionOut.prototype._updateTime,
    reverse: function(){
        return cc._easeCubicActionOut;
    }
};
cc.easeCubicActionOut = function(){
    return cc._easeCubicActionOut;
};
cc.EaseCubicActionInOut = cc.ActionEase.extend({
    _updateTime: function(time){
        time = time*2;
        if (time < 1)
            return 0.5 * time * time * time;
        time -= 2;
        return 0.5 * (time * time * time + 2);
    },
    update: function(dt){
        this._inner.update(this._updateTime(dt));
    },
    clone: function(){
        var action = new cc.EaseCubicActionInOut();
        action.initWithAction(this._inner.clone());
        return action;
    },
    reverse: function(){
        return new cc.EaseCubicActionInOut(this._inner.reverse());
    }
});
cc.EaseCubicActionInOut.create = function(action){
    return new cc.EaseCubicActionInOut(action);
};
cc._easeCubicActionInOut = {
    easing: cc.EaseCubicActionInOut.prototype._updateTime,
    reverse: function(){
        return cc._easeCubicActionInOut;
    }
};
cc.easeCubicActionInOut = function(){
    return cc._easeCubicActionInOut;
};
cc.cardinalSplineAt = function (p0, p1, p2, p3, tension, t) {
    var t2 = t * t;
    var t3 = t2 * t;
    var s = (1 - tension) / 2;
    var b1 = s * ((-t3 + (2 * t2)) - t);
    var b2 = s * (-t3 + t2) + (2 * t3 - 3 * t2 + 1);
    var b3 = s * (t3 - 2 * t2 + t) + (-2 * t3 + 3 * t2);
    var b4 = s * (t3 - t2);
    var x = (p0.x * b1 + p1.x * b2 + p2.x * b3 + p3.x * b4);
    var y = (p0.y * b1 + p1.y * b2 + p2.y * b3 + p3.y * b4);
    return cc.p(x, y);
};
cc.reverseControlPoints = function (controlPoints) {
    var newArray = [];
    for (var i = controlPoints.length - 1; i >= 0; i--) {
        newArray.push(cc.p(controlPoints[i].x, controlPoints[i].y));
    }
    return newArray;
};
cc.cloneControlPoints = function (controlPoints) {
    var newArray = [];
    for (var i = 0; i < controlPoints.length; i++)
        newArray.push(cc.p(controlPoints[i].x, controlPoints[i].y));
    return newArray;
};
cc.copyControlPoints = cc.cloneControlPoints;
cc.getControlPointAt = function (controlPoints, pos) {
    var p = Math.min(controlPoints.length - 1, Math.max(pos, 0));
    return controlPoints[p];
};
cc.reverseControlPointsInline = function (controlPoints) {
    var len = controlPoints.length;
    var mid = 0 | (len / 2);
    for (var i = 0; i < mid; ++i) {
        var temp = controlPoints[i];
        controlPoints[i] = controlPoints[len - i - 1];
        controlPoints[len - i - 1] = temp;
    }
};
cc.CardinalSplineTo = cc.ActionInterval.extend({
    _points:null,
    _deltaT:0,
    _tension:0,
    _previousPosition:null,
    _accumulatedDiff:null,
    ctor: function (duration, points, tension) {
        cc.ActionInterval.prototype.ctor.call(this);
        this._points = [];
        tension !== undefined && this.initWithDuration(duration, points, tension);
    },
    initWithDuration:function (duration, points, tension) {
        if(!points || points.length === 0)
            throw new Error("Invalid configuration. It must at least have one control point");
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this.setPoints(points);
            this._tension = tension;
            return true;
        }
        return false;
    },
    clone:function () {
        var action = new cc.CardinalSplineTo();
        action.initWithDuration(this._duration, cc.copyControlPoints(this._points), this._tension);
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._deltaT = 1 / (this._points.length - 1);
        this._previousPosition = cc.p(this.target.getPositionX(), this.target.getPositionY());
        this._accumulatedDiff = cc.p(0, 0);
    },
    update:function (dt) {
        dt = this._computeEaseTime(dt);
        var p, lt;
        var ps = this._points;
        if (dt === 1) {
            p = ps.length - 1;
            lt = 1;
        } else {
            var locDT = this._deltaT;
            p = 0 | (dt / locDT);
            lt = (dt - locDT * p) / locDT;
        }
        var newPos = cc.cardinalSplineAt(
            cc.getControlPointAt(ps, p - 1),
            cc.getControlPointAt(ps, p - 0),
            cc.getControlPointAt(ps, p + 1),
            cc.getControlPointAt(ps, p + 2),
            this._tension, lt);
        if (cc.ENABLE_STACKABLE_ACTIONS) {
            var tempX, tempY;
            tempX = this.target.getPositionX() - this._previousPosition.x;
            tempY = this.target.getPositionY() - this._previousPosition.y;
            if (tempX !== 0 || tempY !== 0) {
                var locAccDiff = this._accumulatedDiff;
                tempX = locAccDiff.x + tempX;
                tempY = locAccDiff.y + tempY;
                locAccDiff.x = tempX;
                locAccDiff.y = tempY;
                newPos.x += tempX;
                newPos.y += tempY;
            }
        }
        this.updatePosition(newPos);
    },
    reverse:function () {
        var reversePoints = cc.reverseControlPoints(this._points);
        return cc.cardinalSplineTo(this._duration, reversePoints, this._tension);
    },
    updatePosition:function (newPos) {
        this.target.setPosition(newPos);
        this._previousPosition = newPos;
    },
    getPoints:function () {
        return this._points;
    },
    setPoints:function (points) {
        this._points = points;
    }
});
cc.cardinalSplineTo = function (duration, points, tension) {
    return new cc.CardinalSplineTo(duration, points, tension);
};
cc.CardinalSplineTo.create = cc.cardinalSplineTo;
cc.CardinalSplineBy = cc.CardinalSplineTo.extend({
    _startPosition:null,
    ctor:function (duration, points, tension) {
        cc.CardinalSplineTo.prototype.ctor.call(this);
        this._startPosition = cc.p(0, 0);
        tension !== undefined && this.initWithDuration(duration, points, tension);
    },
    startWithTarget:function (target) {
        cc.CardinalSplineTo.prototype.startWithTarget.call(this, target);
        this._startPosition.x = target.getPositionX();
        this._startPosition.y = target.getPositionY();
    },
    reverse:function () {
        var copyConfig = this._points.slice();
        var current;
        var p = copyConfig[0];
        for (var i = 1; i < copyConfig.length; ++i) {
            current = copyConfig[i];
            copyConfig[i] = cc.pSub(current, p);
            p = current;
        }
        var reverseArray = cc.reverseControlPoints(copyConfig);
        p = reverseArray[ reverseArray.length - 1 ];
        reverseArray.pop();
        p.x = -p.x;
        p.y = -p.y;
        reverseArray.unshift(p);
        for (var i = 1; i < reverseArray.length; ++i) {
            current = reverseArray[i];
            current.x = -current.x;
            current.y = -current.y;
            current.x += p.x;
            current.y += p.y;
            reverseArray[i] = current;
            p = current;
        }
        return cc.cardinalSplineBy(this._duration, reverseArray, this._tension);
    },
    updatePosition:function (newPos) {
        var pos = this._startPosition;
        var posX = newPos.x + pos.x;
        var posY = newPos.y + pos.y;
        this._previousPosition.x = posX;
        this._previousPosition.y = posY;
        this.target.setPosition(posX, posY);
    },
    clone:function () {
        var a = new cc.CardinalSplineBy();
        a.initWithDuration(this._duration, cc.copyControlPoints(this._points), this._tension);
        return a;
    }
});
cc.cardinalSplineBy = function (duration, points, tension) {
    return new cc.CardinalSplineBy(duration, points, tension);
};
cc.CardinalSplineBy.create = cc.cardinalSplineBy;
cc.CatmullRomTo = cc.CardinalSplineTo.extend({
    ctor: function(dt, points) {
        points && this.initWithDuration(dt, points);
    },
    initWithDuration:function (dt, points) {
        return cc.CardinalSplineTo.prototype.initWithDuration.call(this, dt, points, 0.5);
    },
    clone:function () {
        var action = new cc.CatmullRomTo();
        action.initWithDuration(this._duration, cc.copyControlPoints(this._points));
        return action;
    }
});
cc.catmullRomTo = function (dt, points) {
    return new cc.CatmullRomTo(dt, points);
};
cc.CatmullRomTo.create = cc.catmullRomTo;
cc.CatmullRomBy = cc.CardinalSplineBy.extend({
    ctor: function(dt, points) {
        cc.CardinalSplineBy.prototype.ctor.call(this);
        points && this.initWithDuration(dt, points);
    },
    initWithDuration:function (dt, points) {
        return cc.CardinalSplineTo.prototype.initWithDuration.call(this, dt, points, 0.5);
    },
    clone:function () {
        var action = new cc.CatmullRomBy();
        action.initWithDuration(this._duration, cc.copyControlPoints(this._points));
        return action;
    }
});
cc.catmullRomBy = function (dt, points) {
    return new cc.CatmullRomBy(dt, points);
};
cc.CatmullRomBy.create = cc.catmullRomBy;
cc.ActionTweenDelegate = cc.Class.extend({
    updateTweenAction:function(value, key){}
});
cc.ActionTween = cc.ActionInterval.extend({
    key:"",
    from:0,
    to:0,
    delta:0,
    ctor:function(duration, key, from, to){
        cc.ActionInterval.prototype.ctor.call(this);
        this.key = "";
        to !== undefined && this.initWithDuration(duration, key, from, to);
    },
    initWithDuration:function (duration, key, from, to) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this.key = key;
            this.to = to;
            this.from = from;
            return true;
        }
        return false;
    },
    startWithTarget:function (target) {
        if(!target || !target.updateTweenAction)
            throw new Error("cc.ActionTween.startWithTarget(): target must be non-null, and target must implement updateTweenAction function");
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this.delta = this.to - this.from;
    },
    update:function (dt) {
        this.target.updateTweenAction(this.to - this.delta * (1 - dt), this.key);
    },
    reverse:function () {
        return new cc.ActionTween(this.duration, this.key, this.to, this.from);
    },
    clone:function(){
        var action = new cc.ActionTween();
        action.initWithDuration(this._duration, this.key, this.from, this.to);
        return action;
    }
});
cc.actionTween = function (duration, key, from, to) {
    return new cc.ActionTween(duration, key, from, to);
};
cc.ActionTween.create = cc.actionTween;
(function(){
    var DEBUG = false;
    var sys = cc.sys;
    var version = sys.browserVersion;
    var supportWebAudio = !!(window.AudioContext || window.webkitAudioContext || window.mozAudioContext);
    var support = {ONLY_ONE: false, WEB_AUDIO: supportWebAudio, DELAY_CREATE_CTX: false, ONE_SOURCE: false };
    if (sys.browserType === sys.BROWSER_TYPE_FIREFOX) {
        support.DELAY_CREATE_CTX = true;
        support.USE_LOADER_EVENT = 'canplay';
    }
    if (sys.os === sys.OS_IOS) {
        support.USE_LOADER_EVENT = 'loadedmetadata';
    }
    if (sys.os === sys.OS_ANDROID) {
        if (sys.browserType === sys.BROWSER_TYPE_UC) {
            support.ONE_SOURCE = true;
        }
    }
    window.__audioSupport = support;
    if(DEBUG){
        setTimeout(function(){
            cc.log("browse type: " + sys.browserType);
            cc.log("browse version: " + version);
            cc.log("MULTI_CHANNEL: " + window.__audioSupport.MULTI_CHANNEL);
            cc.log("WEB_AUDIO: " + window.__audioSupport.WEB_AUDIO);
            cc.log("AUTOPLAY: " + window.__audioSupport.AUTOPLAY);
        }, 0);
    }
})();
cc.Audio = cc.Class.extend({
    src: null,
    _element: null,
    _AUDIO_TYPE: "AUDIO",
    ctor: function(url){
        this.src = url;
    },
    setBuffer: function (buffer) {
        this._AUDIO_TYPE = "WEBAUDIO";
        this._element = new cc.Audio.WebAudio(buffer);
    },
    setElement: function (element) {
        this._AUDIO_TYPE = "AUDIO";
        this._element = element;
        element.addEventListener('ended', function () {
            if (!element.loop) {
                element.paused = true;
            }
        });
    },
    play: function (offset, loop) {
        if (!this._element) return;
        this._element.loop = loop;
        this._element.play();
        if (this._AUDIO_TYPE === 'AUDIO' && this._element.paused) {
            this.stop();
            cc.Audio.touchPlayList.push({ loop: loop, offset: offset, audio: this._element });
        }
        if (cc.Audio.bindTouch === false) {
            cc.Audio.bindTouch = true;
            cc.game.canvas.addEventListener('touchstart', cc.Audio.touchStart);
        }
    },
    getPlaying: function () {
        if (!this._element) return true;
        return !this._element.paused;
    },
    stop: function () {
        if (!this._element) return;
        this._element.pause();
        try{
            this._element.currentTime = 0;
        } catch (err) {}
    },
    pause: function () {
        if (!this._element) return;
        this._element.pause();
    },
    resume: function () {
        if (!this._element) return;
        this._element.play();
    },
    setVolume: function (volume) {
        if (!this._element) return;
        this._element.volume = volume;
    },
    getVolume: function () {
        if (!this._element) return;
        return this._element.volume;
    },
    cloneNode: function () {
        var audio = new cc.Audio(this.src);
        if (this._AUDIO_TYPE === "AUDIO") {
            var elem = document.createElement("audio");
            var sources = elem.getElementsByTagName('source');
            for (var i=0; i<sources.length; i++) {
                elem.appendChild(sources[i]);
            }
            elem.src = this.src;
            audio.setElement(elem);
        } else {
            audio.setBuffer(this._element.buffer);
        }
        return audio;
    }
});
cc.Audio.touchPlayList = [
];
cc.Audio.bindTouch = false;
cc.Audio.touchStart = function () {
    var list = cc.Audio.touchPlayList;
    var item = null;
    while (item = list.pop()) {
        item.audio.loop = !!item.loop;
        item.audio.play(item.offset);
    }
};
cc.Audio.WebAudio = function (buffer) {
    this.buffer = buffer;
    this.context = cc.Audio._context;
    var volume = this.context['createGain']();
    volume['gain'].value = 1;
    volume['connect'](this.context['destination']);
    this._volume = volume;
    this._loop = false;
    this._startTime = -1;
    this._currentSource = null;
    this.playedLength = 0;
    this._currextTimer = null;
};
cc.Audio.WebAudio.prototype = {
    constructor: cc.Audio.WebAudio,
    get paused () {
        if (this._currentSource && this._currentSource.loop)
            return false;
        if (this._startTime === -1)
            return true;
        return this.context.currentTime - this._startTime > this.buffer.duration;
    },
    set paused (bool) {},
    get loop () { return this._loop; },
    set loop (bool) { return this._loop = bool; },
    get volume () { return this._volume['gain'].value; },
    set volume (num) { return this._volume['gain'].value = num; },
    get currentTime () { return this.playedLength; },
    set currentTime (num) { return this.playedLength = num; },
    play: function (offset) {
        if (this._currentSource && !this.paused) {
            this._currentSource.stop(0);
            this.playedLength = 0;
        }
        var audio = this.context["createBufferSource"]();
        audio.buffer = this.buffer;
        audio["connect"](this._volume);
        audio.loop = this._loop;
        this._startTime = this.context.currentTime;
        offset = offset || this.playedLength;
        var duration = this.buffer.duration;
        if (!this._loop) {
            if (audio.start)
                audio.start(0, offset, duration - offset);
            else if (audio["notoGrainOn"])
                audio["noteGrainOn"](0, offset, duration - offset);
            else
                audio["noteOn"](0, offset, duration - offset);
        } else {
            if (audio.start)
                audio.start(0);
            else if (audio["notoGrainOn"])
                audio["noteGrainOn"](0);
            else
                audio["noteOn"](0);
        }
        this._currentSource = audio;
        if (this.context.currentTime === 0) {
            var self = this;
            clearTimeout(this._currextTimer);
            this._currextTimer = setTimeout(function () {
                if (self.context.currentTime === 0) {
                    cc.Audio.touchPlayList.push({
                        offset: offset,
                        audio: self
                    });
                }
            }, 10);
        }
    },
    pause: function () {
        this.playedLength = this.context.currentTime - this._startTime;
        this.playedLength %= this.buffer.duration;
        var audio = this._currentSource;
        this._currentSource = null;
        this._startTime = -1;
        if (audio)
            audio.stop(0);
    }
};
(function(polyfill){
    var SWA = polyfill.WEB_AUDIO, SWB = polyfill.ONLY_ONE;
    var support = [];
    (function(){
        var audio = document.createElement("audio");
        if(audio.canPlayType) {
            var ogg = audio.canPlayType('audio/ogg; codecs="vorbis"');
            if (ogg && ogg !== "") support.push(".ogg");
            var mp3 = audio.canPlayType("audio/mpeg");
            if (mp3 && mp3 !== "") support.push(".mp3");
            var wav = audio.canPlayType('audio/wav; codecs="1"');
            if (wav && wav !== "") support.push(".wav");
            var mp4 = audio.canPlayType("audio/mp4");
            if (mp4 && mp4 !== "") support.push(".mp4");
            var m4a = audio.canPlayType("audio/x-m4a");
            if (m4a && m4a !== "") support.push(".m4a");
        }
    })();
    try{
        if(SWA){
            var context = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)();
            cc.Audio._context = context;
            if(polyfill.DELAY_CREATE_CTX)
                setTimeout(function(){
                    context = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)();
                    cc.Audio._context = context;
                }, 0);
        }
    }catch(error){
        SWA = false;
        cc.log("browser don't support web audio");
    }
    var loader = {
        cache: {},
        useWebAudio: false,
        loadBuffer: function (url, cb) {
            if (!SWA) return;
            var request = new XMLHttpRequest();
            request.open("GET", url, true);
            request.responseType = "arraybuffer";
            request.onload = function () {
                context["decodeAudioData"](request.response, function(buffer){
                    cb(null, buffer);
                }, function(){
                    cb('decode error - ' + url);
                });
            };
            request.onerror = function(){
                cb('request error - ' + url);
            };
            request.send();
        },
        load: function(realUrl, url, res, cb){
            if(support.length === 0)
                return cb("can not support audio!");
            var audio = cc.loader.getRes(url);
            if (audio)
                return cb(null, audio);
            var i;
            if(cc.loader.audioPath)
                realUrl = cc.path.join(cc.loader.audioPath, realUrl);
            var extname = cc.path.extname(realUrl);
            var typeList = [extname];
            for(i=0; i<support.length; i++){
                if(extname !== support[i]){
                    typeList.push(support[i]);
                }
            }
            audio = new cc.Audio(realUrl);
            cc.loader.cache[url] = audio;
            this.loadAudioFromExtList(realUrl, typeList, audio, cb);
            return audio;
        },
        loadAudioFromExtList: function(realUrl, typeList, audio, cb){
            if(typeList.length === 0){
                var ERRSTR = "can not found the resource of audio! Last match url is : ";
                ERRSTR += realUrl.replace(/\.(.*)?$/, "(");
                support.forEach(function(ext){
                    ERRSTR += ext + "|";
                });
                ERRSTR = ERRSTR.replace(/\|$/, ")");
                return cb({status:520, errorMessage:ERRSTR}, null);
            }
            if (SWA && this.useWebAudio) {
                this.loadBuffer(realUrl, function (error, buffer) {
                    if (error)
                        cc.log(error);
                    if (buffer)
                        audio.setBuffer(buffer);
                    cb(null, audio);
                });
                return;
            }
            var num = polyfill.ONE_SOURCE ? 1 : typeList.length;
            var dom = document.createElement('audio');
            for (var i=0; i<num; i++) {
                var source = document.createElement('source');
                source.src = cc.path.changeExtname(realUrl, typeList[i]);
                dom.appendChild(source);
            }
            audio.setElement(dom);
            var timer = setTimeout(function(){
                if (dom.readyState === 0) {
                    failure();
                } else {
                    success();
                }
            }, 8000);
            var success = function () {
                dom.removeEventListener("canplaythrough", success, false);
                dom.removeEventListener("error", failure, false);
                dom.removeEventListener("emptied", success, false);
                if (polyfill.USE_LOADER_EVENT)
                    dom.removeEventListener(polyfill.USE_LOADER_EVENT, success, false);
                clearTimeout(timer);
                cb(null, audio);
            };
            var failure = function () {
                cc.log('load audio failure - ' + realUrl);
                success();
            };
            dom.addEventListener("canplaythrough", success, false);
            dom.addEventListener("error", failure, false);
            if(polyfill.USE_LOADER_EVENT)
                dom.addEventListener(polyfill.USE_LOADER_EVENT, success, false);
        }
    };
    cc.loader.register(["mp3", "ogg", "wav", "mp4", "m4a"], loader);
    cc.audioEngine = {
        _currMusic: null,
        _musicVolume: 1,
        features: polyfill,
        willPlayMusic: function(){return false;},
        playMusic: function(url, loop){
            var bgMusic = this._currMusic;
            if (bgMusic && bgMusic.getPlaying()) {
                bgMusic.stop();
            }
            var audio = cc.loader.getRes(url);
            if (!audio) {
                cc.loader.load(url);
                audio = cc.loader.getRes(url);
            }
            audio.setVolume(this._musicVolume);
            audio.play(0, loop || false);
            this._currMusic = audio;
        },
        stopMusic: function(releaseData){
            var audio = this._currMusic;
            if (audio) {
                audio.stop();
                this._currMusic = null;
                if (releaseData)
                    cc.loader.release(audio.src);
            }
        },
        pauseMusic: function(){
            var audio = this._currMusic;
            if (audio)
                audio.pause();
        },
        resumeMusic: function(){
            var audio = this._currMusic;
            if (audio)
                audio.resume();
        },
        rewindMusic: function(){
            var audio = this._currMusic;
            if (audio){
                audio.stop();
                audio.play();
            }
        },
        getMusicVolume: function(){
            return this._musicVolume;
        },
        setMusicVolume: function(volume){
            volume = volume - 0;
            if (isNaN(volume)) volume = 1;
            if (volume > 1) volume = 1;
            if (volume < 0) volume = 0;
            this._musicVolume = volume;
            var audio = this._currMusic;
            if (audio) {
                audio.setVolume(volume);
            }
        },
        isMusicPlaying: function(){
            var audio = this._currMusic;
            if (audio) {
                return audio.getPlaying();
            } else {
                return false;
            }
        },
        _audioPool: {},
        _maxAudioInstance: 10,
        _effectVolume: 1,
        playEffect: function(url, loop){
            if (SWB && this._currMusic && this._currMusic.getPlaying()) {
                cc.log('Browser is only allowed to play one audio');
                return null;
            }
            var effectList = this._audioPool[url];
            if (!effectList) {
                effectList = this._audioPool[url] = [];
            }
            var i;
            for (i = 0; i < effectList.length; i++) {
                if (!effectList[i].getPlaying()) {
                    break;
                }
            }
            if (!SWA && i > this._maxAudioInstance) {
                var first = effectList.shift();
                first.stop();
                effectList.push(first);
                i = effectList.length - 1;
            }
            var audio;
            if (effectList[i]) {
                audio = effectList[i];
                audio.setVolume(this._effectVolume);
                audio.play(0, loop || false);
                return audio;
            }
            audio = cc.loader.getRes(url);
            if (audio && SWA && audio._AUDIO_TYPE === 'AUDIO') {
                cc.loader.release(url);
                audio = null;
            }
            if (audio) {
                if (SWA && audio._AUDIO_TYPE === 'AUDIO') {
                    loader.loadBuffer(url, function (error, buffer) {
                        audio.setBuffer(buffer);
                        audio.setVolume(cc.audioEngine._effectVolume);
                        if (!audio.getPlaying())
                            audio.play(0, loop || false);
                    });
                } else {
                    audio = audio.cloneNode();
                    audio.setVolume(this._effectVolume);
                    audio.play(0, loop || false);
                    effectList.push(audio);
                    return audio;
                }
            }
            loader.useWebAudio = true;
            cc.loader.load(url, function (audio) {
                audio = cc.loader.getRes(url);
                audio = audio.cloneNode();
                audio.setVolume(cc.audioEngine._effectVolume);
                audio.play(0, loop || false);
                effectList.push(audio);
            });
            loader.useWebAudio = false;
            return audio;
        },
        setEffectsVolume: function(volume){
            volume = volume - 0;
            if(isNaN(volume)) volume = 1;
            if(volume > 1) volume = 1;
            if(volume < 0) volume = 0;
            this._effectVolume = volume;
            var audioPool = this._audioPool;
            for(var p in audioPool){
                var audioList = audioPool[p];
                if(Array.isArray(audioList))
                    for(var i=0; i<audioList.length; i++){
                        audioList[i].setVolume(volume);
                    }
            }
        },
        getEffectsVolume: function(){
            return this._effectVolume;
        },
        pauseEffect: function(audio){
            if(audio){
                audio.pause();
            }
        },
        pauseAllEffects: function(){
            var ap = this._audioPool;
            for(var p in ap){
                var list = ap[p];
                for(var i=0; i<ap[p].length; i++){
                    if(list[i].getPlaying()){
                        list[i].pause();
                    }
                }
            }
        },
        resumeEffect: function(audio){
            if(audio)
                audio.resume();
        },
        resumeAllEffects: function(){
            var ap = this._audioPool;
            for(var p in ap){
                var list = ap[p];
                for(var i=0; i<ap[p].length; i++){
                    list[i].resume();
                }
            }
        },
        stopEffect: function(audio){
            if(audio) {
                audio.stop();
            }
        },
        stopAllEffects: function(){
            var ap = this._audioPool;
            for(var p in ap){
                var list = ap[p];
                for(var i=0; i<list.length; i++){
                    list[i].stop();
                }
                list.length = 0;
            }
        },
        unloadEffect: function(url){
            if(!url){
                return;
            }
            cc.loader.release(url);
            var pool = this._audioPool[url];
            if(pool) pool.length = 0;
            delete this._audioPool[url];
        },
        end: function(){
            this.stopMusic();
            this.stopAllEffects();
        },
        _pauseCache: [],
        _pausePlaying: function(){
            var bgMusic = this._currMusic;
            if(bgMusic && bgMusic.getPlaying()){
                bgMusic.pause();
                this._pauseCache.push(bgMusic);
            }
            var ap = this._audioPool;
            for(var p in ap){
                var list = ap[p];
                for(var i=0; i<ap[p].length; i++){
                    if(list[i].getPlaying()){
                        list[i].pause();
                        this._pauseCache.push(list[i]);
                    }
                }
            }
        },
        _resumePlaying: function(){
            var list = this._pauseCache;
            for(var i=0; i<list.length; i++){
                list[i].resume();
            }
            list.length = 0;
        }
    };
})(window.__audioSupport);
cc._globalFontSize = cc.ITEM_SIZE;
cc._globalFontName = "Arial";
cc._globalFontNameRelease = false;
cc.MenuItem = cc.Node.extend({
    _enabled: false,
    _target: null,
    _callback: null,
    _isSelected: false,
    _className: "MenuItem",
    ctor: function (callback, target) {
        var nodeP = cc.Node.prototype;
        nodeP.ctor.call(this);
        this._target = null;
        this._callback = null;
        this._isSelected = false;
        this._enabled = false;
        nodeP.setAnchorPoint.call(this, 0.5, 0.5);
        this._target = target || null;
        this._callback = callback || null;
        if (this._callback) {
            this._enabled = true;
        }
    },
    isSelected: function () {
        return this._isSelected;
    },
    setOpacityModifyRGB: function (value) {
    },
    isOpacityModifyRGB: function () {
        return false;
    },
    setTarget: function (selector, rec) {
        this._target = rec;
        this._callback = selector;
    },
    isEnabled: function () {
        return this._enabled;
    },
    setEnabled: function (enable) {
        this._enabled = enable;
    },
    initWithCallback: function (callback, target) {
        this.anchorX = 0.5;
        this.anchorY = 0.5;
        this._target = target;
        this._callback = callback;
        this._enabled = true;
        this._isSelected = false;
        return true;
    },
    rect: function () {
        var locPosition = this._position, locContentSize = this._contentSize, locAnchorPoint = this._anchorPoint;
        return cc.rect(locPosition.x - locContentSize.width * locAnchorPoint.x,
            locPosition.y - locContentSize.height * locAnchorPoint.y,
            locContentSize.width, locContentSize.height);
    },
    selected: function () {
        this._isSelected = true;
    },
    unselected: function () {
        this._isSelected = false;
    },
    setCallback: function (callback, target) {
        this._target = target;
        this._callback = callback;
    },
    activate: function () {
        if (this._enabled) {
            var locTarget = this._target, locCallback = this._callback;
            if (!locCallback)
                return;
            if (locTarget && cc.isString(locCallback)) {
                locTarget[locCallback](this);
            } else if (locTarget && cc.isFunction(locCallback)) {
                locCallback.call(locTarget, this);
            } else
                locCallback(this);
        }
    }
});
var _p = cc.MenuItem.prototype;
_p.enabled;
cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
cc.MenuItem.create = function (callback, target) {
    return new cc.MenuItem(callback, target);
};
cc.MenuItemLabel = cc.MenuItem.extend({
    _disabledColor: null,
    _label: null,
    _originalScale: 0,
    _colorBackup: null,
    ctor: function (label, selector, target) {
        cc.MenuItem.prototype.ctor.call(this, selector, target);
        this._disabledColor = null;
        this._label = null;
        this._colorBackup = null;
        if (label) {
            this._originalScale = 1.0;
            this._colorBackup = cc.color.WHITE;
            this._disabledColor = cc.color(126, 126, 126);
            this.setLabel(label);
            if (label.textureLoaded && !label.textureLoaded()) {
                label.addEventListener("load", function (sender) {
                    this.width = sender.width;
                    this.height = sender.height;
                    if (this.parent instanceof cc.Menu) {
                        this.parent.updateAlign();
                    }
                }, this);
            }
            this.setCascadeColorEnabled(true);
            this.setCascadeOpacityEnabled(true);
        }
    },
    getDisabledColor: function () {
        return this._disabledColor;
    },
    setDisabledColor: function (color) {
        this._disabledColor = color;
    },
    getLabel: function () {
        return this._label;
    },
    setLabel: function (label) {
        if (label) {
            this.addChild(label);
            label.anchorX = 0;
            label.anchorY = 0;
            this.width = label.width;
            this.height = label.height;
            label.setCascadeColorEnabled(true);
        }
        if (this._label) {
            this.removeChild(this._label, true);
        }
        this._label = label;
    },
    setEnabled: function (enabled) {
        if (this._enabled !== enabled) {
            if (!enabled) {
                this._colorBackup = this.color;
                this.setColor(this._disabledColor);
            } else {
                this.setColor(this._colorBackup);
            }
        }
        cc.MenuItem.prototype.setEnabled.call(this, enabled);
    },
    initWithLabel: function (label, selector, target) {
        this.initWithCallback(selector, target);
        this._originalScale = 1.0;
        this._colorBackup = cc.color.WHITE;
        this._disabledColor = cc.color(126, 126, 126);
        this.setLabel(label);
        this.setCascadeColorEnabled(true);
        this.setCascadeOpacityEnabled(true);
        return true;
    },
    setString: function (label) {
        this._label.string = label;
        this.width = this._label.width;
        this.height = this._label.height;
    },
    getString: function () {
        return this._label.string;
    },
    activate: function () {
        if (this._enabled) {
            this.stopAllActions();
            this.scale = this._originalScale;
            cc.MenuItem.prototype.activate.call(this);
        }
    },
    selected: function () {
        if (this._enabled) {
            cc.MenuItem.prototype.selected.call(this);
            var action = this.getActionByTag(cc.ZOOM_ACTION_TAG);
            if (action)
                this.stopAction(action);
            else
                this._originalScale = this.scale;
            var zoomAction = cc.scaleTo(0.1, this._originalScale * 1.2);
            zoomAction.setTag(cc.ZOOM_ACTION_TAG);
            this.runAction(zoomAction);
        }
    },
    unselected: function () {
        if (this._enabled) {
            cc.MenuItem.prototype.unselected.call(this);
            this.stopActionByTag(cc.ZOOM_ACTION_TAG);
            var zoomAction = cc.scaleTo(0.1, this._originalScale);
            zoomAction.setTag(cc.ZOOM_ACTION_TAG);
            this.runAction(zoomAction);
        }
    }
});
var _p = cc.MenuItemLabel.prototype;
_p.string;
cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
_p.disabledColor;
cc.defineGetterSetter(_p, "disabledColor", _p.getDisabledColor, _p.setDisabledColor);
_p.label;
cc.defineGetterSetter(_p, "label", _p.getLabel, _p.setLabel);
cc.MenuItemLabel.create = function (label, selector, target) {
    return new cc.MenuItemLabel(label, selector, target);
};
cc.MenuItemAtlasFont = cc.MenuItemLabel.extend({
    ctor: function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
        var label;
        if (value && value.length > 0) {
            label = new cc.LabelAtlas(value, charMapFile, itemWidth, itemHeight, startCharMap);
        }
        cc.MenuItemLabel.prototype.ctor.call(this, label, callback, target);
    },
    initWithString: function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
        if (!value || value.length === 0)
            throw new Error("cc.MenuItemAtlasFont.initWithString(): value should be non-null and its length should be greater than 0");
        var label = new cc.LabelAtlas();
        label.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap);
        if (this.initWithLabel(label, callback, target)) {
        }
        return true;
    }
});
cc.MenuItemAtlasFont.create = function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
    return new cc.MenuItemAtlasFont(value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target);
};
cc.MenuItemFont = cc.MenuItemLabel.extend({
    _fontSize: null,
    _fontName: null,
    ctor: function (value, callback, target) {
        var label;
        if (value && value.length > 0) {
            this._fontName = cc._globalFontName;
            this._fontSize = cc._globalFontSize;
            label = new cc.LabelTTF(value, this._fontName, this._fontSize);
        }
        else {
            this._fontSize = 0;
            this._fontName = "";
        }
        cc.MenuItemLabel.prototype.ctor.call(this, label, callback, target);
    },
    initWithString: function (value, callback, target) {
        if (!value || value.length === 0)
            throw new Error("Value should be non-null and its length should be greater than 0");
        this._fontName = cc._globalFontName;
        this._fontSize = cc._globalFontSize;
        var label = new cc.LabelTTF(value, this._fontName, this._fontSize);
        if (this.initWithLabel(label, callback, target)) {
        }
        return true;
    },
    setFontSize: function (s) {
        this._fontSize = s;
        this._recreateLabel();
    },
    getFontSize: function () {
        return this._fontSize;
    },
    setFontName: function (name) {
        this._fontName = name;
        this._recreateLabel();
    },
    getFontName: function () {
        return this._fontName;
    },
    _recreateLabel: function () {
        var label = new cc.LabelTTF(this._label.string, this._fontName, this._fontSize);
        this.setLabel(label);
    }
});
cc.MenuItemFont.setFontSize = function (fontSize) {
    cc._globalFontSize = fontSize;
};
cc.MenuItemFont.fontSize = function () {
    return cc._globalFontSize;
};
cc.MenuItemFont.setFontName = function (name) {
    if (cc._globalFontNameRelease) {
        cc._globalFontName = '';
    }
    cc._globalFontName = name;
    cc._globalFontNameRelease = true;
};
var _p = cc.MenuItemFont.prototype;
_p.fontSize;
cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
_p.fontName;
cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
cc.MenuItemFont.fontName = function () {
    return cc._globalFontName;
};
cc.MenuItemFont.create = function (value, callback, target) {
    return new cc.MenuItemFont(value, callback, target);
};
cc.MenuItemSprite = cc.MenuItem.extend({
    _normalImage: null,
    _selectedImage: null,
    _disabledImage: null,
    ctor: function (normalSprite, selectedSprite, three, four, five) {
        cc.MenuItem.prototype.ctor.call(this);
        this._normalImage = null;
        this._selectedImage = null;
        this._disabledImage = null;
        this._loader = new cc.Sprite.LoadManager();
        if (normalSprite !== undefined) {
            selectedSprite = selectedSprite || null;
            var disabledImage, target, callback;
            if (five !== undefined) {
                disabledImage = three;
                callback = four;
                target = five;
            } else if (four !== undefined && cc.isFunction(four)) {
                disabledImage = three;
                callback = four;
            } else if (four !== undefined && cc.isFunction(three)) {
                target = four;
                callback = three;
                disabledImage = null;
            } else if (three === undefined) {
                disabledImage = null;
            }
            this._loader.clear();
            if (normalSprite.textureLoaded && !normalSprite.textureLoaded()) {
                this._loader.once(normalSprite, function () {
                    this.initWithNormalSprite(normalSprite, selectedSprite, disabledImage, callback, target);
                }, this);
                return false;
            }
            this.initWithNormalSprite(normalSprite, selectedSprite, disabledImage, callback, target);
            return true;
        }
    },
    getNormalImage: function () {
        return this._normalImage;
    },
    setNormalImage: function (normalImage) {
        if (this._normalImage === normalImage) {
            return;
        }
        if (normalImage) {
            this.addChild(normalImage, 0, cc.NORMAL_TAG);
            normalImage.anchorX = 0;
            normalImage.anchorY = 0;
        }
        if (this._normalImage) {
            this.removeChild(this._normalImage, true);
        }
        this._normalImage = normalImage;
        if(!this._normalImage)
            return;
        this.width = this._normalImage.width;
        this.height = this._normalImage.height;
        this._updateImagesVisibility();
        if (normalImage.textureLoaded && !normalImage.textureLoaded()) {
            normalImage.addEventListener("load", function (sender) {
                this.width = sender.width;
                this.height = sender.height;
                if (this.parent instanceof cc.Menu) {
                    this.parent.updateAlign();
                }
            }, this);
        }
    },
    getSelectedImage: function () {
        return this._selectedImage;
    },
    setSelectedImage: function (selectedImage) {
        if (this._selectedImage === selectedImage)
            return;
        if (selectedImage) {
            this.addChild(selectedImage, 0, cc.SELECTED_TAG);
            selectedImage.anchorX = 0;
            selectedImage.anchorY = 0;
        }
        if (this._selectedImage) {
            this.removeChild(this._selectedImage, true);
        }
        this._selectedImage = selectedImage;
        this._updateImagesVisibility();
    },
    getDisabledImage: function () {
        return this._disabledImage;
    },
    setDisabledImage: function (disabledImage) {
        if (this._disabledImage === disabledImage)
            return;
        if (disabledImage) {
            this.addChild(disabledImage, 0, cc.DISABLE_TAG);
            disabledImage.anchorX = 0;
            disabledImage.anchorY = 0;
        }
        if (this._disabledImage)
            this.removeChild(this._disabledImage, true);
        this._disabledImage = disabledImage;
        this._updateImagesVisibility();
    },
    initWithNormalSprite: function (normalSprite, selectedSprite, disabledSprite, callback, target) {
        this._loader.clear();
        if (normalSprite.textureLoaded && !normalSprite.textureLoaded()) {
            this._loader.once(normalSprite, function () {
                this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, callback, target);
            }, this);
            return false;
        }
        this.initWithCallback(callback, target);
        this.setNormalImage(normalSprite);
        this.setSelectedImage(selectedSprite);
        this.setDisabledImage(disabledSprite);
        var locNormalImage = this._normalImage;
        if (locNormalImage) {
            this.width = locNormalImage.width;
            this.height = locNormalImage.height;
        }
        this.setCascadeColorEnabled(true);
        this.setCascadeOpacityEnabled(true);
        return true;
    },
    selected: function () {
        cc.MenuItem.prototype.selected.call(this);
        if (this._normalImage) {
            if (this._disabledImage)
                this._disabledImage.visible = false;
            if (this._selectedImage) {
                this._normalImage.visible = false;
                this._selectedImage.visible = true;
            } else
                this._normalImage.visible = true;
        }
    },
    unselected: function () {
        cc.MenuItem.prototype.unselected.call(this);
        if (this._normalImage) {
            this._normalImage.visible = true;
            if (this._selectedImage)
                this._selectedImage.visible = false;
            if (this._disabledImage)
                this._disabledImage.visible = false;
        }
    },
    setEnabled: function (bEnabled) {
        if (this._enabled !== bEnabled) {
            cc.MenuItem.prototype.setEnabled.call(this, bEnabled);
            this._updateImagesVisibility();
        }
    },
    _updateImagesVisibility: function () {
        var locNormalImage = this._normalImage, locSelImage = this._selectedImage, locDisImage = this._disabledImage;
        if (this._enabled) {
            if (locNormalImage)
                locNormalImage.visible = true;
            if (locSelImage)
                locSelImage.visible = false;
            if (locDisImage)
                locDisImage.visible = false;
        } else {
            if (locDisImage) {
                if (locNormalImage)
                    locNormalImage.visible = false;
                if (locSelImage)
                    locSelImage.visible = false;
                if (locDisImage)
                    locDisImage.visible = true;
            } else {
                if (locNormalImage)
                    locNormalImage.visible = true;
                if (locSelImage)
                    locSelImage.visible = false;
            }
        }
    }
});
var _p = cc.MenuItemSprite.prototype;
_p.normalImage;
cc.defineGetterSetter(_p, "normalImage", _p.getNormalImage, _p.setNormalImage);
_p.selectedImage;
cc.defineGetterSetter(_p, "selectedImage", _p.getSelectedImage, _p.setSelectedImage);
_p.disabledImage;
cc.defineGetterSetter(_p, "disabledImage", _p.getDisabledImage, _p.setDisabledImage);
cc.MenuItemSprite.create = function (normalSprite, selectedSprite, three, four, five) {
    return new cc.MenuItemSprite(normalSprite, selectedSprite, three, four, five || undefined);
};
cc.MenuItemImage = cc.MenuItemSprite.extend({
    ctor: function (normalImage, selectedImage, three, four, five) {
        var normalSprite = null,
            selectedSprite = null,
            disabledSprite = null,
            callback = null,
            target = null;
        if (normalImage === undefined || normalImage === null) {
            cc.MenuItemSprite.prototype.ctor.call(this);
        }
        else {
            normalSprite = new cc.Sprite(normalImage);
            selectedImage &&
            (selectedSprite = new cc.Sprite(selectedImage));
            if (four === undefined) {
                callback = three;
            }
            else if (five === undefined) {
                callback = three;
                target = four;
            }
            else if (five) {
                disabledSprite = new cc.Sprite(three);
                callback = four;
                target = five;
            }
            cc.MenuItemSprite.prototype.ctor.call(this, normalSprite, selectedSprite, disabledSprite, callback, target);
        }
    },
    setNormalSpriteFrame: function (frame) {
        this.setNormalImage(new cc.Sprite(frame));
    },
    setSelectedSpriteFrame: function (frame) {
        this.setSelectedImage(new cc.Sprite(frame));
    },
    setDisabledSpriteFrame: function (frame) {
        this.setDisabledImage(new cc.Sprite(frame));
    },
    initWithNormalImage: function (normalImage, selectedImage, disabledImage, callback, target) {
        var normalSprite = null;
        var selectedSprite = null;
        var disabledSprite = null;
        if (normalImage) {
            normalSprite = new cc.Sprite(normalImage);
        }
        if (selectedImage) {
            selectedSprite = new cc.Sprite(selectedImage);
        }
        if (disabledImage) {
            disabledSprite = new cc.Sprite(disabledImage);
        }
        return this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, callback, target);
    }
});
cc.MenuItemImage.create = function (normalImage, selectedImage, three, four, five) {
    return new cc.MenuItemImage(normalImage, selectedImage, three, four, five);
};
cc.MenuItemToggle = cc.MenuItem.extend({
    subItems: null,
    _selectedIndex: 0,
    _opacity: null,
    _color: null,
    ctor: function () {
        cc.MenuItem.prototype.ctor.call(this);
        this._selectedIndex = 0;
        this.subItems = [];
        this._opacity = 0;
        this._color = cc.color.WHITE;
        if(arguments.length > 0)
            this.initWithItems(Array.prototype.slice.apply(arguments));
    },
    getOpacity: function () {
        return this._opacity;
    },
    setOpacity: function (opacity) {
        this._opacity = opacity;
        if (this.subItems && this.subItems.length > 0) {
            for (var it = 0; it < this.subItems.length; it++) {
                this.subItems[it].opacity = opacity;
            }
        }
        this._color.a = opacity;
    },
    getColor: function () {
        var locColor = this._color;
        return cc.color(locColor.r, locColor.g, locColor.b, locColor.a);
    },
    setColor: function (color) {
        var locColor = this._color;
        locColor.r = color.r;
        locColor.g = color.g;
        locColor.b = color.b;
        if (this.subItems && this.subItems.length > 0) {
            for (var it = 0; it < this.subItems.length; it++) {
                this.subItems[it].setColor(color);
            }
        }
        if (color.a !== undefined && !color.a_undefined) {
            this.setOpacity(color.a);
        }
    },
    getSelectedIndex: function () {
        return this._selectedIndex;
    },
    setSelectedIndex: function (SelectedIndex) {
        if (SelectedIndex !== this._selectedIndex) {
            this._selectedIndex = SelectedIndex;
            var currItem = this.getChildByTag(cc.CURRENT_ITEM);
            if (currItem)
                currItem.removeFromParent(false);
            var item = this.subItems[this._selectedIndex];
            this.addChild(item, 0, cc.CURRENT_ITEM);
            var w = item.width, h = item.height;
            this.width = w;
            this.height = h;
            item.setPosition(w / 2, h / 2);
        }
    },
    getSubItems: function () {
        return this.subItems;
    },
    setSubItems: function (subItems) {
        this.subItems = subItems;
    },
    initWithItems: function (args) {
        var l = args.length;
        if (cc.isFunction(args[args.length - 2])) {
            this.initWithCallback(args[args.length - 2], args[args.length - 1]);
            l = l - 2;
        } else if (cc.isFunction(args[args.length - 1])) {
            this.initWithCallback(args[args.length - 1], null);
            l = l - 1;
        } else {
            this.initWithCallback(null, null);
        }
        var locSubItems = this.subItems;
        locSubItems.length = 0;
        for (var i = 0; i < l; i++) {
            if (args[i])
                locSubItems.push(args[i]);
        }
        this._selectedIndex = cc.UINT_MAX;
        this.setSelectedIndex(0);
        this.setCascadeColorEnabled(true);
        this.setCascadeOpacityEnabled(true);
        return true;
    },
    addSubItem: function (item) {
        this.subItems.push(item);
    },
    activate: function () {
        if (this._enabled) {
            var newIndex = (this._selectedIndex + 1) % this.subItems.length;
            this.setSelectedIndex(newIndex);
        }
        cc.MenuItem.prototype.activate.call(this);
    },
    selected: function () {
        cc.MenuItem.prototype.selected.call(this);
        this.subItems[this._selectedIndex].selected();
    },
    unselected: function () {
        cc.MenuItem.prototype.unselected.call(this);
        this.subItems[this._selectedIndex].unselected();
    },
    setEnabled: function (enabled) {
        if (this._enabled !== enabled) {
            cc.MenuItem.prototype.setEnabled.call(this, enabled);
            var locItems = this.subItems;
            if (locItems && locItems.length > 0) {
                for (var it = 0; it < locItems.length; it++)
                    locItems[it].enabled = enabled;
            }
        }
    },
    selectedItem: function () {
        return this.subItems[this._selectedIndex];
    },
    getSelectedItem: function() {
        return this.subItems[this._selectedIndex];
    },
    onEnter: function () {
        cc.Node.prototype.onEnter.call(this);
        this.setSelectedIndex(this._selectedIndex);
    }
});
var _p = cc.MenuItemToggle.prototype;
_p.selectedIndex;
cc.defineGetterSetter(_p, "selectedIndex", _p.getSelectedIndex, _p.setSelectedIndex);
cc.MenuItemToggle.create = function () {
    if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
        cc.log("parameters should not be ending with null in Javascript");
    var ret = new cc.MenuItemToggle();
    ret.initWithItems(Array.prototype.slice.apply(arguments));
    return ret;
};
cc.MENU_STATE_WAITING = 0;
cc.MENU_STATE_TRACKING_TOUCH = 1;
cc.MENU_HANDLER_PRIORITY = -128;
cc.DEFAULT_PADDING = 5;
cc.Menu = cc.Layer.extend({
    enabled: false,
    _selectedItem: null,
    _state: -1,
    _touchListener: null,
    _className: "Menu",
    ctor: function (menuItems) {
        cc.Layer.prototype.ctor.call(this);
        this._color = cc.color.WHITE;
        this.enabled = false;
        this._opacity = 255;
        this._selectedItem = null;
        this._state = -1;
        this._touchListener = cc.EventListener.create({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,
            onTouchBegan: this._onTouchBegan,
            onTouchMoved: this._onTouchMoved,
            onTouchEnded: this._onTouchEnded,
            onTouchCancelled: this._onTouchCancelled
        });
        if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
            cc.log("parameters should not be ending with null in Javascript");
        var argc = arguments.length, items;
        if (argc === 0) {
            items = [];
        } else if (argc === 1) {
            if (menuItems instanceof Array) {
                items = menuItems;
            }
            else items = [menuItems];
        }
        else if (argc > 1) {
            items = [];
            for (var i = 0; i < argc; i++) {
                if (arguments[i])
                    items.push(arguments[i]);
            }
        }
        this.initWithArray(items);
    },
    onEnter: function () {
        var locListener = this._touchListener;
        if (!locListener._isRegistered())
            cc.eventManager.addListener(locListener, this);
        cc.Node.prototype.onEnter.call(this);
    },
    isEnabled: function () {
        return this.enabled;
    },
    setEnabled: function (enabled) {
        this.enabled = enabled;
    },
    initWithItems: function (args) {
        var pArray = [];
        if (args) {
            for (var i = 0; i < args.length; i++) {
                if (args[i])
                    pArray.push(args[i]);
            }
        }
        return this.initWithArray(pArray);
    },
    initWithArray: function (arrayOfItems) {
        if (cc.Layer.prototype.init.call(this)) {
            this.enabled = true;
            var winSize = cc.winSize;
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setContentSize(winSize);
            this.setAnchorPoint(0.5, 0.5);
            this.ignoreAnchorPointForPosition(true);
            if (arrayOfItems) {
                for (var i = 0; i < arrayOfItems.length; i++)
                    this.addChild(arrayOfItems[i], i);
            }
            this._selectedItem = null;
            this._state = cc.MENU_STATE_WAITING;
            this.cascadeColor = true;
            this.cascadeOpacity = true;
            return true;
        }
        return false;
    },
    addChild: function (child, zOrder, tag) {
        if (!(child instanceof cc.MenuItem))
            throw new Error("cc.Menu.addChild() : Menu only supports MenuItem objects as children");
        cc.Layer.prototype.addChild.call(this, child, zOrder, tag);
    },
    updateAlign: function () {
        switch (this._align) {
            case 'vertically':
                this.alignItemsVertically();
                break;
            case 'horizontally':
                this.alignItemsHorizontally();
                break;
        }
    },
    alignItemsVertically: function () {
        this.alignItemsVerticallyWithPadding(cc.DEFAULT_PADDING);
    },
    alignItemsVerticallyWithPadding: function (padding) {
        this._align = 'vertically';
        var height = -padding, locChildren = this._children, len, i, locScaleY, locHeight, locChild;
        if (locChildren && locChildren.length > 0) {
            for (i = 0, len = locChildren.length; i < len; i++)
                height += locChildren[i].height * locChildren[i].scaleY + padding;
            var y = height / 2.0;
            for (i = 0, len = locChildren.length; i < len; i++) {
                locChild = locChildren[i];
                locHeight = locChild.height;
                locScaleY = locChild.scaleY;
                locChild.setPosition(0, y - locHeight * locScaleY / 2);
                y -= locHeight * locScaleY + padding;
            }
        }
    },
    alignItemsHorizontally: function () {
        this.alignItemsHorizontallyWithPadding(cc.DEFAULT_PADDING);
    },
    alignItemsHorizontallyWithPadding: function (padding) {
        this._align = 'horizontally';
        var width = -padding, locChildren = this._children, i, len, locScaleX, locWidth, locChild;
        if (locChildren && locChildren.length > 0) {
            for (i = 0, len = locChildren.length; i < len; i++)
                width += locChildren[i].width * locChildren[i].scaleX + padding;
            var x = -width / 2.0;
            for (i = 0, len = locChildren.length; i < len; i++) {
                locChild = locChildren[i];
                locScaleX = locChild.scaleX;
                locWidth = locChildren[i].width;
                locChild.setPosition(x + locWidth * locScaleX / 2, 0);
                x += locWidth * locScaleX + padding;
            }
        }
    },
    alignItemsInColumns: function () {
        if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
            cc.log("parameters should not be ending with null in Javascript");
        var rows = [];
        for (var i = 0; i < arguments.length; i++) {
            rows.push(arguments[i]);
        }
        var height = -5;
        var row = 0;
        var rowHeight = 0;
        var columnsOccupied = 0;
        var rowColumns, tmp, len;
        var locChildren = this._children;
        if (locChildren && locChildren.length > 0) {
            for (i = 0, len = locChildren.length; i < len; i++) {
                if (row >= rows.length)
                    continue;
                rowColumns = rows[row];
                if (!rowColumns)
                    continue;
                tmp = locChildren[i].height;
                rowHeight = ((rowHeight >= tmp || isNaN(tmp)) ? rowHeight : tmp);
                ++columnsOccupied;
                if (columnsOccupied >= rowColumns) {
                    height += rowHeight + 5;
                    columnsOccupied = 0;
                    rowHeight = 0;
                    ++row;
                }
            }
        }
        var winSize = cc.director.getWinSize();
        row = 0;
        rowHeight = 0;
        rowColumns = 0;
        var w = 0.0;
        var x = 0.0;
        var y = (height / 2);
        if (locChildren && locChildren.length > 0) {
            for (i = 0, len = locChildren.length; i < len; i++) {
                var child = locChildren[i];
                if (rowColumns === 0) {
                    rowColumns = rows[row];
                    w = winSize.width / (1 + rowColumns);
                    x = w;
                }
                tmp = child._getHeight();
                rowHeight = ((rowHeight >= tmp || isNaN(tmp)) ? rowHeight : tmp);
                child.setPosition(x - winSize.width / 2, y - tmp / 2);
                x += w;
                ++columnsOccupied;
                if (columnsOccupied >= rowColumns) {
                    y -= rowHeight + 5;
                    columnsOccupied = 0;
                    rowColumns = 0;
                    rowHeight = 0;
                    ++row;
                }
            }
        }
    },
    alignItemsInRows: function () {
        if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
            cc.log("parameters should not be ending with null in Javascript");
        var columns = [], i;
        for (i = 0; i < arguments.length; i++) {
            columns.push(arguments[i]);
        }
        var columnWidths = [];
        var columnHeights = [];
        var width = -10;
        var columnHeight = -5;
        var column = 0;
        var columnWidth = 0;
        var rowsOccupied = 0;
        var columnRows, child, len, tmp;
        var locChildren = this._children;
        if (locChildren && locChildren.length > 0) {
            for (i = 0, len = locChildren.length; i < len; i++) {
                child = locChildren[i];
                if (column >= columns.length)
                    continue;
                columnRows = columns[column];
                if (!columnRows)
                    continue;
                tmp = child.width;
                columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp);
                columnHeight += (child.height + 5);
                ++rowsOccupied;
                if (rowsOccupied >= columnRows) {
                    columnWidths.push(columnWidth);
                    columnHeights.push(columnHeight);
                    width += columnWidth + 10;
                    rowsOccupied = 0;
                    columnWidth = 0;
                    columnHeight = -5;
                    ++column;
                }
            }
        }
        var winSize = cc.director.getWinSize();
        column = 0;
        columnWidth = 0;
        columnRows = 0;
        var x = -width / 2;
        var y = 0.0;
        if (locChildren && locChildren.length > 0) {
            for (i = 0, len = locChildren.length; i < len; i++) {
                child = locChildren[i];
                if (columnRows === 0) {
                    columnRows = columns[column];
                    y = columnHeights[column];
                }
                tmp = child._getWidth();
                columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp);
                child.setPosition(x + columnWidths[column] / 2, y - winSize.height / 2);
                y -= child.height + 10;
                ++rowsOccupied;
                if (rowsOccupied >= columnRows) {
                    x += columnWidth + 5;
                    rowsOccupied = 0;
                    columnRows = 0;
                    columnWidth = 0;
                    ++column;
                }
            }
        }
    },
    removeChild: function (child, cleanup) {
        if (child == null)
            return;
        if (!(child instanceof cc.MenuItem)) {
            cc.log("cc.Menu.removeChild():Menu only supports MenuItem objects as children");
            return;
        }
        if (this._selectedItem === child)
            this._selectedItem = null;
        cc.Node.prototype.removeChild.call(this, child, cleanup);
    },
    _onTouchBegan: function (touch, event) {
        var target = event.getCurrentTarget();
        if (target._state !== cc.MENU_STATE_WAITING || !target._visible || !target.enabled)
            return false;
        for (var c = target.parent; c != null; c = c.parent) {
            if (!c.isVisible())
                return false;
        }
        target._selectedItem = target._itemForTouch(touch);
        if (target._selectedItem) {
            target._state = cc.MENU_STATE_TRACKING_TOUCH;
            target._selectedItem.selected();
            target._selectedItem.setNodeDirty();
            return true;
        }
        return false;
    },
    _onTouchEnded: function (touch, event) {
        var target = event.getCurrentTarget();
        if (target._state !== cc.MENU_STATE_TRACKING_TOUCH) {
            cc.log("cc.Menu.onTouchEnded(): invalid state");
            return;
        }
        if (target._selectedItem) {
            target._selectedItem.unselected();
            target._selectedItem.setNodeDirty();
            target._selectedItem.activate();
        }
        target._state = cc.MENU_STATE_WAITING;
    },
    _onTouchCancelled: function (touch, event) {
        var target = event.getCurrentTarget();
        if (target._state !== cc.MENU_STATE_TRACKING_TOUCH) {
            cc.log("cc.Menu.onTouchCancelled(): invalid state");
            return;
        }
        if (target._selectedItem) {
            target._selectedItem.unselected();
            target._selectedItem.setNodeDirty();
        }
        target._state = cc.MENU_STATE_WAITING;
    },
    _onTouchMoved: function (touch, event) {
        var target = event.getCurrentTarget();
        if (target._state !== cc.MENU_STATE_TRACKING_TOUCH) {
            cc.log("cc.Menu.onTouchMoved(): invalid state");
            return;
        }
        var currentItem = target._itemForTouch(touch);
        if (currentItem !== target._selectedItem) {
            if (target._selectedItem) {
                target._selectedItem.unselected();
                target._selectedItem.setNodeDirty();
            }
            target._selectedItem = currentItem;
            if (target._selectedItem) {
                target._selectedItem.selected();
                target._selectedItem.setNodeDirty();
            }
        }
    },
    onExit: function () {
        if (this._state === cc.MENU_STATE_TRACKING_TOUCH) {
            if (this._selectedItem) {
                this._selectedItem.unselected();
                this._selectedItem = null;
            }
            this._state = cc.MENU_STATE_WAITING;
        }
        cc.Node.prototype.onExit.call(this);
    },
    setOpacityModifyRGB: function (value) {
    },
    isOpacityModifyRGB: function () {
        return false;
    },
    _itemForTouch: function (touch) {
        var touchLocation = touch.getLocation();
        var itemChildren = this._children, locItemChild;
        if (itemChildren && itemChildren.length > 0) {
            for (var i = itemChildren.length - 1; i >= 0; i--) {
                locItemChild = itemChildren[i];
                if (locItemChild.isVisible() && locItemChild.isEnabled()) {
                    var local = locItemChild.convertToNodeSpace(touchLocation);
                    var r = locItemChild.rect();
                    r.x = 0;
                    r.y = 0;
                    if (cc.rectContainsPoint(r, local))
                        return locItemChild;
                }
            }
        }
        return null;
    }
});
var _p = cc.Menu.prototype;
_p.enabled;
cc.Menu.create = function (menuItems) {
    var argc = arguments.length;
    if ((argc > 0) && (arguments[argc - 1] == null))
        cc.log("parameters should not be ending with null in Javascript");
    var ret;
    if (argc === 0)
        ret = new cc.Menu();
    else if (argc === 1)
        ret = new cc.Menu(menuItems);
    else
        ret = new cc.Menu(Array.prototype.slice.call(arguments, 0));
    return ret;
};
cc.math = cc.math || {};
cc.math.EPSILON = 1.0 / 64.0;
cc.math.square = function(s){
    return s*s;
};
cc.math.almostEqual = function(lhs,rhs){
    return (lhs + cc.math.EPSILON > rhs && lhs - cc.math.EPSILON < rhs);
};
(function(cc){
    cc.math.Vec2 = function (x, y) {
        if(y === undefined){
            this.x = x.x;
            this.y = x.y;
        }else{
            this.x = x || 0;
            this.y = y || 0;
        }
    };
    var proto = cc.math.Vec2.prototype;
    proto.fill = function(x, y){
        this.x = x;
        this.y = y;
    };
    proto.length = function(){
        return Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y));
    };
    proto.lengthSq = function(){
        return cc.math.square(this.x) + cc.math.square(this.y);
    };
    proto.normalize = function(){
        var l = 1.0 / this.length();
        this.x *= l;
        this.y *= l;
        return this;
    };
    cc.math.Vec2.add = function (pOut, pV1, pV2) {
        pOut.x = pV1.x + pV2.x;
        pOut.y = pV1.y + pV2.y;
        return pOut
    };
    proto.add = function(vec){
        this.x += vec.x;
        this.y += vec.y;
        return this;
    };
    proto.dot = function (vec) {
        return this.x * vec.x + this.y * vec.y;
    };
    cc.math.Vec2.subtract = function (pOut, pV1, pV2) {
        pOut.x = pV1.x - pV2.x;
        pOut.y = pV1.y - pV2.y;
        return pOut;
    };
    proto.subtract = function(vec){
        this.x -= vec.x;
        this.y -= vec.y;
        return this;
    };
    proto.transform = function (mat3) {
        var x = this.x, y = this.y;
        this.x = x * mat3.mat[0] + y * mat3.mat[3] + mat3.mat[6];
        this.y = x * mat3.mat[1] + y * mat3.mat[4] + mat3.mat[7];
        return this;
    };
    cc.math.Vec2.scale = function (pOut, pIn, s) {
        pOut.x = pIn.x * s;
        pOut.y = pIn.y * s;
        return pOut;
    };
    proto.scale = function(s) {
        this.x *= s;
        this.y *= s;
        return this;
    };
    proto.equals = function (vec) {
        return (this.x < vec.x + cc.math.EPSILON && this.x > vec.x - cc.math.EPSILON) &&
            (this.y < vec.y + cc.math.EPSILON && this.y > vec.y - cc.math.EPSILON);
    };
})(cc);
(function(cc) {
    cc.math.Vec3 = cc.kmVec3 = function (x, y, z) {
        if(x && y === undefined){
            this.x = x.x;
            this.y = x.y;
            this.z = x.z;
        } else {
            this.x = x || 0;
            this.y = y || 0;
            this.z = z || 0;
        }
    };
    cc.math.vec3 = function(x, y, z){
        return new cc.math.Vec3(x, y, z);
    };
    var _p = cc.math.Vec3.prototype;
    _p.fill = function (x, y, z) {
        if (x && y === undefined) {
            this.x = x.x;
            this.y = x.y;
            this.z = x.z;
        } else {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        return this;
    };
    _p.length = function () {
        return Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z));
    };
    _p.lengthSq = function () {
        return cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z)
    };
    _p.normalize = function () {
        var l = 1.0 / this.length();
        this.x *= l;
        this.y *= l;
        this.z *= l;
        return this;
    };
    _p.cross = function (vec3) {
        var x = this.x, y = this.y, z = this.z;
        this.x = (y * vec3.z) - (z * vec3.y);
        this.y = (z * vec3.x) - (x * vec3.z);
        this.z = (x * vec3.y) - (y * vec3.x);
        return this;
    };
    _p.dot = function (vec) {
        return (  this.x * vec.x + this.y * vec.y + this.z * vec.z );
    };
    _p.add = function(vec){
        this.x += vec.x;
        this.y += vec.y;
        this.z += vec.z;
        return this;
    };
    _p.subtract = function (vec) {
        this.x -= vec.x;
        this.y -= vec.y;
        this.z -= vec.z;
        return this;
    };
    _p.transform = function (mat4) {
        var x = this.x, y = this.y, z = this.z, mat = mat4.mat;
        this.x = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
        this.y = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
        this.z = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
        return this;
    };
    _p.transformNormal = function(mat4){
        var x = this.x, y = this.y, z = this.z, mat = mat4.mat;
        this.x = x * mat[0] + y * mat[4] + z * mat[8];
        this.y = x * mat[1] + y * mat[5] + z * mat[9];
        this.z = x * mat[2] + y * mat[6] + z * mat[10];
        return this;
    };
    _p.transformCoord = function(mat4){
        var v = new cc.math.Vec4(this.x, this.y, this.z, 1.0);
        v.transform(mat4);
        this.x = v.x / v.w;
        this.y = v.y / v.w;
        this.z = v.z / v.w;
        return this;
    };
    _p.scale = function(scale){
        this.x *= scale;
        this.y *= scale;
        this.z *= scale;
        return this;
    };
    _p.equals = function(vec){
        var EPSILON = cc.math.EPSILON;
        return (this.x < (vec.x + EPSILON) && this.x > (vec.x - EPSILON)) &&
            (this.y < (vec.y + EPSILON) && this.y > (vec.y - EPSILON)) &&
            (this.z < (vec.z + EPSILON) && this.z > (vec.z - EPSILON));
    };
    _p.inverseTransform = function(mat4){
        var mat = mat4.mat;
        var v1 = new cc.math.Vec3(this.x - mat[12], this.y - mat[13], this.z - mat[14]);
        this.x = v1.x * mat[0] + v1.y * mat[1] + v1.z * mat[2];
        this.y = v1.x * mat[4] + v1.y * mat[5] + v1.z * mat[6];
        this.z = v1.x * mat[8] + v1.y * mat[9] + v1.z * mat[10];
        return this;
    };
    _p.inverseTransformNormal = function(mat4){
        var x = this.x, y = this.y, z = this.z, mat = mat4.mat;
        this.x = x * mat[0] + y * mat[1] + z * mat[2];
        this.y = x * mat[4] + y * mat[5] + z * mat[6];
        this.z = x * mat[8] + y * mat[9] + z * mat[10];
        return this;
    };
    _p.assignFrom = function(vec){
        if(!vec)
            return this;
        this.x = vec.x;
        this.y = vec.y;
        this.z = vec.z;
         return this;
    };
    cc.math.Vec3.zero = function(vec){
        vec.x = vec.y = vec.z = 0.0;
        return vec;
    };
    _p.toTypeArray = function(){
        var tyArr = new Float32Array(3);
        tyArr[0] = this.x;
        tyArr[1] = this.y;
        tyArr[2] = this.z;
        return tyArr;
    };
})(cc);
(function(cc) {
    cc.math.Vec4 = function (x, y, z, w) {
        if (x && y === undefined) {
            this.x = x.x;
            this.y = x.y;
            this.z = x.z;
            this.w = x.w;
        } else {
            this.x = x || 0;
            this.y = y || 0;
            this.z = z || 0;
            this.w = w || 0;
        }
    };
    cc.kmVec4 = cc.math.Vec4;
    var proto = cc.math.Vec4.prototype;
    proto.fill = function (x, y, z, w) {
        if (x && y === undefined) {
            this.x = x.x;
            this.y = x.y;
            this.z = x.z;
            this.w = x.w;
        } else {
            this.x = x;
            this.y = y;
            this.z = z;
            this.w = w;
        }
    };
    proto.add = function(vec) {
        if(!vec)
            return this;
        this.x += vec.x;
        this.y += vec.y;
        this.z += vec.z;
        this.w += vec.w;
        return this;
    };
    proto.dot = function(vec){
        return ( this.x * vec.x + this.y * vec.y + this.z * vec.z + this.w * vec.w );
    };
    proto.length = function(){
        return Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z) + cc.math.square(this.w));
    };
    proto.lengthSq = function(){
        return cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z) + cc.math.square(this.w);
    };
    proto.lerp = function(vec, t){
        return this;
    };
    proto.normalize = function() {
        var l = 1.0 / this.length();
        this.x *= l;
        this.y *= l;
        this.z *= l;
        this.w *= l;
        return this;
    };
    proto.scale = function(scale){
        this.normalize();
        this.x *= scale;
        this.y *= scale;
        this.z *= scale;
        this.w *= scale;
        return this;
    };
    proto.subtract = function(vec) {
        this.x -= vec.x;
        this.y -= vec.y;
        this.z -= vec.z;
        this.w -= vec.w;
    };
    proto.transform = function(mat4) {
        var x = this.x, y = this.y, z = this.z, w = this.w, mat = mat4.mat;
        this.x = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
        this.y = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
        this.z = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
        this.w = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
        return this;
    };
    cc.math.Vec4.transformArray = function(vecArray, mat4){
        var retArray = [];
        for (var i = 0; i < vecArray.length; i++) {
            var selVec = new cc.math.Vec4(vecArray[i]);
            selVec.transform(mat4);
            retArray.push(selVec);
        }
        return retArray;
    };
    proto.equals = function(vec){
       var EPSILON = cc.math.EPSILON;
        return (this.x < vec.x + EPSILON && this.x > vec.x - EPSILON) &&
            (this.y < vec.y + EPSILON && this.y > vec.y - EPSILON) &&
            (this.z < vec.z + EPSILON && this.z > vec.z - EPSILON) &&
            (this.w < vec.w + EPSILON && this.w > vec.w - EPSILON);
    };
    proto.assignFrom = function(vec) {
        this.x = vec.x;
        this.y = vec.y;
        this.z = vec.z;
        this.w = vec.w;
        return this;
    };
    proto.toTypeArray = function(){
        var tyArr = new Float32Array(4);
        tyArr[0] = this.x;
        tyArr[1] = this.y;
        tyArr[2] = this.z;
        tyArr[3] = this.w;
        return tyArr;
    };
})(cc);
(function(cc){
    cc.math.Ray2 = function (start, dir) {
        this.start = start || new cc.math.Vec2();
        this.dir = dir || new cc.math.Vec2();
    };
    cc.math.Ray2.prototype.fill = function (px, py, vx, vy) {
        this.start.x = px;
        this.start.y = py;
        this.dir.x = vx;
        this.dir.y = vy;
    };
    cc.math.Ray2.prototype.intersectLineSegment = function (p1, p2, intersection) {
        var x1 = this.start.x, y1 = this.start.y;
        var x2 = this.start.x + this.dir.x, y2 = this.start.y + this.dir.y;
        var x3 = p1.x, y3 = p1.y;
        var x4 = p2.x, y4 = p2.y;
        var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
        var ua, x, y;
        if (denom > -cc.math.EPSILON && denom < cc.math.EPSILON)
            return false;
        ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
        x = x1 + ua * (x2 - x1);
        y = y1 + ua * (y2 - y1);
        if (x < Math.min(p1.x, p2.x) - cc.math.EPSILON ||
            x > Math.max(p1.x, p2.x) + cc.math.EPSILON ||
            y < Math.min(p1.y, p2.y) - cc.math.EPSILON ||
            y > Math.max(p1.y, p2.y) + cc.math.EPSILON) {
            return false;
        }
        if (x < Math.min(x1, x2) - cc.math.EPSILON ||
            x > Math.max(x1, x2) + cc.math.EPSILON ||
            y < Math.min(y1, y2) - cc.math.EPSILON ||
            y > Math.max(y1, y2) + cc.math.EPSILON) {
            return false;
        }
        intersection.x = x;
        intersection.y = y;
        return true;
    };
    function calculate_line_normal(p1, p2, normalOut){
        var tmp = new cc.math.Vec2(p2);
        tmp.subtract(p1);
        normalOut.x = -tmp.y;
        normalOut.y = tmp.x;
        normalOut.normalize();
    }
    cc.math.Ray2.prototype.intersectTriangle = function(p1, p2, p3, intersection, normal_out){
        var intersect = new cc.math.Vec2(), final_intersect = new cc.math.Vec2();
        var normal = new cc.math.Vec2(), distance = 10000.0, intersected = false;
        var this_distance;
        if(this.intersectLineSegment(p1, p2, intersect)) {
            intersected = true;
            this_distance = intersect.subtract(this.start).length();
            if(this_distance < distance) {
                final_intersect.x = intersect.x;
                final_intersect.y = intersect.y;
                distance = this_distance;
                calculate_line_normal(p1, p2, normal);
            }
        }
        if(this.intersectLineSegment(p2, p3, intersect)) {
            intersected = true;
            this_distance = intersect.subtract(this.start).length();
            if(this_distance < distance) {
                final_intersect.x = intersect.x;
                final_intersect.y = intersect.y;
                distance = this_distance;
                calculate_line_normal(p2, p3, normal);
            }
        }
        if(this.intersectLineSegment(p3, p1, intersect)) {
            intersected = true;
            this_distance = intersect.subtract(this.start).length();
            if(this_distance < distance) {
                final_intersect.x = intersect.x;
                final_intersect.y = intersect.y;
                distance = this_distance;
                calculate_line_normal(p3, p1, normal);
            }
        }
        if(intersected) {
            intersection.x = final_intersect.x;
            intersection.y = final_intersect.y;
            if(normal_out) {
                normal_out.x = normal.x;
                normal_out.y = normal.y;
            }
        }
        return intersected;
    };
})(cc);
window.Uint16Array = window.Uint16Array || window.Array;
window.Float32Array = window.Float32Array || window.Array;
(function(cc){
    cc.math.Matrix3 = function(mat3) {
        if (mat3 && mat3.mat) {
            this.mat = new Float32Array(mat3.mat);
        } else {
            this.mat = new Float32Array(9);
        }
    };
    cc.kmMat3 = cc.math.Matrix3;
    var _p = cc.math.Matrix3.prototype;
    _p.fill = function(mat3) {
        var mat = this.mat, matIn = mat3.mat;
        mat[0] = matIn[0];
        mat[1] = matIn[1];
        mat[2] = matIn[2];
        mat[3] = matIn[3];
        mat[4] = matIn[4];
        mat[5] = matIn[5];
        mat[6] = matIn[6];
        mat[7] = matIn[7];
        mat[8] = matIn[8];
        return this;
    };
    _p.adjugate = function(){
        var mat = this.mat;
        var m0 = mat[0], m1 = mat[1], m2 = mat[2], m3 = mat[3], m4 = mat[4],
            m5 = mat[5], m6 = mat[6], m7 = mat[7], m8 = mat[8];
        mat[0] = m4 * m8 - m5 * m7;
        mat[1] = m2 * m7 - m1 * m8;
        mat[2] = m1 * m5 - m2 * m4;
        mat[3] = m5 * m6 - m3 * m8;
        mat[4] = m0 * m8 - m2 * m6;
        mat[5] = m2 * m3 - m0 * m5;
        mat[6] = m3 * m7 - m4 * m6;
        mat[8] = m0 * m4 - m1 * m3;
        return this;
    };
    _p.identity = function() {
        var mat = this.mat;
        mat[1] = mat[2] = mat[3] =
            mat[5] = mat[6] = mat[7] = 0;
        mat[0] = mat[4] = mat[8] = 1.0;
        return this;
    };
    var tmpMatrix = new cc.math.Matrix3();
    _p.inverse = function(determinate){
        if (determinate === 0.0)
            return this;
        tmpMatrix.assignFrom(this);
        var detInv = 1.0 / determinate;
        this.adjugate();
        this.multiplyScalar(detInv);
        return this;
    };
    _p.isIdentity = function(){
        var mat = this.mat;
        return (mat[0] === 1 && mat[1] === 0 && mat[2] === 0
        && mat[3] === 0 && mat[4] === 1 && mat[5] === 0
        && mat[6] === 0 && mat[7] === 0 && mat[8] === 1);
    };
    _p.transpose = function(){
        var mat = this.mat;
        var  m1 = mat[1], m2 = mat[2], m3 = mat[3],  m5 = mat[5],
            m6 = mat[6], m7 = mat[7];
        mat[1] = m3;
        mat[2] = m6;
        mat[3] = m1;
        mat[5] = m7;
        mat[6] = m2;
        mat[7] = m5;
        return this;
    };
    _p.determinant = function(){
        var mat = this.mat;
        var output = mat[0] * mat[4] * mat[8] + mat[1] * mat[5] * mat[6] + mat[2] * mat[3] * mat[7];
        output -= mat[2] * mat[4] * mat[6] + mat[0] * mat[5] * mat[7] + mat[1] * mat[3] * mat[8];
        return output;
    };
    _p.multiply = function(mat3){
        var m1 = this.mat, m2 = mat3.mat;
        var a0 = m1[0], a1 = m1[1], a2 = m1[2], a3 = m1[3], a4 = m1[4], a5 = m1[5],
            a6 = m1[6], a7 = m1[7], a8 = m1[8];
        var b0 = m2[0], b1 = m2[1], b2 = m2[2], b3 = m2[3], b4 = m2[4], b5 = m2[5],
            b6 = m2[6], b7 = m2[7], b8 = m2[8];
        m1[0] = a0 * b0 + a3 * b1 + a6 * b2;
        m1[1] = a1 * b0 + a4 * b1 + a7 * b2;
        m1[2] = a2 * b0 + a5 * b1 + a8 * b2;
        m1[3] = a2 * b0 + a5 * b1 + a8 * b2;
        m1[4] = a1 * b3 + a4 * b4 + a7 * b5;
        m1[5] = a2 * b3 + a5 * b4 + a8 * b5;
        m1[6] = a0 * b6 + a3 * b7 + a6 * b8;
        m1[7] = a1 * b6 + a4 * b7 + a7 * b8;
        m1[8] = a2 * b6 + a5 * b7 + a8 * b8;
        return this;
    };
    _p.multiplyScalar = function(factor) {
        var mat = this.mat;
        mat[0] *= factor;
        mat[1] *= factor;
        mat[2] *= factor;
        mat[3] *= factor;
        mat[4] *= factor;
        mat[5] *= factor;
        mat[6] *= factor;
        mat[7] *= factor;
        mat[8] *= factor;
        return this;
    };
    cc.math.Matrix3.rotationAxisAngle = function(axis, radians) {
        var rcos = Math.cos(radians), rsin = Math.sin(radians);
        var retMat = new cc.math.Matrix3();
        var mat = retMat.mat;
        mat[0] = rcos + axis.x * axis.x * (1 - rcos);
        mat[1] = axis.z * rsin + axis.y * axis.x * (1 - rcos);
        mat[2] = -axis.y * rsin + axis.z * axis.x * (1 - rcos);
        mat[3] = -axis.z * rsin + axis.x * axis.y * (1 - rcos);
        mat[4] = rcos + axis.y * axis.y * (1 - rcos);
        mat[5] = axis.x * rsin + axis.z * axis.y * (1 - rcos);
        mat[6] = axis.y * rsin + axis.x * axis.z * (1 - rcos);
        mat[7] = -axis.x * rsin + axis.y * axis.z * (1 - rcos);
        mat[8] = rcos + axis.z * axis.z * (1 - rcos);
        return retMat;
    };
    _p.assignFrom = function(matIn){
        if(this === matIn) {
            cc.log("cc.math.Matrix3.assign(): current matrix equals matIn");
            return this;
        }
        var mat = this.mat, m2 = matIn.mat;
        mat[0] = m2[0];
        mat[1] = m2[1];
        mat[2] = m2[2];
        mat[3] = m2[3];
        mat[4] = m2[4];
        mat[5] = m2[5];
        mat[6] = m2[6];
        mat[7] = m2[7];
        mat[8] = m2[8];
        return this;
    };
    _p.equals = function(mat3) {
        if (this === mat3)
            return true;
        var EPSILON = cc.math.EPSILON,m1 = this.mat, m2 = mat3.mat;
        for (var i = 0; i < 9; ++i) {
            if (!(m1[i] + EPSILON > m2[i] && m1[i] - EPSILON < m2[i]))
                return false;
        }
        return true;
    };
    cc.math.Matrix3.createByRotationX = function(radians) {
        var retMat = new cc.math.Matrix3(), mat = retMat.mat;
        mat[0] = 1.0;
        mat[1] = 0.0;
        mat[2] = 0.0;
        mat[3] = 0.0;
        mat[4] = Math.cos(radians);
        mat[5] = Math.sin(radians);
        mat[6] = 0.0;
        mat[7] = -Math.sin(radians);
        mat[8] = Math.cos(radians);
        return retMat;
    };
    cc.math.Matrix3.createByRotationY = function(radians) {
        var retMat = new cc.math.Matrix3(), mat = retMat.mat;
        mat[0] = Math.cos(radians);
        mat[1] = 0.0;
        mat[2] = -Math.sin(radians);
        mat[3] = 0.0;
        mat[4] = 1.0;
        mat[5] = 0.0;
        mat[6] = Math.sin(radians);
        mat[7] = 0.0;
        mat[8] = Math.cos(radians);
        return retMat;
    };
    cc.math.Matrix3.createByRotationZ = function(radians) {
        var retMat = new cc.math.Matrix3(), mat = retMat.mat;
        mat[0] = Math.cos(radians);
        mat[1] = -Math.sin(radians);
        mat[2] = 0.0;
        mat[3] = Math.sin(radians);
        mat[4] = Math.cos(radians);
        mat[5] = 0.0;
        mat[6] = 0.0;
        mat[7] = 0.0;
        mat[8] = 1.0;
        return retMat;
    };
    cc.math.Matrix3.createByRotation = function(radians) {
        var retMat = new cc.math.Matrix3(), mat = retMat.mat;
        mat[0] = Math.cos(radians);
        mat[1] = Math.sin(radians);
        mat[2] = 0.0;
        mat[3] = -Math.sin(radians);
        mat[4] = Math.cos(radians);
        mat[5] = 0.0;
        mat[6] = 0.0;
        mat[7] = 0.0;
        mat[8] = 1.0;
        return retMat;
    };
    cc.math.Matrix3.createByScale = function(x, y) {
        var ret = new cc.math.Matrix3();
        ret.identity();
        ret.mat[0] = x;
        ret.mat[4] = y;
        return ret;
    };
    cc.math.Matrix3.createByTranslation = function(x, y){
        var ret = new cc.math.Matrix3();
        ret.identity();
        ret.mat[6] = x;
        ret.mat[7] = y;
        return ret;
    };
    cc.math.Matrix3.createByQuaternion = function(quaternion) {
        if(!quaternion)
            return null;
        var ret = new cc.math.Matrix3(), mat = ret.mat;
        mat[0] = 1.0 - 2.0 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z);
        mat[1] = 2.0 * (quaternion.x * quaternion.y - quaternion.w * quaternion.z);
        mat[2] = 2.0 * (quaternion.x * quaternion.z + quaternion.w * quaternion.y);
        mat[3] = 2.0 * (quaternion.x * quaternion.y + quaternion.w * quaternion.z);
        mat[4] = 1.0 - 2.0 * (quaternion.x * quaternion.x + quaternion.z * quaternion.z);
        mat[5] = 2.0 * (quaternion.y * quaternion.z - quaternion.w * quaternion.x);
        mat[6] = 2.0 * (quaternion.x * quaternion.z - quaternion.w * quaternion.y);
        mat[7] = 2.0 * (quaternion.y * quaternion.z + quaternion.w * quaternion.x);
        mat[8] = 1.0 - 2.0 * (quaternion.x * quaternion.x + quaternion.y * quaternion.y);
        return ret;
    };
    _p.rotationToAxisAngle = function() {
        return cc.math.Quaternion.rotationMatrix(this).toAxisAndAngle();
    }
})(cc);
(function(cc) {
    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;
    proto.fill = function(scalarArr){
         var mat = this.mat;
        for(var i = 0; i < 16; i++){
            mat[i] = scalarArr[i];
        }
        return this;
    };
    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;
    };
    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 mat = this.mat, tmp = mat[r1 + 4 * c1];
        mat[r1 + 4 * c1] = mat[r2 + 4 * c2];
        mat[r2 + 4 * c2] = tmp;
    };
    cc.math.Matrix4._gaussj = function (a, b) {
        var i, icol = 0, irow = 0, j, k, l, ll, n = 4, m = 4, selElement;
        var big, dumb, pivinv;
        var indxc = [0, 0, 0, 0], indxr = [0, 0, 0, 0], ipiv = [0, 0, 0, 0];
        for (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++)
                    a.swap(irow, l, icol, l);
                for (l = 0; l < m; l++)
                    b.swap(irow, l, icol, l);
            }
            indxr[i] = irow;
            indxc[i] = icol;
            if (a.get(icol, icol) === 0.0)
                return false;
            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);
            for (l = 0; l < m; l++)
                b.set(icol, l, b.get(icol, l) * pivinv);
            for (ll = 0; ll < n; ll++) {
                if (ll !== icol) {
                    dumb = a.get(ll, icol);
                    a.set(ll, icol, 0.0);
                    for (l = 0; l < n; l++)
                        a.set(ll, l, a.get(ll, l) - a.get(icol, l) * dumb);
                    for (l = 0; l < m; l++)
                        b.set(ll, l, a.get(ll, l) - b.get(icol, l) * dumb);
                }
            }
        }
        for (l = n - 1; l >= 0; l--) {
            if (indxr[l] !== indxc[l]) {
                for (k = 0; k < n; k++)
                    a.swap(k, indxr[l], k, indxc[l]);
            }
        }
        return true;
    };
    var identityMatrix = new cc.math.Matrix4().identity();
    cc.kmMat4Inverse = function (pOut, pM) {
        var inv = new cc.math.Matrix4(pM);
        var tmp = new cc.math.Matrix4(identityMatrix);
        if (cc.math.Matrix4._gaussj(inv, tmp) === false)
            return null;
        pOut.assignFrom(inv);
        return pOut;
    };
    proto.inverse = function(){
        var inv = new cc.math.Matrix4(this);
        var tmp = new cc.math.Matrix4(identityMatrix);
        if (cc.math.Matrix4._gaussj(inv, tmp) === false)
            return null;
        return inv;
    };
    proto.isIdentity = function () {
        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);
    };
    proto.transpose = function() {
        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;
    };
    cc.kmMat4Multiply = function (pOut, pM1, pM2) {
        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;
    };
    proto.multiply = function(mat4){
        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;
    };
    cc.kmMat4Assign = function (pOut, pIn) {
        if (pOut === pIn) {
            cc.log("cc.kmMat4Assign(): pOut equals pIn");
            return pOut;
        }
        var outArr = pOut.mat;
        var inArr = pIn.mat;
        outArr[0] = inArr[0];
        outArr[1] = inArr[1];
        outArr[2] = inArr[2];
        outArr[3] = inArr[3];
        outArr[4] = inArr[4];
        outArr[5] = inArr[5];
        outArr[6] = inArr[6];
        outArr[7] = inArr[7];
        outArr[8] = inArr[8];
        outArr[9] = inArr[9];
        outArr[10] = inArr[10];
        outArr[11] = inArr[11];
        outArr[12] = inArr[12];
        outArr[13] = inArr[13];
        outArr[14] = inArr[14];
        outArr[15] = inArr[15];
        return pOut;
    };
    proto.assignFrom = function(mat4) {
        if (this === mat4) {
            cc.log("cc.mat.Matrix4.assignFrom(): mat4 equals current matrix");
            return this;
        }
        var outArr = this.mat, inArr = mat4.mat;
        outArr[0] = inArr[0];
        outArr[1] = inArr[1];
        outArr[2] = inArr[2];
        outArr[3] = inArr[3];
        outArr[4] = inArr[4];
        outArr[5] = inArr[5];
        outArr[6] = inArr[6];
        outArr[7] = inArr[7];
        outArr[8] = inArr[8];
        outArr[9] = inArr[9];
        outArr[10] = inArr[10];
        outArr[11] = inArr[11];
        outArr[12] = inArr[12];
        outArr[13] = inArr[13];
        outArr[14] = inArr[14];
        outArr[15] = inArr[15];
        return this;
    };
    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;
    };
    cc.math.Matrix4.createByRotationX = function(radians, matrix) {
        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;
    };
    cc.math.Matrix4.createByRotationY = function(radians, matrix) {
        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;
    };
    cc.math.Matrix4.createByRotationZ = function(radians, matrix){
        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;
    };
    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;
    };
    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;
        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;
        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;
        mat[14] = mat[13] = mat[12] = 0;
        mat[15] = 1.0;
        return matrix;
    };
    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;
    };
    cc.math.Matrix4.createByScale = function(x, y, z, matrix) {
        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;
    };
    cc.kmMat4Translation = function (pOut, x, y, z) {
        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;
    };
    cc.math.Matrix4.createByTranslation = function(x, y, z, matrix){
        matrix = matrix || new cc.math.Matrix4();
        matrix.identity();
        matrix.mat[12] = x;
        matrix.mat[13] = y;
        matrix.mat[14] = z;
        return matrix;
    };
    proto.getUpVec3 = function() {
        var mat = this.mat;
        var ret = new cc.math.Vec3(mat[4],mat[5], mat[6]);
        return ret.normalize();
    };
    proto.getRightVec3 = function(){
        var mat = this.mat;
        var ret = new cc.math.Vec3(mat[0],mat[1], mat[2]);
        return ret.normalize();
    };
    proto.getForwardVec3 = function() {
        var mat = this.mat;
        var ret = new cc.math.Vec3(mat[8],mat[9], mat[10]);
        return ret.normalize();
    };
    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;
        var cotangent = Math.cos(r) / s;
        pOut.identity();
        pOut.mat[0] = cotangent / aspect;
        pOut.mat[5] = cotangent;
        pOut.mat[10] = -(zFar + zNear) / deltaZ;
        pOut.mat[11] = -1;
        pOut.mat[14] = -2 * zNear * zFar / deltaZ;
        pOut.mat[15] = 0;
        return pOut;
    };
    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;
        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;
    };
    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;
    };
    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;
    };
    cc.kmMat4LookAt = function (pOut, pEye, pCenter, pUp) {
        var f = new cc.math.Vec3(pCenter), up = new cc.math.Vec3(pUp);
        f.subtract(pEye);
        f.normalize();
        up.normalize();
        var s = new cc.math.Vec3(f);
        s.cross(up);
        s.normalize();
        var u = new cc.math.Vec3(s);
        u.cross(f);
        s.normalize();
        pOut.identity();
        pOut.mat[0] = s.x;
        pOut.mat[4] = s.y;
        pOut.mat[8] = s.z;
        pOut.mat[1] = u.x;
        pOut.mat[5] = u.y;
        pOut.mat[9] = u.z;
        pOut.mat[2] = -f.x;
        pOut.mat[6] = -f.y;
        pOut.mat[10] = -f.z;
        var translate = cc.math.Matrix4.createByTranslation(-pEye.x, -pEye.y, -pEye.z);
        pOut.multiply(translate);
        return pOut;
    };
    var tempMatrix = new cc.math.Matrix4();
    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;
    };
    cc.kmMat4RotationAxisAngle = function (pOut, axis, radians) {
        var rcos = Math.cos(radians), rsin = Math.sin(radians);
        var normalizedAxis = new cc.math.Vec3(axis);
        normalizedAxis.normalize();
        pOut.mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
        pOut.mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
        pOut.mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
        pOut.mat[3] = 0.0;
        pOut.mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
        pOut.mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
        pOut.mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
        pOut.mat[7] = 0.0;
        pOut.mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
        pOut.mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
        pOut.mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
        pOut.mat[11] = 0.0;
        pOut.mat[12] = 0.0;
        pOut.mat[13] = 0.0;
        pOut.mat[14] = 0.0;
        pOut.mat[15] = 1.0;
        return pOut;
    };
    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;
    };
    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;
    };
    proto.toAxisAndAngle = function() {
        var rotation = this.extractRotation();
        var temp = cc.math.Quaternion.rotationMatrix(rotation);
        return temp.toAxisAndAngle();
    };
})(cc);
(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){
        return (this.a * vec4.x + this.b * vec4.y + this.c * vec4.z + this.d * vec4.w);
    };
    proto.dotCoord = function(vec3) {
        return (this.a * vec3.x + this.b * vec3.y + this.c * vec3.z + this.d);
    };
    proto.dotNormal = function(vec3) {
        return (this.a * vec3.x + this.b * vec3.y + this.c * vec3.z);
    };
    cc.math.Plane.fromPointNormal = function(vec3, normal) {
        return new cc.math.Plane(normal.x, normal.y, normal.z, -normal.dot(vec3));
    };
    cc.math.Plane.fromPoints = function(vec1, vec2, vec3) {
        var  v1 = new cc.math.Vec3(vec2), v2 = new cc.math.Vec3(vec3), plane = new cc.math.Plane();
        v1.subtract(vec1);
        v2.subtract(vec1);
        v1.cross(v2);
        v1.normalize();
        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(){
        var n = new cc.math.Vec3(this.a, this.b, this.c), l = 1.0 / n.length();
        n.normalize();
        this.a = n.x;
        this.b = n.y;
        this.c = n.z;
        this.d = this.d * l;
        return this;
    };
    proto.classifyPoint = function(vec3) {
        var distance = this.a * vec3.x + this.b * vec3.y + this.c * vec3.z + this.d;
        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);
(function(cc) {
    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 {
            this.x = x || 0;
            this.y = y || 0;
            this.z = z || 0;
            this.w = w || 0;
        }
    };
    cc.kmQuaternion = cc.math.Quaternion;
    var proto = cc.math.Quaternion.prototype;
    proto.conjugate = function (quaternion) {
        this.x = -quaternion.x;
        this.y = -quaternion.y;
        this.z = -quaternion.z;
        this.w = quaternion.w;
        return this;
    };
    proto.dot = function(quaternion) {
        return (this.w * quaternion.w + this.x * quaternion.x + this.y * quaternion.y + this.z * quaternion.z);
    };
    proto.exponential = function(){
        return this;
    };
    proto.identity = function(){
        this.x = 0.0;
        this.y = 0.0;
        this.z = 0.0;
        this.w = 1.0;
        return this;
    };
    proto.inverse = function(){
        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;
        }
        this.conjugate(this).scale(1.0 / len);
        return this;
    };
    proto.isIdentity = function(){
        return (this.x === 0.0 && this.y === 0.0 && this.z === 0.0 && this.w === 1.0);
    };
    proto.length = function() {
        return Math.sqrt(this.lengthSq());
    };
    proto.lengthSq = function() {
        return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
    };
    proto.multiply = function(quaternion) {
        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;
    };
    proto.normalize = function(){
        var length = this.length();
        if (Math.abs(length) <= cc.math.EPSILON)
            throw new Error("current quaternion is an invalid value");
        this.scale(1.0 / length);
        return this;
    };
    proto.rotationAxis = function(axis, angle){
        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;
    };
    cc.math.Quaternion.rotationMatrix = function (mat3) {
        if (!mat3)
            return null;
        var x, y, z, w;
        var m4x4 = [], mat = mat3.mat, scale = 0.0;
        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) {
            scale = Math.sqrt(diagonal) * 2;
            x = ( pMatrix[9] - pMatrix[6] ) / scale;
            y = ( pMatrix[2] - pMatrix[8] ) / scale;
            z = ( pMatrix[4] - pMatrix[1] ) / scale;
            w = 0.25 * scale;
        } else {
            if (pMatrix[0] > pMatrix[5] && pMatrix[0] > pMatrix[10]) {
                scale = Math.sqrt(1.0 + pMatrix[0] - pMatrix[5] - pMatrix[10]) * 2.0;
                x = 0.25 * scale;
                y = (pMatrix[4] + pMatrix[1] ) / scale;
                z = (pMatrix[2] + pMatrix[8] ) / scale;
                w = (pMatrix[9] - pMatrix[6] ) / scale;
            }
            else if (pMatrix[5] > pMatrix[10]) {
                scale = Math.sqrt(1.0 + pMatrix[5] - pMatrix[0] - pMatrix[10]) * 2.0;
                x = (pMatrix[4] + pMatrix[1] ) / scale;
                y = 0.25 * scale;
                z = (pMatrix[9] + pMatrix[6] ) / scale;
                w = (pMatrix[2] - pMatrix[8] ) / scale;
            } else {
                scale = Math.sqrt(1.0 + pMatrix[10] - pMatrix[0] - pMatrix[5]) * 2.0;
                x = (pMatrix[2] + pMatrix[8] ) / scale;
                y = (pMatrix[9] + pMatrix[6] ) / scale;
                z = 0.25 * scale;
                w = (pMatrix[4] - pMatrix[1] ) / scale;
            }
        }
        return new cc.math.Quaternion(x, y, z, w);
    };
    cc.math.Quaternion.rotationYawPitchRoll = function (yaw, pitch, roll) {
        var ex, ey, ez;
        var cr, cp, cy, sr, sp, sy, cpcy, spsy;
        ex = cc.degreesToRadians(pitch) / 2.0;
        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;
    };
    proto.slerp = function(quaternion, t) {
        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;
    };
    proto.toAxisAndAngle = function(){
        var tempAngle;
        var scale;
        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)) {
            retAngle = 0.0;
            retAxis.x = 0.0;
            retAxis.y = 0.0;
            retAxis.z = 1.0;
        } else {
            retAngle = tempAngle * 2.0;
            retAxis.x = this.x / scale;
            retAxis.y = this.y / scale;
            retAxis.z = this.z / scale;
            retAxis.normalize();
        }
         return {axis: retAxis, angle: retAngle};
    };
    proto.scale = function(scale) {
        this.x *= scale;
        this.y *= scale;
        this.z *= scale;
        this.w *= scale;
        return this;
    };
    proto.assignFrom = function(quaternion){
        this.x = quaternion.x;
        this.y = quaternion.y;
        this.z = quaternion.z;
        this.w = quaternion.w;
        return this;
    };
    proto.add = function(quaternion) {
        this.x += quaternion.x;
        this.y += quaternion.y;
        this.z += quaternion.z;
        this.w += quaternion.w;
        return this;
    };
    cc.math.Quaternion.rotationBetweenVec3 = function(vec1, vec2, fallback) {
        var v1 = new cc.math.Vec3(vec1), v2 = new cc.math.Vec3(vec2);
        v1.normalize();
        v2.normalize();
        var a = v1.dot(v2), quaternion = new cc.math.Quaternion();
        if (a >= 1.0) {
            quaternion.identity();
            return quaternion;
        }
        if (a < (1e-6 - 1.0)) {
            if (Math.abs(fallback.lengthSq()) < cc.math.EPSILON) {
                quaternion.rotationAxis(fallback, Math.PI);
            } else {
                var axis = new cc.math.Vec3(1.0, 0.0, 0.0);
                axis.cross(vec1);
                if (Math.abs(axis.lengthSq()) < cc.math.EPSILON) {
                    axis.fill(0.0, 1.0, 0.0);
                    axis.cross(vec1);
                }
                axis.normalize();
                quaternion.rotationAxis(axis, Math.PI);
            }
        } else {
            var s = Math.sqrt((1 + a) * 2), invs = 1 / s;
            v1.cross(v2);
            quaternion.x = v1.x * invs;
            quaternion.y = v1.y * invs;
            quaternion.z = v1.z * invs;
            quaternion.w = s * 0.5;
            quaternion.normalize();
        }
        return quaternion;
    };
    proto.multiplyVec3 = function(vec){
        var x = this.x, y = this.y, z = this.z, retVec = new cc.math.Vec3(vec);
        var uv = new cc.math.Vec3(x, y, z), uuv = new cc.math.Vec3(x, y, z);
        uv.cross(vec);
        uuv.cross(uv);
        uv.scale((2.0 * q.w));
        uuv.scale(2.0);
        retVec.add(uv);
        retVec.add(uuv);
        return retVec;
    };
})(cc);
cc.math.AABB = function (min, max) {
    this.min = min || new cc.math.Vec3();
    this.max = max || new cc.math.Vec3();
};
cc.math.AABB.prototype.containsPoint = function (point) {
    return (point.x >= this.min.x && point.x <= this.max.x &&
    point.y >= this.min.y && point.y <= this.max.y &&
    point.z >= this.min.z && point.z <= this.max.z);
};
cc.math.AABB.containsPoint = function (pPoint, pBox) {
    return (pPoint.x >= pBox.min.x && pPoint.x <= pBox.max.x &&
        pPoint.y >= pBox.min.y && pPoint.y <= pBox.max.y &&
        pPoint.z >= pBox.min.z && pPoint.z <= pBox.max.z);
};
cc.math.AABB.prototype.assignFrom = function(aabb){
    this.min.assignFrom(aabb.min);
    this.max.assignFrom(aabb.max);
};
cc.math.AABB.assign = function (pOut, pIn) {
    pOut.min.assignFrom(pIn.min);
    pOut.max.assignFrom(pIn.max);
    return pOut;
};
(function(cc){
    cc.math.Matrix4Stack = function(top, stack) {
        this.top = top;
        this.stack = stack || [];
    };
    cc.km_mat4_stack = cc.math.Matrix4Stack;
    var proto = cc.math.Matrix4Stack.prototype;
    proto.initialize = function() {
        this.stack.length = 0;
        this.top = null;
    };
    cc.km_mat4_stack_push = function(stack, item){
        stack.stack.push(stack.top);
        stack.top = new cc.math.Matrix4(item);
    };
    cc.km_mat4_stack_pop = function(stack, pOut){
        stack.top = stack.stack.pop();
    };
    cc.km_mat4_stack_release = function(stack){
        stack.stack = null;
        stack.top = null;
    };
    proto.push = function(item) {
        item = item || this.top;
        this.stack.push(this.top);
        this.top = new cc.math.Matrix4(item);
    };
    proto.pop = function() {
        this.top = this.stack.pop();
    };
    proto.release = function(){
        this.stack = null;
        this.top = null;
        this._matrixPool = null;
    };
    proto._getFromPool = function (item) {
        var pool = this._matrixPool;
        if (pool.length === 0)
            return new cc.math.Matrix4(item);
        var ret = pool.pop();
        ret.assignFrom(item);
        return ret;
    };
    proto._putInPool = function(matrix){
        this._matrixPool.push(matrix);
    };
})(cc);
(function(cc) {
    cc.KM_GL_MODELVIEW = 0x1700;
    cc.KM_GL_PROJECTION = 0x1701;
    cc.KM_GL_TEXTURE = 0x1702;
    cc.modelview_matrix_stack = new cc.math.Matrix4Stack();
    cc.projection_matrix_stack = new cc.math.Matrix4Stack();
    cc.texture_matrix_stack = new cc.math.Matrix4Stack();
    cc.current_stack = null;
    var initialized = false;
    cc.lazyInitialize = function () {
        if (!initialized) {
            var identity = new cc.math.Matrix4();
            cc.modelview_matrix_stack.initialize();
            cc.projection_matrix_stack.initialize();
            cc.texture_matrix_stack.initialize();
            cc.current_stack = cc.modelview_matrix_stack;
            cc.initialized = true;
            identity.identity();
            cc.modelview_matrix_stack.push(identity);
            cc.projection_matrix_stack.push(identity);
            cc.texture_matrix_stack.push(identity);
        }
    };
    cc.lazyInitialize();
    cc.kmGLFreeAll = function () {
        cc.modelview_matrix_stack.release();
        cc.modelview_matrix_stack = null;
        cc.projection_matrix_stack.release();
        cc.projection_matrix_stack = null;
        cc.texture_matrix_stack.release();
        cc.texture_matrix_stack = null;
        cc.initialized = false;
        cc.current_stack = null;
    };
    cc.kmGLPushMatrix = function () {
        cc.current_stack.push(cc.current_stack.top);
    };
    cc.kmGLPushMatrixWitMat4 = function (saveMat) {
        cc.current_stack.stack.push(cc.current_stack.top);
        saveMat.assignFrom(cc.current_stack.top);
        cc.current_stack.top = saveMat;
    };
    cc.kmGLPopMatrix = function () {
        cc.current_stack.top = cc.current_stack.stack.pop();
    };
    cc.kmGLMatrixMode = function (mode) {
        switch (mode) {
            case cc.KM_GL_MODELVIEW:
                cc.current_stack = cc.modelview_matrix_stack;
                break;
            case cc.KM_GL_PROJECTION:
                cc.current_stack = cc.projection_matrix_stack;
                break;
            case cc.KM_GL_TEXTURE:
                cc.current_stack = cc.texture_matrix_stack;
                break;
            default:
                throw new Error("Invalid matrix mode specified");
                break;
        }
    };
    cc.kmGLLoadIdentity = function () {
        cc.current_stack.top.identity();
    };
    cc.kmGLLoadMatrix = function (pIn) {
        cc.current_stack.top.assignFrom(pIn);
    };
    cc.kmGLMultMatrix = function (pIn) {
        cc.current_stack.top.multiply(pIn);
    };
    var tempMatrix = new cc.math.Matrix4();
    cc.kmGLTranslatef = function (x, y, z) {
        var translation = cc.math.Matrix4.createByTranslation(x, y, z, tempMatrix);
        cc.current_stack.top.multiply(translation);
    };
    var tempVector3 = new cc.math.Vec3();
    cc.kmGLRotatef = function (angle, x, y, z) {
        tempVector3.fill(x, y, z);
        var rotation = cc.math.Matrix4.createByAxisAndAngle(tempVector3, cc.degreesToRadians(angle), tempMatrix);
        cc.current_stack.top.multiply(rotation);
    };
    cc.kmGLScalef = function (x, y, z) {
        var scaling = cc.math.Matrix4.createByScale(x, y, z, tempMatrix);
        cc.current_stack.top.multiply(scaling);
    };
    cc.kmGLGetMatrix = function (mode, pOut) {
        switch (mode) {
            case cc.KM_GL_MODELVIEW:
                pOut.assignFrom(cc.modelview_matrix_stack.top);
                break;
            case cc.KM_GL_PROJECTION:
                pOut.assignFrom(cc.projection_matrix_stack.top);
                break;
            case cc.KM_GL_TEXTURE:
                pOut.assignFrom(cc.texture_matrix_stack.top);
                break;
            default:
                throw new Error("Invalid matrix mode specified");
                break;
        }
    };
})(cc);
//-----------------------Shader_Position_uColor Shader Source--------------------------
cc.SHADER_POSITION_UCOLOR_FRAG =
        "precision lowp float;\n"
        + "varying vec4 v_fragmentColor;\n"
        + "void main()                              \n"
        + "{ \n"
        + "    gl_FragColor = v_fragmentColor;      \n"
        + "}\n";
cc.SHADER_POSITION_UCOLOR_VERT =
        "attribute vec4 a_position;\n"
        + "uniform    vec4 u_color;\n"
        + "uniform float u_pointSize;\n"
        + "varying lowp vec4 v_fragmentColor; \n"
        + "void main(void)   \n"
        + "{\n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    gl_PointSize = u_pointSize;          \n"
        + "    v_fragmentColor = u_color;           \n"
        + "}";
cc.SHADER_POSITION_COLOR_FRAG =
        "precision lowp float; \n"
        + "varying vec4 v_fragmentColor; \n"
        + "void main() \n"
        + "{ \n"
        + "     gl_FragColor = v_fragmentColor; \n"
        + "} ";
cc.SHADER_POSITION_COLOR_VERT =
        "attribute vec4 a_position;\n"
        + "attribute vec4 a_color;\n"
        + "varying lowp vec4 v_fragmentColor;\n"
        + "void main()\n"
        + "{\n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    v_fragmentColor = a_color;             \n"
        + "}";
cc.SHADER_SPRITE_POSITION_COLOR_VERT =
        "attribute vec4 a_position;\n"
        + "attribute vec4 a_color;\n"
        + "varying lowp vec4 v_fragmentColor;\n"
        + "void main()\n"
        + "{\n"
        + "    gl_Position = CC_PMatrix * a_position;  \n"
        + "    v_fragmentColor = a_color;             \n"
        + "}";
cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_FRAG =
        "// #extension GL_OES_standard_derivatives : enable\n"
        + "varying mediump vec4 v_color;\n"
        + "varying mediump vec2 v_texcoord;\n"
        + "void main()    \n"
        + "{ \n"
        + "// #if defined GL_OES_standard_derivatives    \n"
        + "// gl_FragColor = v_color*smoothstep(0.0, length(fwidth(v_texcoord)), 1.0 - length(v_texcoord)); \n"
        + "// #else    \n"
        + "gl_FragColor = v_color * step(0.0, 1.0 - length(v_texcoord)); \n"
        + "// #endif \n"
        + "}";
cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_VERT =
        "attribute mediump vec4 a_position; \n"
        + "attribute mediump vec2 a_texcoord; \n"
        + "attribute mediump vec4 a_color;    \n"
        + "varying mediump vec4 v_color; \n"
        + "varying mediump vec2 v_texcoord;    \n"
        + "void main() \n"
        + "{ \n"
        + "     v_color = a_color;//vec4(a_color.rgb * a_color.a, a_color.a); \n"
        + "     v_texcoord = a_texcoord; \n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_FRAG =
        "precision lowp float;   \n"
        + "varying vec2 v_texCoord;  \n"
        + "void main() \n"
        + "{  \n"
        + "    gl_FragColor =  texture2D(CC_Texture0, v_texCoord);   \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_VERT =
        "attribute vec4 a_position; \n"
        + "attribute vec2 a_texCoord; \n"
        + "varying mediump vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    v_texCoord = a_texCoord;               \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_UCOLOR_FRAG =
        "precision lowp float;  \n"
        + "uniform vec4 u_color; \n"
        + "varying vec2 v_texCoord; \n"
        + "void main() \n"
        + "{  \n"
        + "    gl_FragColor =  texture2D(CC_Texture0, v_texCoord) * u_color;    \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_UCOLOR_VERT =
        "attribute vec4 a_position;\n"
        + "attribute vec2 a_texCoord; \n"
        + "varying mediump vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    v_texCoord = a_texCoord;                 \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_A8COLOR_FRAG =
        "precision lowp float;  \n"
        + "varying vec4 v_fragmentColor; \n"
        + "varying vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_FragColor = vec4( v_fragmentColor.rgb,         \n"
        + "        v_fragmentColor.a * texture2D(CC_Texture0, v_texCoord).a   \n"
        + "    ); \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_A8COLOR_VERT =
        "attribute vec4 a_position; \n"
        + "attribute vec2 a_texCoord; \n"
        + "attribute vec4 a_color;  \n"
        + "varying lowp vec4 v_fragmentColor; \n"
        + "varying mediump vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    v_fragmentColor = a_color; \n"
        + "    v_texCoord = a_texCoord; \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_COLOR_FRAG =
        "precision lowp float;\n"
        + "varying vec4 v_fragmentColor; \n"
        + "varying vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_COLOR_VERT =
        "attribute vec4 a_position; \n"
        + "attribute vec2 a_texCoord; \n"
        + "attribute vec4 a_color;  \n"
        + "varying lowp vec4 v_fragmentColor; \n"
        + "varying mediump vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;  \n"
        + "    v_fragmentColor = a_color; \n"
        + "    v_texCoord = a_texCoord; \n"
        + "}";
cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT =
        "attribute vec4 a_position; \n"
        + "attribute vec2 a_texCoord; \n"
        + "attribute vec4 a_color;  \n"
        + "varying lowp vec4 v_fragmentColor; \n"
        + "varying mediump vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    gl_Position = CC_PMatrix * a_position;  \n"
        + "    v_fragmentColor = a_color; \n"
        + "    v_texCoord = a_texCoord; \n"
        + "}";
cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG =
        "precision lowp float;   \n"
        + "varying vec4 v_fragmentColor; \n"
        + "varying vec2 v_texCoord;   \n"
        + "uniform float CC_alpha_value; \n"
        + "void main() \n"
        + "{  \n"
        + "    vec4 texColor = texture2D(CC_Texture0, v_texCoord);  \n"
        + "    if ( texColor.a <= CC_alpha_value )          \n"
        + "        discard; \n"
        + "    gl_FragColor = texColor * v_fragmentColor;  \n"
        + "}";
cc.SHADEREX_SWITCHMASK_FRAG =
        "precision lowp float; \n"
        + "varying vec4 v_fragmentColor; \n"
        + "varying vec2 v_texCoord; \n"
        + "uniform sampler2D u_texture;  \n"
        + "uniform sampler2D   u_mask;   \n"
        + "void main()  \n"
        + "{  \n"
        + "    vec4 texColor   = texture2D(u_texture, v_texCoord);  \n"
        + "    vec4 maskColor  = texture2D(u_mask, v_texCoord); \n"
        + "    vec4 finalColor = vec4(texColor.r, texColor.g, texColor.b, maskColor.a * texColor.a);        \n"
        + "    gl_FragColor    = v_fragmentColor * finalColor; \n"
        + "}";
cc.shaderCache = {
    TYPE_POSITION_TEXTURECOLOR: 0,
    TYPE_POSITION_TEXTURECOLOR_ALPHATEST: 1,
    TYPE_POSITION_COLOR: 2,
    TYPE_POSITION_TEXTURE: 3,
    TYPE_POSITION_TEXTURE_UCOLOR: 4,
    TYPE_POSITION_TEXTURE_A8COLOR: 5,
    TYPE_POSITION_UCOLOR: 6,
    TYPE_POSITION_LENGTH_TEXTURECOLOR: 7,
    TYPE_SPRITE_POSITION_TEXTURECOLOR: 8,
    TYPE_SPRITE_POSITION_TEXTURECOLOR_ALPHATEST: 9,
    TYPE_SPRITE_POSITION_COLOR: 10,
    TYPE_MAX: 10,
    _programs: {},
    _init: function () {
        this.loadDefaultShaders();
        return true;
    },
    _loadDefaultShader: function (program, type) {
        switch (type) {
            case this.TYPE_POSITION_TEXTURECOLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_SPRITE_POSITION_TEXTURECOLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_POSITION_TEXTURECOLOR_ALPHATEST:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_SPRITE_POSITION_TEXTURECOLOR_ALPHATEST:
                program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_POSITION_COLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_COLOR_VERT, cc.SHADER_POSITION_COLOR_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                break;
            case this.TYPE_SPRITE_POSITION_COLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_COLOR_VERT, cc.SHADER_POSITION_COLOR_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                break;
            case this.TYPE_POSITION_TEXTURE:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_VERT, cc.SHADER_POSITION_TEXTURE_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_POSITION_TEXTURE_UCOLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_UCOLOR_VERT, cc.SHADER_POSITION_TEXTURE_UCOLOR_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_POSITION_TEXTURE_A8COLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_A8COLOR_VERT, cc.SHADER_POSITION_TEXTURE_A8COLOR_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                break;
            case this.TYPE_POSITION_UCOLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_UCOLOR_VERT, cc.SHADER_POSITION_UCOLOR_FRAG);
                program.addAttribute("aVertex", cc.VERTEX_ATTRIB_POSITION);
                break;
            case this.TYPE_POSITION_LENGTH_TEXTURECOLOR:
                program.initWithVertexShaderByteArray(cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_VERT, cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_FRAG);
                program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
                program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
                program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
                break;
            default:
                cc.log("cocos2d: cc.shaderCache._loadDefaultShader, error shader type");
                return;
        }
        program.link();
        program.updateUniforms();
    },
    loadDefaultShaders: function () {
        var program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURECOLOR);
        this._programs[cc.SHADER_POSITION_TEXTURECOLOR] = program;
        this._programs["ShaderPositionTextureColor"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_SPRITE_POSITION_TEXTURECOLOR);
        this._programs[cc.SHADER_SPRITE_POSITION_TEXTURECOLOR] = program;
        this._programs["ShaderSpritePositionTextureColor"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURECOLOR_ALPHATEST);
        this._programs[cc.SHADER_POSITION_TEXTURECOLORALPHATEST] = program;
        this._programs["ShaderPositionTextureColorAlphaTest"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_SPRITE_POSITION_TEXTURECOLOR_ALPHATEST);
        this._programs[cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST] = program;
        this._programs["ShaderSpritePositionTextureColorAlphaTest"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_COLOR);
        this._programs[cc.SHADER_POSITION_COLOR] = program;
        this._programs["ShaderPositionColor"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_SPRITE_POSITION_COLOR);
        this._programs[cc.SHADER_SPRITE_POSITION_COLOR] = program;
        this._programs["ShaderSpritePositionColor"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURE);
        this._programs[cc.SHADER_POSITION_TEXTURE] = program;
        this._programs["ShaderPositionTexture"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURE_UCOLOR);
        this._programs[cc.SHADER_POSITION_TEXTURE_UCOLOR] = program;
        this._programs["ShaderPositionTextureUColor"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURE_A8COLOR);
        this._programs[cc.SHADER_POSITION_TEXTUREA8COLOR] = program;
        this._programs["ShaderPositionTextureA8Color"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_UCOLOR);
        this._programs[cc.SHADER_POSITION_UCOLOR] = program;
        this._programs["ShaderPositionUColor"] = program;
        program = new cc.GLProgram();
        this._loadDefaultShader(program, this.TYPE_POSITION_LENGTH_TEXTURECOLOR);
        this._programs[cc.SHADER_POSITION_LENGTHTEXTURECOLOR] = program;
        this._programs["ShaderPositionLengthTextureColor"] = program;
    },
    reloadDefaultShaders: function () {
        var program = this.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURECOLOR);
        program = this.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_SPRITE_POSITION_TEXTURECOLOR);
        program = this.programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURECOLOR_ALPHATEST);
        program = this.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_SPRITE_POSITION_TEXTURECOLOR_ALPHATEST);
        program = this.programForKey(cc.SHADER_POSITION_COLOR);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_COLOR);
        program = this.programForKey(cc.SHADER_POSITION_TEXTURE);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURE);
        program = this.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURE_UCOLOR);
        program = this.programForKey(cc.SHADER_POSITION_TEXTUREA8COLOR);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_TEXTURE_A8COLOR);
        program = this.programForKey(cc.SHADER_POSITION_UCOLOR);
        program.reset();
        this._loadDefaultShader(program, this.TYPE_POSITION_UCOLOR);
    },
    programForKey: function (key) {
        return this._programs[key];
    },
    getProgram: function (shaderName) {
        return this._programs[shaderName];
    },
    addProgram: function (program, key) {
        this._programs[key] = program;
    }
};
cc.GLProgram = cc.Class.extend({
    _glContext: null,
    _programObj: null,
    _vertShader: null,
    _fragShader: null,
    _uniforms: null,
    _hashForUniforms: null,
    _usesTime: false,
    _updateUniformLocation: function (location) {
        if (!location)
            return false;
        var updated;
        var element = this._hashForUniforms[location];
        if (!element) {
            element = [
                arguments[1],
                arguments[2],
                arguments[3],
                arguments[4]
            ];
            this._hashForUniforms[location] = element;
            updated = true;
        } else {
            updated = false;
            var count = arguments.length-1;
            for (var i = 0; i < count; ++i) {
                if (arguments[i+1] !== element[i]) {
                    element[i] = arguments[i+1];
                    updated = true;
                }
            }
        }
        return updated;
    },
    _description: function () {
        return "<CCGLProgram = " + this.toString() + " | Program = " + this._programObj.toString() + ", VertexShader = " +
            this._vertShader.toString() + ", FragmentShader = " + this._fragShader.toString() + ">";
    },
    _compileShader: function (shader, type, source) {
        if (!source || !shader)
            return false;
        var preStr = cc.GLProgram._isHighpSupported() ? "precision highp float;\n" : "precision mediump float;\n";
        source = preStr
            + "uniform mat4 CC_PMatrix;         \n"
            + "uniform mat4 CC_MVMatrix;        \n"
            + "uniform mat4 CC_MVPMatrix;       \n"
            + "uniform vec4 CC_Time;            \n"
            + "uniform vec4 CC_SinTime;         \n"
            + "uniform vec4 CC_CosTime;         \n"
            + "uniform vec4 CC_Random01;        \n"
            + "uniform sampler2D CC_Texture0;   \n"
            + "//CC INCLUDES END                \n" + source;
        this._glContext.shaderSource(shader, source);
        this._glContext.compileShader(shader);
        var status = this._glContext.getShaderParameter(shader, this._glContext.COMPILE_STATUS);
        if (!status) {
            cc.log("cocos2d: ERROR: Failed to compile shader:\n" + this._glContext.getShaderSource(shader));
            if (type === this._glContext.VERTEX_SHADER)
                cc.log("cocos2d: \n" + this.vertexShaderLog());
            else
                cc.log("cocos2d: \n" + this.fragmentShaderLog());
        }
        return ( status === true );
    },
    ctor: function (vShaderFileName, fShaderFileName, glContext) {
        this._uniforms = {};
        this._hashForUniforms = {};
        this._glContext = glContext || cc._renderContext;
        vShaderFileName && fShaderFileName && this.init(vShaderFileName, fShaderFileName);
    },
    destroyProgram: function () {
        this._vertShader = null;
        this._fragShader = null;
        this._uniforms = null;
        this._hashForUniforms = null;
        this._glContext.deleteProgram(this._programObj);
    },
    initWithVertexShaderByteArray: function (vertShaderStr, fragShaderStr) {
        var locGL = this._glContext;
        this._programObj = locGL.createProgram();
        this._vertShader = null;
        this._fragShader = null;
        if (vertShaderStr) {
            this._vertShader = locGL.createShader(locGL.VERTEX_SHADER);
            if (!this._compileShader(this._vertShader, locGL.VERTEX_SHADER, vertShaderStr)) {
                cc.log("cocos2d: ERROR: Failed to compile vertex shader");
            }
        }
        if (fragShaderStr) {
            this._fragShader = locGL.createShader(locGL.FRAGMENT_SHADER);
            if (!this._compileShader(this._fragShader, locGL.FRAGMENT_SHADER, fragShaderStr)) {
                cc.log("cocos2d: ERROR: Failed to compile fragment shader");
            }
        }
        if (this._vertShader)
            locGL.attachShader(this._programObj, this._vertShader);
        cc.checkGLErrorDebug();
        if (this._fragShader)
            locGL.attachShader(this._programObj, this._fragShader);
        for (var key in this._hashForUniforms) {
            delete this._hashForUniforms[key];
        }
        cc.checkGLErrorDebug();
        return true;
    },
    initWithString: function (vertShaderStr, fragShaderStr) {
        return this.initWithVertexShaderByteArray(vertShaderStr, fragShaderStr);
    },
    initWithVertexShaderFilename: function (vShaderFilename, fShaderFileName) {
        var vertexSource = cc.loader.getRes(vShaderFilename);
        if(!vertexSource) throw new Error("Please load the resource firset : " + vShaderFilename);
        var fragmentSource = cc.loader.getRes(fShaderFileName);
        if(!fragmentSource) throw new Error("Please load the resource firset : " + fShaderFileName);
        return this.initWithVertexShaderByteArray(vertexSource, fragmentSource);
    },
    init: function (vShaderFilename, fShaderFileName) {
        return this.initWithVertexShaderFilename(vShaderFilename, fShaderFileName);
    },
    addAttribute: function (attributeName, index) {
        this._glContext.bindAttribLocation(this._programObj, index, attributeName);
    },
    link: function () {
        if(!this._programObj) {
            cc.log("cc.GLProgram.link(): Cannot link invalid program");
            return false;
        }
        this._glContext.linkProgram(this._programObj);
        if (this._vertShader)
            this._glContext.deleteShader(this._vertShader);
        if (this._fragShader)
            this._glContext.deleteShader(this._fragShader);
        this._vertShader = null;
        this._fragShader = null;
        if (cc.game.config[cc.game.CONFIG_KEY.debugMode]) {
            var status = this._glContext.getProgramParameter(this._programObj, this._glContext.LINK_STATUS);
            if (!status) {
                cc.log("cocos2d: ERROR: Failed to link program: " + this._glContext.getProgramInfoLog(this._programObj));
                cc.glDeleteProgram(this._programObj);
                this._programObj = null;
                return false;
            }
        }
        return true;
    },
    use: function () {
        cc.glUseProgram(this._programObj);
    },
    updateUniforms: function () {
        this._uniforms[cc.UNIFORM_PMATRIX_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_PMATRIX_S);
        this._uniforms[cc.UNIFORM_MVMATRIX_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVMATRIX_S);
        this._uniforms[cc.UNIFORM_MVPMATRIX_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVPMATRIX_S);
        this._uniforms[cc.UNIFORM_TIME_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_TIME_S);
        this._uniforms[cc.UNIFORM_SINTIME_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SINTIME_S);
        this._uniforms[cc.UNIFORM_COSTIME_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_COSTIME_S);
        this._usesTime = (this._uniforms[cc.UNIFORM_TIME_S] != null || this._uniforms[cc.UNIFORM_SINTIME_S] != null || this._uniforms[cc.UNIFORM_COSTIME_S] != null);
        this._uniforms[cc.UNIFORM_RANDOM01_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_RANDOM01_S);
        this._uniforms[cc.UNIFORM_SAMPLER_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SAMPLER_S);
        this.use();
        this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER_S], 0);
    },
    _addUniformLocation: function (name) {
        var location = this._glContext.getUniformLocation(this._programObj, name);
        this._uniforms[name] = location;
    },
    getUniformLocationForName: function (name) {
        if (!name)
            throw new Error("cc.GLProgram.getUniformLocationForName(): uniform name should be non-null");
        if (!this._programObj)
            throw new Error("cc.GLProgram.getUniformLocationForName(): Invalid operation. Cannot get uniform location when program is not initialized");
        var location = this._uniforms[name] || this._glContext.getUniformLocation(this._programObj, name);
        return location;
    },
    getUniformMVPMatrix: function () {
        return this._uniforms[cc.UNIFORM_MVPMATRIX_S];
    },
    getUniformSampler: function () {
        return this._uniforms[cc.UNIFORM_SAMPLER_S];
    },
    setUniformLocationWith1i: function (location, i1) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, i1);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform1i(locObj, i1);
            }
        }
        else {
            gl.uniform1i(location, i1);
        }
    },
    setUniformLocationWith2i: function (location, i1, i2) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, i1, i2);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform2i(locObj, i1, i2);
            }
        }
        else {
            gl.uniform2i(location, i1, i2);
        }
    },
    setUniformLocationWith3i: function (location, i1, i2, i3) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, i1, i2, i3);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform3i(locObj, i1, i2, i3);
            }
        }
        else {
            gl.uniform3i(location, i1, i2, i3);
        }
    },
    setUniformLocationWith4i: function (location, i1, i2, i3, i4) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, i1, i2, i3, i4);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform4i(locObj, i1, i2, i3, i4);
            }
        }
        else {
            gl.uniform4i(location, i1, i2, i3, i4);
        }
    },
    setUniformLocationWith2iv: function (location, intArray) {
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniform2iv(locObj, intArray);
    },
    setUniformLocationWith3iv:function(location, intArray){
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniform3iv(locObj, intArray);
    },
    setUniformLocationWith4iv:function(location, intArray){
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniform4iv(locObj, intArray);
    },
    setUniformLocationI32: function (location, i1) {
        this.setUniformLocationWith1i(location, i1);
    },
    setUniformLocationWith1f: function (location, f1) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, f1);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform1f(locObj, f1);
            }
        }
        else {
            gl.uniform1f(location, f1);
        }
    },
    setUniformLocationWith2f: function (location, f1, f2) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, f1, f2);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform2f(locObj, f1, f2);
            }
        }
        else {
            gl.uniform2f(location, f1, f2);
        }
    },
    setUniformLocationWith3f: function (location, f1, f2, f3) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, f1, f2, f3);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform3f(locObj, f1, f2, f3);
            }
        }
        else {
            gl.uniform3f(location, f1, f2, f3);
        }
    },
    setUniformLocationWith4f: function (location, f1, f2, f3, f4) {
        var gl = this._glContext;
        if (typeof location === 'string') {
            var updated = this._updateUniformLocation(location, f1, f2, f3, f4);
            if (updated) {
                var locObj = this.getUniformLocationForName(location);
                gl.uniform4f(locObj, f1, f2, f3, f4);
            }
        }
        else {
            gl.uniform4f(location, f1, f2, f3, f4);
        }
    },
    setUniformLocationWith2fv: function (location, floatArray) {
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniform2fv(locObj, floatArray);
    },
    setUniformLocationWith3fv: function (location, floatArray) {
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniform3fv(locObj, floatArray);
    },
    setUniformLocationWith4fv: function (location, floatArray) {
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniform4fv(locObj, floatArray);
    },
    setUniformLocationWithMatrix4fv: function (location, matrixArray) {
        var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location;
        this._glContext.uniformMatrix4fv(locObj, false, matrixArray);
    },
    setUniformLocationF32: function () {
        if (arguments.length < 2)
            return;
        switch (arguments.length) {
            case 2:
                this.setUniformLocationWith1f(arguments[0], arguments[1]);
                break;
            case 3:
                this.setUniformLocationWith2f(arguments[0], arguments[1], arguments[2]);
                break;
            case 4:
                this.setUniformLocationWith3f(arguments[0], arguments[1], arguments[2], arguments[3]);
                break;
            case 5:
                this.setUniformLocationWith4f(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
                break;
        }
    },
    setUniformsForBuiltins: function () {
        var matrixP = new cc.math.Matrix4();
        var matrixMV = new cc.math.Matrix4();
        var matrixMVP = new cc.math.Matrix4();
        cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP);
        cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, matrixMV);
        cc.kmMat4Multiply(matrixMVP, matrixP, matrixMV);
        this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], matrixP.mat, 1);
        this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], matrixMV.mat, 1);
        this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], matrixMVP.mat, 1);
        if (this._usesTime) {
            var director = cc.director;
            var time = director.getTotalFrames() * director.getAnimationInterval();
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME_S], time / 10.0, time, time * 2, time * 4);
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.sin(time));
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.cos(time));
        }
        if (this._uniforms[cc.UNIFORM_RANDOM01_S] !== -1)
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01_S], Math.random(), Math.random(), Math.random(), Math.random());
    },
    _setUniformsForBuiltinsForRenderer: function (node) {
        if(!node || !node._renderCmd)
            return;
        var matrixP = new cc.math.Matrix4();
        var matrixMVP = new cc.math.Matrix4();
        cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP);
        cc.kmMat4Multiply(matrixMVP, matrixP, node._renderCmd._stackMatrix);
        this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], matrixP.mat, 1);
        this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], node._renderCmd._stackMatrix.mat, 1);
        this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], matrixMVP.mat, 1);
        if (this._usesTime) {
            var director = cc.director;
            var time = director.getTotalFrames() * director.getAnimationInterval();
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME_S], time / 10.0, time, time * 2, time * 4);
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.sin(time));
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.cos(time));
        }
        if (this._uniforms[cc.UNIFORM_RANDOM01_S] !== -1)
            this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01_S], Math.random(), Math.random(), Math.random(), Math.random());
    },
    setUniformForModelViewProjectionMatrix: function () {
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], false,
        cc.getMat4MultiplyValue(cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top));
    },
    setUniformForModelViewProjectionMatrixWithMat4: function (swapMat4) {
        cc.kmMat4Multiply(swapMat4, cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top);
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], false, swapMat4.mat);
    },
    setUniformForModelViewAndProjectionMatrixWithMat4: function () {
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], false, cc.modelview_matrix_stack.top.mat);
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], false, cc.projection_matrix_stack.top.mat);
    },
    _setUniformForMVPMatrixWithMat4: function(modelViewMatrix){
        if(!modelViewMatrix)
            throw new Error("modelView matrix is undefined.");
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], false, modelViewMatrix.mat);
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], false, cc.projection_matrix_stack.top.mat);
    },
    _updateProjectionUniform: function(){
        this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], false, cc.projection_matrix_stack.top.mat);
    },
    vertexShaderLog: function () {
        return this._glContext.getShaderInfoLog(this._vertShader);
    },
    getVertexShaderLog: function () {
        return this._glContext.getShaderInfoLog(this._vertShader);
    },
    getFragmentShaderLog: function () {
        return this._glContext.getShaderInfoLog(this._vertShader);
    },
    fragmentShaderLog: function () {
        return this._glContext.getShaderInfoLog(this._fragShader);
    },
    programLog: function () {
        return this._glContext.getProgramInfoLog(this._programObj);
    },
    getProgramLog: function () {
        return this._glContext.getProgramInfoLog(this._programObj);
    },
    reset: function () {
        this._vertShader = null;
        this._fragShader = null;
        this._uniforms.length = 0;
        this._glContext.deleteProgram(this._programObj);
        this._programObj = null;
        for (var key in this._hashForUniforms) {
            this._hashForUniforms[key].length = 0;
            delete this._hashForUniforms[key];
        }
    },
    getProgram: function () {
        return this._programObj;
    },
    retain: function () {
    },
    release: function () {
    }
});
cc.GLProgram.create = function (vShaderFileName, fShaderFileName) {
    return new cc.GLProgram(vShaderFileName, fShaderFileName);
};
cc.GLProgram._highpSupported = null;
cc.GLProgram._isHighpSupported = function(){
    if(cc.GLProgram._highpSupported == null){
        var ctx = cc._renderContext;
        var highp = ctx.getShaderPrecisionFormat(ctx.FRAGMENT_SHADER, ctx.HIGH_FLOAT);
        cc.GLProgram._highpSupported = highp.precision !== 0;
    }
    return cc.GLProgram._highpSupported;
};
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);
};
cc._currentProjectionMatrix = -1;
if (cc.ENABLE_GL_STATE_CACHE) {
    cc.MAX_ACTIVETEXTURE = 16;
    cc._currentShaderProgram = -1;
    cc._currentBoundTexture = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
    cc._blendingSource = -1;
    cc._blendingDest = -1;
    cc._GLServerState = 0;
    if(cc.TEXTURE_ATLAS_USE_VAO)
        cc._uVAO = 0;
    var _currBuffers = {};
    WebGLRenderingContext.prototype.glBindBuffer = WebGLRenderingContext.prototype.bindBuffer;
    WebGLRenderingContext.prototype.bindBuffer = function (target, buffer) {
        if (_currBuffers[target] !== buffer) {
            this.glBindBuffer(target, buffer);
            _currBuffers[target] = buffer;
            return false;
        }
        else {
            return true;
        }
    };
    WebGLRenderingContext.prototype.glEnableVertexAttribArray = WebGLRenderingContext.prototype.enableVertexAttribArray;
    WebGLRenderingContext.prototype.enableVertexAttribArray = function (index) {
        if (index === cc.VERTEX_ATTRIB_FLAG_POSITION) {
            if (!this._vertexAttribPosition) {
                this.glEnableVertexAttribArray(index);
                this._vertexAttribPosition = true;
            }
        }
        else if (index === cc.VERTEX_ATTRIB_FLAG_COLOR) {
            if (!this._vertexAttribColor) {
                this.glEnableVertexAttribArray(index);
                this._vertexAttribColor = true;
            }
        }
        else if (index === cc.VERTEX_ATTRIB_FLAG_TEX_COORDS) {
            if (!this._vertexAttribTexCoords) {
                this.glEnableVertexAttribArray(index);
                this._vertexAttribTexCoords = true;
            }
        }
        else {
            this.glEnableVertexAttribArray(index);
        }
    };
    WebGLRenderingContext.prototype.glDisableVertexAttribArray = WebGLRenderingContext.prototype.disableVertexAttribArray;
    WebGLRenderingContext.prototype.disableVertexAttribArray = function (index) {
        if (index === cc.VERTEX_ATTRIB_FLAG_COLOR) {
            if (this._vertexAttribColor) {
                this.glDisableVertexAttribArray(index);
                this._vertexAttribColor = false;
            }
        }
        else if (index === cc.VERTEX_ATTRIB_FLAG_TEX_COORDS) {
            if (this._vertexAttribTexCoords) {
                this.glDisableVertexAttribArray(index);
                this._vertexAttribTexCoords = false;
            }
        }
        else if (index !== 0) {
            this.glDisableVertexAttribArray(index);
        }
    };
}
cc.glInvalidateStateCache = function () {
    cc.kmGLFreeAll();
    cc._currentProjectionMatrix = -1;
    if (cc.ENABLE_GL_STATE_CACHE) {
        cc._currentShaderProgram = -1;
        for (var i = 0; i < cc.MAX_ACTIVETEXTURE; i++) {
            cc._currentBoundTexture[i] = -1;
        }
        cc._blendingSource = -1;
        cc._blendingDest = -1;
        cc._GLServerState = 0;
    }
};
cc.glUseProgram = cc.ENABLE_GL_STATE_CACHE ? function (program) {
    if (program !== cc._currentShaderProgram) {
        cc._currentShaderProgram = program;
        cc._renderContext.useProgram(program);
    }
} : function (program) {
    cc._renderContext.useProgram(program);
};
cc.glDeleteProgram = function (program) {
    if (cc.ENABLE_GL_STATE_CACHE) {
        if (program === cc._currentShaderProgram)
            cc._currentShaderProgram = -1;
    }
    gl.deleteProgram(program);
};
cc.setBlending = function (sfactor, dfactor) {
    var ctx = cc._renderContext;
    if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) {
        ctx.disable(ctx.BLEND);
    } else {
        ctx.enable(ctx.BLEND);
        cc._renderContext.blendFunc(sfactor,dfactor);
    }
};
cc.glBlendFunc = cc.ENABLE_GL_STATE_CACHE ? function (sfactor, dfactor) {
    if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) {
        cc._blendingSource = sfactor;
        cc._blendingDest = dfactor;
        cc.setBlending(sfactor, dfactor);
    }
} : cc.setBlending;
cc.glBlendFuncForParticle = function(sfactor, dfactor) {
    if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) {
        cc._blendingSource = sfactor;
        cc._blendingDest = dfactor;
        var ctx = cc._renderContext;
        if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) {
            ctx.disable(ctx.BLEND);
        } else {
            ctx.enable(ctx.BLEND);
            ctx.blendFuncSeparate(ctx.SRC_ALPHA, dfactor, sfactor, dfactor);
        }
    }
};
cc.glBlendResetToCache = function () {
    var ctx = cc._renderContext;
    ctx.blendEquation(ctx.FUNC_ADD);
    if (cc.ENABLE_GL_STATE_CACHE)
        cc.setBlending(cc._blendingSource, cc._blendingDest);
    else
        cc.setBlending(ctx.BLEND_SRC, ctx.BLEND_DST);
};
cc.setProjectionMatrixDirty = function () {
    cc._currentProjectionMatrix = -1;
};
cc.glBindTexture2D = function (textureId) {
    cc.glBindTexture2DN(0, textureId);
};
cc.glBindTexture2DN = cc.ENABLE_GL_STATE_CACHE ? function (textureUnit, textureId) {
    if (cc._currentBoundTexture[textureUnit] === textureId)
        return;
    cc._currentBoundTexture[textureUnit] = textureId;
    var ctx = cc._renderContext;
    ctx.activeTexture(ctx.TEXTURE0 + textureUnit);
    if(textureId)
        ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj);
    else
        ctx.bindTexture(ctx.TEXTURE_2D, null);
} : function (textureUnit, textureId) {
    var ctx = cc._renderContext;
    ctx.activeTexture(ctx.TEXTURE0 + textureUnit);
    if(textureId)
        ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj);
    else
        ctx.bindTexture(ctx.TEXTURE_2D, null);
};
cc.glDeleteTexture = function (textureId) {
    cc.glDeleteTextureN(0, textureId);
};
cc.glDeleteTextureN = function (textureUnit, textureId) {
    if (cc.ENABLE_GL_STATE_CACHE) {
        if (textureId === cc._currentBoundTexture[ textureUnit ])
            cc._currentBoundTexture[ textureUnit ] = -1;
    }
    cc._renderContext.deleteTexture(textureId._webTextureObj);
};
cc.glBindVAO = function (vaoId) {
    if (!cc.TEXTURE_ATLAS_USE_VAO)
        return;
    if (cc.ENABLE_GL_STATE_CACHE) {
        if (cc._uVAO !== vaoId) {
            cc._uVAO = vaoId;
        }
    } else {
    }
};
cc.glEnable = function (flags) {
    if (cc.ENABLE_GL_STATE_CACHE) {
    } else {
    }
};
cc.IMAGE_FORMAT_JPEG = 0;
cc.IMAGE_FORMAT_PNG = 1;
cc.IMAGE_FORMAT_RAWDATA = 9;
cc.NextPOT = function (x) {
    x = x - 1;
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);
    return x + 1;
};
cc.RenderTexture = cc.Node.extend({
    sprite:null,
    clearFlags:0,
    clearDepthVal:0,
    autoDraw:false,
    _texture:null,
    _pixelFormat:0,
    clearStencilVal:0,
    _clearColor:null,
    _className:"RenderTexture",
    ctor: function(width, height, format, depthStencilFormat){
        cc.Node.prototype.ctor.call(this);
        this._cascadeColorEnabled = true;
        this._cascadeOpacityEnabled = true;
        this._pixelFormat = cc.Texture2D.PIXEL_FORMAT_RGBA8888;
        this._clearColor = new cc.Color(0,0,0,255);
        if(width !== undefined && height !== undefined) {
            format = format || cc.Texture2D.PIXEL_FORMAT_RGBA8888;
            depthStencilFormat = depthStencilFormat || 0;
            this.initWithWidthAndHeight(width, height, format, depthStencilFormat);
        }
        this.setAnchorPoint(0,0);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.RenderTexture.CanvasRenderCmd(this);
        else
            return new cc.RenderTexture.WebGLRenderCmd(this);
    },
    cleanup: function(){
        cc.Node.prototype.onExit.call(this);
        this._renderCmd.cleanup();
    },
    getSprite:function () {
        return this.sprite;
    },
    setSprite:function (sprite) {
        this.sprite = sprite;
    },
    setVirtualViewport: function(rtBegin, fullRect, fullViewport){
         this._renderCmd.setVirtualViewport(rtBegin, fullRect, fullViewport);
    },
    initWithWidthAndHeight: function(width, height, format, depthStencilFormat){
        return this._renderCmd.initWithWidthAndHeight(width, height, format, depthStencilFormat);
    },
    begin: function(){
        cc.renderer._turnToCacheMode(this.__instanceId);
        this._renderCmd.begin();
    },
    beginWithClear:function (r, g, b, a, depthValue, stencilValue) {
        var gl = cc._renderContext;
        depthValue = depthValue || gl.COLOR_BUFFER_BIT;
        stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        this._beginWithClear(r , g , b , a , depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
    },
    _beginWithClear: function(r, g, b, a, depthValue, stencilValue, flags){
        this.begin();
        this._renderCmd._beginWithClear(r, g, b, a, depthValue, stencilValue, flags);
    },
    end: function(){
        this._renderCmd.end();
    },
    clear:function (r, g, b, a) {
        this.beginWithClear(r, g, b, a);
        this.end();
    },
    clearRect: function(x, y, width, height){
        this._renderCmd.clearRect(x, y, width, height);
    },
    clearDepth: function(depthValue){
        this._renderCmd.clearDepth(depthValue);
    },
    clearStencil: function(stencilValue) {
        this._renderCmd.clearStencil(stencilValue);
    },
    getClearFlags:function () {
        return this.clearFlags;
    },
    setClearFlags:function (clearFlags) {
        this.clearFlags = clearFlags;
    },
    getClearColor:function () {
        return this._clearColor;
    },
    setClearColor: function(clearColor){
        var locClearColor = this._clearColor;
        locClearColor.r = clearColor.r;
        locClearColor.g = clearColor.g;
        locClearColor.b = clearColor.b;
        locClearColor.a = clearColor.a;
        this._renderCmd.updateClearColor(clearColor);
    },
    getClearDepth:function () {
        return this.clearDepthVal;
    },
    setClearDepth:function (clearDepth) {
        this.clearDepthVal = clearDepth;
    },
    getClearStencil:function () {
        return this.clearStencilVal;
    },
    setClearStencil:function (clearStencil) {
        this.clearStencilVal = clearStencil;
    },
    isAutoDraw:function () {
        return this.autoDraw;
    },
    setAutoDraw:function (autoDraw) {
        this.autoDraw = autoDraw;
    },
    saveToFile:function (filePath, format) {
        cc.log("saveToFile isn't supported on Cocos2d-Html5");
    },
    newCCImage:function(flipImage){
        cc.log("saveToFile isn't supported on cocos2d-html5");
        return null;
    },
    listenToBackground:function (obj) { },
    listenToForeground:function (obj) { }
});
var _p = cc.RenderTexture.prototype;
_p.clearColorVal;
cc.defineGetterSetter(_p, "clearColorVal", _p.getClearColor, _p.setClearColor);
cc.RenderTexture.create = function (width, height, format, depthStencilFormat) {
    return new cc.RenderTexture(width, height, format, depthStencilFormat);
};
(function(){
    cc.RenderTexture.CanvasRenderCmd = function(renderableObject){
        cc.Node.CanvasRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._clearColorStr = "rgba(255,255,255,1)";
        this._cacheCanvas = document.createElement('canvas');
        this._cacheContext = new cc.CanvasContextWrapper(this._cacheCanvas.getContext('2d'));
    };
    var proto = cc.RenderTexture.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.RenderTexture.CanvasRenderCmd;
    proto.cleanup = function(){
        this._cacheContext = null;
        this._cacheCanvas = null;
    };
    proto.clearStencil = function (stencilValue) { };
    proto.setVirtualViewport = function(rtBegin, fullRect, fullViewport) {};
    proto.updateClearColor = function(clearColor){
        this._clearColorStr = "rgba(" + (0 | clearColor.r) + "," + (0 | clearColor.g) + "," + (0 | clearColor.b) + "," + clearColor.a / 255 + ")";
    };
    proto.initWithWidthAndHeight = function(width, height, format, depthStencilFormat){
        var node = this._node;
        var locCacheCanvas = this._cacheCanvas, locScaleFactor = cc.contentScaleFactor();
        locCacheCanvas.width = 0 | (width * locScaleFactor);
        locCacheCanvas.height = 0 | (height * locScaleFactor);
        var texture = new cc.Texture2D();
        texture.initWithElement(locCacheCanvas);
        texture.handleLoadedTexture();
        var locSprite = node.sprite = new cc.Sprite(texture);
        locSprite.setBlendFunc(cc.ONE, cc.ONE_MINUS_SRC_ALPHA);
        node.autoDraw = false;
        node.addChild(locSprite);
        return true;
    };
    proto.begin = function(){};
    proto._beginWithClear = function(r, g, b, a, depthValue, stencilValue, flags){
        r = r || 0;
        g = g || 0;
        b = b || 0;
        a = isNaN(a) ? 255 : a;
        var context = this._cacheContext.getContext();
        var locCanvas = this._cacheCanvas;
        context.setTransform(1,0,0,1,0,0);
        this._cacheContext.setFillStyle("rgba(" + (0 | r) + "," + (0 | g) + "," + (0 | b) + "," + a / 255 + ")");
        context.clearRect(0, 0, locCanvas.width, locCanvas.height);
        context.fillRect(0, 0, locCanvas.width, locCanvas.height);
    };
    proto.end = function(){
        var node = this._node;
        var scale = cc.contentScaleFactor();
        cc.renderer._renderingToCacheCanvas(this._cacheContext, node.__instanceId, scale, scale);
        var spriteRenderCmd = node.sprite._renderCmd;
        spriteRenderCmd._notifyRegionStatus && spriteRenderCmd._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
    };
    proto.clearRect = function(x, y, width, height){
        this._cacheContext.clearRect(x, y, width, -height);
    };
    proto.clearDepth = function(depthValue){
        cc.log("clearDepth isn't supported on Cocos2d-Html5");
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        this._syncStatus(parentCmd);
        node.sprite.visit(this);
        this._dirtyFlag = 0;
    };
})();
(function(){
    cc.RenderTexture.WebGLRenderCmd = function(renderableObject){
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._fBO = null;
        this._oldFBO = null;
        this._textureCopy = null;
        this._depthRenderBuffer = null;
        this._rtTextureRect = new cc.Rect();
        this._fullRect = new cc.Rect();
        this._fullViewport = new cc.Rect();
    };
    var proto = cc.RenderTexture.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.RenderTexture.WebGLRenderCmd;
    proto.setVirtualViewport = function(rtBegin, fullRect, fullViewport) {
        this._rtTextureRect.x = rtBegin.x;
        this._rtTextureRect.y = rtBegin.y;
        this._fullRect = fullRect;
        this._fullViewport = fullViewport;
    };
    proto.needDraw = function () {
        return this._needDraw && this._node.autoDraw;
    };
    proto.rendering = function (ctx) {
        var gl = ctx || cc._renderContext;
        var node = this._node;
        if (node.autoDraw) {
            node.begin();
            var locClearFlags = node.clearFlags;
            if (locClearFlags) {
                var oldClearColor = [0.0, 0.0, 0.0, 0.0];
                var oldDepthClearValue = 0.0;
                var oldStencilClearValue = 0;
                if (locClearFlags & gl.COLOR_BUFFER_BIT) {
                    oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
                    gl.clearColor(node._clearColor.r / 255, node._clearColor.g / 255, node._clearColor.b / 255, node._clearColor.a / 255);
                }
                if (locClearFlags & gl.DEPTH_BUFFER_BIT) {
                    oldDepthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
                    gl.clearDepth(node.clearDepthVal);
                }
                if (locClearFlags & gl.STENCIL_BUFFER_BIT) {
                    oldStencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
                    gl.clearStencil(node.clearStencilVal);
                }
                gl.clear(locClearFlags);
                if (locClearFlags & gl.COLOR_BUFFER_BIT)
                    gl.clearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);
                if (locClearFlags & gl.DEPTH_BUFFER_BIT)
                    gl.clearDepth(oldDepthClearValue);
                if (locClearFlags & gl.STENCIL_BUFFER_BIT)
                    gl.clearStencil(oldStencilClearValue);
            }
            node.sortAllChildren();
            var locChildren = node._children;
            for (var i = 0; i < locChildren.length; i++) {
                var getChild = locChildren[i];
                if (getChild !== node.sprite){
                    getChild._renderCmd.visit(node.sprite._renderCmd);
                }
            }
            node.end();
        }
    };
    proto.clearStencil = function(stencilValue) {
        var gl = cc._renderContext;
        var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
        gl.clearStencil(stencilValue);
        gl.clear(gl.STENCIL_BUFFER_BIT);
        gl.clearStencil(stencilClearValue);
    };
    proto.cleanup = function(){
        var node = this._node;
        this._textureCopy = null;
        var gl = cc._renderContext;
        gl.deleteFramebuffer(this._fBO);
        if (this._depthRenderBuffer)
            gl.deleteRenderbuffer(this._depthRenderBuffer);
    };
    proto.updateClearColor = function(clearColor){ };
    proto.initWithWidthAndHeight = function(width, height, format, depthStencilFormat){
        var node = this._node;
        if(format === cc.Texture2D.PIXEL_FORMAT_A8)
            cc.log( "cc.RenderTexture._initWithWidthAndHeightForWebGL() : only RGB and RGBA formats are valid for a render texture;");
        var gl = cc._renderContext, locScaleFactor = cc.contentScaleFactor();
        this._fullRect = new cc.Rect(0,0, width, height);
        this._fullViewport = new cc.Rect(0,0, width, height);
        width = 0 | (width * locScaleFactor);
        height = 0 | (height * locScaleFactor);
        this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
        var powW , powH;
        if (cc.configuration.supportsNPOT()) {
            powW = width;
            powH = height;
        } else {
            powW = cc.NextPOT(width);
            powH = cc.NextPOT(height);
        }
        var dataLen = powW * powH * 4;
        var data = new Uint8Array(dataLen);
        for (var i = 0; i < powW * powH * 4; i++)
            data[i] = 0;
        this._pixelFormat = format;
        var locTexture = node._texture = new cc.Texture2D();
        if (!node._texture)
            return false;
        locTexture.initWithData(data, node._pixelFormat, powW, powH, cc.size(width, height));
        var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING);
        if (cc.configuration.checkForGLExtension("GL_QCOM")) {
            this._textureCopy = new cc.Texture2D();
            if (!this._textureCopy)
                return false;
            this._textureCopy.initWithData(data, node._pixelFormat, powW, powH, cc.size(width, height));
        }
        this._fBO = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, locTexture._webTextureObj, 0);
        if (depthStencilFormat !== 0) {
            this._depthRenderBuffer = gl.createRenderbuffer();
            gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer);
            gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH);
            if(depthStencilFormat === gl.DEPTH_STENCIL)
                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
            else if(depthStencilFormat === gl.STENCIL_INDEX || depthStencilFormat === gl.STENCIL_INDEX8)
                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
            else if(depthStencilFormat === gl.DEPTH_COMPONENT16)
                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
        }
        if(gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE)
            cc.log("Could not attach texture to the framebuffer");
        locTexture.setAliasTexParameters();
        var locSprite = node.sprite = new cc.Sprite(locTexture);
        locSprite.scaleY = -1;
        locSprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
        gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO);
        gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
        node.autoDraw = false;
        node.addChild(locSprite);
        return true;
    };
    proto.begin = function(){
        var node = this._node;
        cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
        cc.kmGLPushMatrix();
        cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
        cc.kmGLPushMatrix();
        var gl = cc._renderContext;
        var director = cc.director;
        director.setProjection(director.getProjection());
        var texSize = node._texture.getContentSizeInPixels();
        var size = cc.director.getWinSizeInPixels();
        var widthRatio = size.width / texSize.width;
        var heightRatio = size.height / texSize.height;
        var orthoMatrix = cc.math.Matrix4.createOrthographicProjection(-1.0 / widthRatio, 1.0 / widthRatio,
            -1.0 / heightRatio, 1.0 / heightRatio, -1, 1);
        cc.kmGLMultMatrix(orthoMatrix);
        var viewport = new cc.Rect(0, 0, 0, 0);
        viewport.width = this._fullViewport.width;
        viewport.height = this._fullViewport.height;
        var viewPortRectWidthRatio = viewport.width / this._fullRect.width;
        var viewPortRectHeightRatio = viewport.height / this._fullRect.height;
        viewport.x = (this._fullRect.x - this._rtTextureRect.x) * viewPortRectWidthRatio;
        viewport.y = (this._fullRect.y - this._rtTextureRect.y) * viewPortRectHeightRatio;
        gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
        this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
        gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);//Will direct drawing to the frame buffer created above
        if (cc.configuration.checkForGLExtension("GL_QCOM")) {
            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._textureCopy._webTextureObj, 0);
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, node._texture._webTextureObj, 0);
        }
    };
    proto._beginWithClear = function(r, g, b, a, depthValue, stencilValue, flags){
        r = r / 255;
        g = g / 255;
        b = b / 255;
        a = a / 255;
        var gl = cc._renderContext;
        var clearColor = [0.0, 0.0, 0.0, 0.0];
        var depthClearValue = 0.0;
        var stencilClearValue = 0;
        if (flags & gl.COLOR_BUFFER_BIT) {
            clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
            gl.clearColor(r, g, b, a);
        }
        if (flags & gl.DEPTH_BUFFER_BIT) {
            depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
            gl.clearDepth(depthValue);
        }
        if (flags & gl.STENCIL_BUFFER_BIT) {
            stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
            gl.clearStencil(stencilValue);
        }
        gl.clear(flags);
        if (flags & gl.COLOR_BUFFER_BIT)
            gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
        if (flags & gl.DEPTH_BUFFER_BIT)
            gl.clearDepth(depthClearValue);
        if (flags & gl.STENCIL_BUFFER_BIT)
            gl.clearStencil(stencilClearValue);
    };
    proto.end = function(){
        var node = this._node;
        cc.renderer._renderingToBuffer(node.__instanceId);
        var gl = cc._renderContext;
        var director = cc.director;
        gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
        director.setViewport();
        cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
        cc.kmGLPopMatrix();
        cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
        cc.kmGLPopMatrix();
    };
    proto.clearRect = function(x, y, width, height){
    };
    proto.clearDepth = function(depthValue){
        var node = this._node;
        node.begin();
        var gl = cc._renderContext;
        var depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
        gl.clearDepth(depthValue);
        gl.clear(gl.DEPTH_BUFFER_BIT);
        gl.clearDepth(depthClearValue);
        node.end();
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        cc.kmGLPushMatrix();
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this);
        node.sprite.visit(this);
        this._dirtyFlag = 0;
        cc.kmGLPopMatrix();
    };
})();
cc.SpriteBatchNode = cc.Node.extend({
    _blendFunc: null,
    _texture: null,
    _className: "SpriteBatchNode",
    ctor: function (fileImage) {
        cc.Node.prototype.ctor.call(this);
        this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
        var texture2D;
        if (cc.isString(fileImage)) {
            texture2D = cc.textureCache.getTextureForKey(fileImage);
            if (!texture2D)
                texture2D = cc.textureCache.addImage(fileImage);
        }else if (fileImage instanceof cc.Texture2D)
            texture2D = fileImage;
        texture2D && this.initWithTexture(texture2D);
    },
    addSpriteWithoutQuad: function (child, z, aTag) {
        this.addChild(child, z, aTag);
        return this;
    },
    getTextureAtlas: function () {
        return null;
    },
    setTextureAtlas: function (textureAtlas) {},
    getDescendants: function () {
        return this._children;
    },
    initWithFile: function (fileImage, capacity) {
        var texture2D = cc.textureCache.getTextureForKey(fileImage);
        if (!texture2D)
            texture2D = cc.textureCache.addImage(fileImage);
        return this.initWithTexture(texture2D, capacity);
    },
    init: function (fileImage, capacity) {
        var texture2D = cc.textureCache.getTextureForKey(fileImage);
        if (!texture2D)
            texture2D = cc.textureCache.addImage(fileImage);
        return this.initWithTexture(texture2D, capacity);
    },
    increaseAtlasCapacity: function () {},
    removeChildAtIndex: function (index, doCleanup) {
        this.removeChild(this._children[index], doCleanup);
    },
    rebuildIndexInOrder: function (pobParent, index) {
        return index;
    },
    highestAtlasIndexInChild: function (sprite) {
        var children = sprite.children;
        if (!children || children.length === 0)
            return sprite.zIndex;
        else
            return this.highestAtlasIndexInChild(children[children.length - 1]);
    },
    lowestAtlasIndexInChild: function (sprite) {
        var children = sprite.children;
        if (!children || children.length === 0)
            return sprite.zIndex;
        else
            return this.lowestAtlasIndexInChild(children[children.length - 1]);
    },
    atlasIndexForChild: function (sprite) {
        return sprite.zIndex;
    },
    reorderBatch: function (reorder) {
        this._reorderChildDirty = reorder;
    },
    setBlendFunc: function (src, dst) {
        if (dst === undefined)
            this._blendFunc = src;
        else
            this._blendFunc = {src: src, dst: dst};
    },
    getBlendFunc: function () {
        return new cc.BlendFunc(this._blendFunc.src,this._blendFunc.dst);
    },
    updateQuadFromSprite: function (sprite, index) {
        cc.assert(sprite, cc._LogInfos.CCSpriteBatchNode_updateQuadFromSprite_2);
        if (!(sprite instanceof cc.Sprite)) {
            cc.log(cc._LogInfos.CCSpriteBatchNode_updateQuadFromSprite);
            return;
        }
        sprite.dirty = true;
        sprite._renderCmd.transform(this._renderCmd, true);
    },
    insertQuadFromSprite: function (sprite, index) {
        this.addChild(sprite, index);
    },
    insertChild: function (sprite, index) {
        this.addChild(sprite, index);
    },
    appendChild: function (sprite) {
        this.sortAllChildren();
        var lastLocalZOrder = this._children[this._children.length-1]._localZOrder;
        this.addChild(sprite. lastLocalZOrder + 1);
    },
    removeSpriteFromAtlas: function (sprite, cleanup) {
        this.removeChild(sprite, cleanup);
    },
    initWithTexture: function (tex) {
        this.setTexture(tex);
        return true;
    },
    getTexture: function () {
        return this._texture;
    },
    setTexture: function(texture){
        this._texture = texture;
        if (texture._textureLoaded) {
            var children = this._children, i, len = children.length;
            for (i = 0; i < len; ++i) {
                children[i].setTexture(texture);
            }
        }
        else {
            texture.addEventListener("load", function(){
                var children = this._children, i, len = children.length;
                for (i = 0; i < len; ++i) {
                    children[i].setTexture(texture);
                }
            }, this);
        }
    },
    setShaderProgram: function (newShaderProgram) {
        this._renderCmd.setShaderProgram(newShaderProgram);
        var children = this._children, i, len = children.length;
        for (i = 0; i < len; ++i) {
            children[i].setShaderProgram(newShaderProgram);
        }
    },
    addChild: function (child, zOrder, tag) {
        cc.assert(child !== undefined, cc._LogInfos.CCSpriteBatchNode_addChild_3);
        if(!this._isValidChild(child))
            return;
        zOrder = (zOrder === undefined) ? child.zIndex : zOrder;
        tag = (tag === undefined) ? child.tag : tag;
        cc.Node.prototype.addChild.call(this, child, zOrder, tag);
        if (this._renderCmd._shaderProgram) {
            child.shaderProgram = this._renderCmd._shaderProgram;
        }
    },
    _isValidChild: function (child) {
        if (!(child instanceof cc.Sprite)) {
            cc.log(cc._LogInfos.Sprite_addChild_4);
            return false;
        }
        if (child.texture !== this._texture) {
            cc.log(cc._LogInfos.Sprite_addChild_5);
            return false;
        }
        return true;
    }
});
var _p = cc.SpriteBatchNode.prototype;
cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
cc.defineGetterSetter(_p, "shaderProgram", _p.getShaderProgram, _p.setShaderProgram);
cc.SpriteBatchNode.create = function (fileImage) {
    return new cc.SpriteBatchNode(fileImage);
};
cc.SpriteBatchNode.createWithTexture = cc.SpriteBatchNode.create;
cc.LabelAtlas = cc.AtlasNode.extend({
    _string: null,
    _mapStartChar: null,
    _textureLoaded: false,
    _className: "LabelAtlas",
    ctor: function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
        cc.AtlasNode.prototype.ctor.call(this);
        this._renderCmd.setCascade();
        charMapFile && cc.LabelAtlas.prototype.initWithString.call(this, strText, charMapFile, itemWidth, itemHeight, startCharMap);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new cc.LabelAtlas.WebGLRenderCmd(this);
        else
            return new cc.LabelAtlas.CanvasRenderCmd(this);
    },
    textureLoaded: function () {
        return this._textureLoaded;
    },
    addLoadedEventListener: function (callback, target) {
        this.addEventListener("load", callback, target);
    },
    initWithString: function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
        var label = strText + "", textureFilename, width, height, startChar;
        if (itemWidth === undefined) {
            var dict = cc.loader.getRes(charMapFile);
            if (parseInt(dict["version"], 10) !== 1) {
                cc.log("cc.LabelAtlas.initWithString(): Unsupported version. Upgrade cocos2d version");
                return false;
            }
            textureFilename = cc.path.changeBasename(charMapFile, dict["textureFilename"]);
            var locScaleFactor = cc.contentScaleFactor();
            width = parseInt(dict["itemWidth"], 10) / locScaleFactor;
            height = parseInt(dict["itemHeight"], 10) / locScaleFactor;
            startChar = String.fromCharCode(parseInt(dict["firstChar"], 10));
        } else {
            textureFilename = charMapFile;
            width = itemWidth || 0;
            height = itemHeight || 0;
            startChar = startCharMap || " ";
        }
        var texture = null;
        if (textureFilename instanceof cc.Texture2D)
            texture = textureFilename;
        else
            texture = cc.textureCache.addImage(textureFilename);
        var locLoaded = texture.isLoaded();
        this._textureLoaded = locLoaded;
        if (!locLoaded) {
            this._string = label;
            texture.addEventListener("load", function (sender) {
                this.initWithTexture(texture, width, height, label.length);
                this.string = this._string;
                this.setColor(this._renderCmd._displayedColor);
                this.dispatchEvent("load");
            }, this);
        }
        if (this.initWithTexture(texture, width, height, label.length)) {
            this._mapStartChar = startChar;
            this.string = label;
            return true;
        }
        return false;
    },
    setColor: function (color3) {
        cc.AtlasNode.prototype.setColor.call(this, color3);
        this._renderCmd.updateAtlasValues();
    },
    getString: function () {
        return this._string;
    },
    addChild: function(child, localZOrder, tag){
        this._renderCmd._addChild(child);
        cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
    },
    updateAtlasValues: function(){
        this._renderCmd.updateAtlasValues();
    },
    setString: function(label){
        label = String(label);
        var len = label.length;
        this._string = label;
        this.setContentSize(len * this._itemWidth, this._itemHeight);
        this._renderCmd.setString(label);
        this._renderCmd.updateAtlasValues();
        this.quadsToDraw = len;
    }
});
(function(){
    var proto = cc.LabelAtlas.prototype;
    cc.defineGetterSetter(proto, "opacity", proto.getOpacity, proto.setOpacity);
    cc.defineGetterSetter(proto, "color", proto.getColor, proto.setColor);
    proto.string;
    cc.defineGetterSetter(proto, "string", proto.getString, proto.setString);
})();
cc.LabelAtlas.create = function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
    return new cc.LabelAtlas(strText, charMapFile, itemWidth, itemHeight, startCharMap);
};
(function(){
    cc.LabelAtlas.CanvasRenderCmd = function(renderableObject){
        cc.AtlasNode.CanvasRenderCmd.call(this, renderableObject);
        this._needDraw = false;
    };
    var proto = cc.LabelAtlas.CanvasRenderCmd.prototype = Object.create(cc.AtlasNode.CanvasRenderCmd.prototype);
    proto.constructor = cc.LabelAtlas.CanvasRenderCmd;
    proto.setCascade = function(){
        var node = this._node;
        node._cascadeOpacityEnabled = true;
        node._cascadeColorEnabled = false;
    };
    proto.updateAtlasValues = function(){
        var node = this._node;
        var locString = node._string || "";
        var n = locString.length;
        var texture = this._textureToRender;
        var locItemWidth = node._itemWidth , locItemHeight = node._itemHeight;
        for (var i = 0, cr = -1; i < n; i++) {
            var a = locString.charCodeAt(i) - node._mapStartChar.charCodeAt(0);
            var row = parseInt(a % node._itemsPerRow, 10);
            var col = parseInt(a / node._itemsPerRow, 10);
            if(row < 0 || col < 0)
                continue;
            var rect = cc.rect(row * locItemWidth, col * locItemHeight, locItemWidth, locItemHeight);
            var textureContent = texture._contentSize;
            if(rect.x < 0 || rect.y < 0 || rect.x + rect.width > textureContent.width || rect.y + rect.height > textureContent.height)
                continue;
            cr++;
            var c = locString.charCodeAt(i);
            var fontChar = node.getChildByTag(i);
            if (!fontChar) {
                fontChar = new cc.Sprite();
                if (c === 32) {
                    fontChar.init();
                    fontChar.setTextureRect(cc.rect(0, 0, 10, 10), false, cc.size(0, 0));
                } else
                    fontChar.initWithTexture(texture, rect);
                cc.Node.prototype.addChild.call(node, fontChar, 0, i);
            } else {
                if (c === 32) {
                    fontChar.init();
                    fontChar.setTextureRect(cc.rect(0, 0, 10, 10), false, cc.size(0, 0));
                } else {
                    fontChar.initWithTexture(texture, rect);
                    fontChar.visible = true;
                }
            }
            fontChar.setPosition(cr * locItemWidth + locItemWidth / 2, locItemHeight / 2);
        }
        this.updateContentSize(i, cr+1);
    };
    proto.updateContentSize = function(i, cr){
        var node = this._node,
            contentSize = node._contentSize;
        if(i !== cr && i*node._itemWidth === contentSize.width && node._itemHeight === contentSize.height){
            node.setContentSize(cr * node._itemWidth, node._itemHeight);
        }
    };
    proto.setString = function(label){
        var node = this._node;
        if (node._children) {
            var locChildren = node._children;
            var len = locChildren.length;
            for (var i = 0; i < len; i++) {
                var child = locChildren[i];
                if (child && !child._lateChild)
                    child.visible = false;
            }
        }
    };
    proto._addChild = function(){
        child._lateChild = true;
    };
})();
cc.LabelBMFont = cc.SpriteBatchNode.extend({
    _opacityModifyRGB: false,
    _string: "",
    _config: null,
    _fntFile: "",
    _initialString: "",
    _alignment: cc.TEXT_ALIGNMENT_CENTER,
    _width: -1,
    _lineBreakWithoutSpaces: false,
    _imageOffset: null,
    _textureLoaded: false,
    _className: "LabelBMFont",
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new cc.LabelBMFont.WebGLRenderCmd(this);
        else
            return new cc.LabelBMFont.CanvasRenderCmd(this);
    },
    _setString: function (newString, needUpdateLabel) {
        if (!needUpdateLabel) {
            this._string = newString;
        } else {
            this._initialString = newString;
        }
        var locChildren = this._children;
        if (locChildren) {
            for (var i = 0; i < locChildren.length; i++) {
                var selNode = locChildren[i];
                if (selNode)
                    selNode.setVisible(false);
            }
        }
        if (this._textureLoaded) {
            this.createFontChars();
            if (needUpdateLabel)
                this.updateLabel();
        }
    },
    ctor: function (str, fntFile, width, alignment, imageOffset) {
        cc.SpriteBatchNode.prototype.ctor.call(this);
        this._imageOffset = cc.p(0, 0);
        this._cascadeColorEnabled = true;
        this._cascadeOpacityEnabled = true;
        this.initWithString(str, fntFile, width, alignment, imageOffset);
    },
    textureLoaded: function () {
        return this._textureLoaded;
    },
    addLoadedEventListener: function (callback, target) {
        this.addEventListener("load", callback, target);
    },
    isOpacityModifyRGB: function () {
        return this._opacityModifyRGB;
    },
    setOpacityModifyRGB: function (opacityModifyRGB) {
        this._opacityModifyRGB = opacityModifyRGB;
        var locChildren = this._children;
        if (locChildren) {
            for (var i = 0; i < locChildren.length; i++) {
                var node = locChildren[i];
                if (node)
                    node.opacityModifyRGB = this._opacityModifyRGB;
            }
        }
    },
    _changeTextureColor: function () {
        this._renderCmd._changeTextureColor();
    },
    /**
     * Initialization of the node, please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
     */
    init: function () {
        return this.initWithString(null, null, null, null, null);
    },
    initWithString: function (str, fntFile, width, alignment, imageOffset) {
        var self = this, theString = str || "";
        if (self._config)
            cc.log("cc.LabelBMFont.initWithString(): re-init is no longer supported");
        var texture;
        if (fntFile) {
            var newConf = cc.loader.getRes(fntFile);
            if (!newConf) {
                cc.log("cc.LabelBMFont.initWithString(): Impossible to create font. Please check file");
                return false;
            }
            self._config = newConf;
            self._fntFile = fntFile;
            texture = cc.textureCache.addImage(newConf.atlasName);
            var locIsLoaded = texture.isLoaded();
            self._textureLoaded = locIsLoaded;
            if (!locIsLoaded) {
                texture.addEventListener("load", function (sender) {
                    var self1 = this;
                    self1._textureLoaded = true;
                    self1.initWithTexture(sender, self1._initialString.length);
                    self1.setString(self1._initialString, true);
                    self1.dispatchEvent("load");
                }, self);
            }
        } else {
            texture = new cc.Texture2D();
            var image = new Image();
            texture.initWithElement(image);
            self._textureLoaded = false;
        }
        if (self.initWithTexture(texture, theString.length)) {
            self._alignment = alignment || cc.TEXT_ALIGNMENT_LEFT;
            self._imageOffset = imageOffset || cc.p(0, 0);
            self._width = (width === undefined) ? -1 : width;
            self._realOpacity = 255;
            self._realColor = cc.color(255, 255, 255, 255);
            self._contentSize.width = 0;
            self._contentSize.height = 0;
            self.setAnchorPoint(0.5, 0.5);
            self.setString(theString, true);
            return true;
        }
        return false;
    },
    createFontChars: function () {
        var self = this;
        var cmd = this._renderCmd;
        var locTexture = cmd._texture || this._texture;
        var nextFontPositionX = 0;
        var tmpSize = cc.size(0, 0);
        var longestLine = 0;
        var quantityOfLines = 1;
        var locStr = self._string;
        var stringLen = locStr ? locStr.length : 0;
        if (stringLen === 0)
            return;
        var i, locCfg = self._config, locKerningDict = locCfg.kerningDict,
            locCommonH = locCfg.commonHeight, locFontDict = locCfg.fontDefDictionary;
        for (i = 0; i < stringLen - 1; i++) {
            if (locStr.charCodeAt(i) === 10) quantityOfLines++;
        }
        var totalHeight = locCommonH * quantityOfLines;
        var nextFontPositionY = -(locCommonH - locCommonH * quantityOfLines);
        var prev = -1;
        var fontDef;
        for (i = 0; i < stringLen; i++) {
            var key = locStr.charCodeAt(i);
            if (key === 0) continue;
            if (key === 10) {
                nextFontPositionX = 0;
                nextFontPositionY -= locCfg.commonHeight;
                continue;
            }
            var kerningAmount = locKerningDict[(prev << 16) | (key & 0xffff)] || 0;
            fontDef = locFontDict[key];
            if (!fontDef) {
                cc.log("cocos2d: LabelBMFont: character not found " + locStr[i]);
                fontDef = {
                    rect: {
                        x: 0,
                        y: 0,
                        width: 0,
                        height: 0
                    },
                    xOffset: 0,
                    yOffset: 0,
                    xAdvance: 0
                };
            }
            var rect = cc.rect(fontDef.rect.x, fontDef.rect.y, fontDef.rect.width, fontDef.rect.height);
            rect = cc.rectPixelsToPoints(rect);
            rect.x += self._imageOffset.x;
            rect.y += self._imageOffset.y;
            var fontChar = self.getChildByTag(i);
            if (!fontChar) {
                fontChar = new cc.Sprite();
                fontChar.initWithTexture(locTexture, rect, false);
                fontChar._newTextureWhenChangeColor = true;
                this.addChild(fontChar, 0, i);
            } else {
                cmd._updateCharTexture(fontChar, rect, key);
            }
            fontChar.opacityModifyRGB = this._opacityModifyRGB;
            cmd._updateCharColorAndOpacity(fontChar);
            var yOffset = locCfg.commonHeight - fontDef.yOffset;
            var fontPos = cc.p(nextFontPositionX + fontDef.xOffset + fontDef.rect.width * 0.5 + kerningAmount,
                nextFontPositionY + yOffset - rect.height * 0.5 * cc.contentScaleFactor());
            fontChar.setPosition(cc.pointPixelsToPoints(fontPos));
            nextFontPositionX += fontDef.xAdvance + kerningAmount;
            prev = key;
            if (longestLine < nextFontPositionX)
                longestLine = nextFontPositionX;
        }
        if(fontDef && fontDef.xAdvance < fontDef.rect.width)
            tmpSize.width = longestLine - fontDef.xAdvance + fontDef.rect.width;
        else
            tmpSize.width = longestLine;
        tmpSize.height = totalHeight;
        self.setContentSize(cc.sizePixelsToPoints(tmpSize));
    },
    updateString: function (fromUpdate) {
        var self = this;
        var locChildren = self._children;
        if (locChildren) {
            for (var i = 0, li = locChildren.length; i < li; i++) {
                var node = locChildren[i];
                if (node) node.visible = false;
            }
        }
        if (self._config)
            self.createFontChars();
        if (!fromUpdate)
            self.updateLabel();
    },
    getString: function () {
        return this._initialString;
    },
    setString: function (newString, needUpdateLabel) {
        newString = String(newString);
        if (needUpdateLabel == null)
            needUpdateLabel = true;
        if (newString == null || !cc.isString(newString))
            newString = newString + "";
        this._initialString = newString;
        this._setString(newString, needUpdateLabel);
    },
    _setStringForSetter: function (newString) {
        this.setString(newString, false);
    },
    setCString: function (label) {
        this.setString(label, true);
    },
    _getCharsWidth:function (startIndex, endIndex) {
        if (endIndex <= 0)
        {
            return 0;
        }
        var curTextFirstSprite = this.getChildByTag(startIndex);
        var curTextLastSprite = this.getChildByTag(startIndex + endIndex);
        return this._getLetterPosXLeft(curTextLastSprite) - this._getLetterPosXLeft(curTextFirstSprite);
    },
    _checkWarp:function (strArr, i, maxWidth, initStringWrapNum) {
        var self = this;
        var text = strArr[i];
        var curLength = 0;
        for (var strArrIndex = 0; strArrIndex < i; strArrIndex++)
        {
            curLength += strArr[strArrIndex].length;
        }
        curLength = curLength + i - initStringWrapNum;
        var allWidth = self._getCharsWidth(curLength, strArr[i].length - 1);
        if (allWidth > maxWidth && text.length > 1) {
            var fuzzyLen = text.length * ( maxWidth / allWidth ) | 0;
            var tmpText = text.substr(fuzzyLen);
            var width = allWidth - this._getCharsWidth(curLength + fuzzyLen, tmpText.length - 1);
            var sLine;
            var pushNum = 0;
            var checkWhile = 0;
            while (width > maxWidth && checkWhile++ < 100) {
                fuzzyLen *= maxWidth / width;
                fuzzyLen = fuzzyLen | 0;
                tmpText = text.substr(fuzzyLen);
                width = allWidth - this._getCharsWidth(curLength + fuzzyLen, tmpText.length - 1);
            }
            checkWhile = 0;
            while (width < maxWidth && checkWhile++ < 100) {
                if (tmpText) {
                    var exec = cc.LabelTTF._wordRex.exec(tmpText);
                    pushNum = exec ? exec[0].length : 1;
                    sLine = tmpText;
                }
                if (self._lineBreakWithoutSpaces) {
                    pushNum = 0;
                }
                fuzzyLen = fuzzyLen + pushNum;
                tmpText = text.substr(fuzzyLen);
                width = allWidth - this._getCharsWidth(curLength + fuzzyLen, tmpText.length - 1);
            }
            fuzzyLen -= pushNum;
            if (fuzzyLen === 0) {
                fuzzyLen = 1;
                sLine = sLine.substr(1);
            }
            var sText = text.substr(0, fuzzyLen), result;
            if (cc.LabelTTF.wrapInspection) {
                if (cc.LabelTTF._symbolRex.test(sLine || tmpText)) {
                    result = cc.LabelTTF._lastWordRex.exec(sText);
                    pushNum = result ? result[0].length : 0;
                    if (self._lineBreakWithoutSpaces) {
                        pushNum = 0;
                    }
                    fuzzyLen -= pushNum;
                    sLine = text.substr(fuzzyLen);
                    sText = text.substr(0, fuzzyLen);
                }
            }
            if (cc.LabelTTF._firsrEnglish.test(sLine)) {
                result = cc.LabelTTF._lastEnglish.exec(sText);
                if (result && sText !== result[0]) {
                    pushNum = result[0].length;
                    if (self._lineBreakWithoutSpaces) {
                        pushNum = 0;
                    }
                    fuzzyLen -= pushNum;
                    sLine = text.substr(fuzzyLen);
                    sText = text.substr(0, fuzzyLen);
                }
            }
            strArr[i] = sLine || tmpText;
            strArr.splice(i, 0, sText);
        }
    },
    updateLabel: function () {
        var self = this;
        self.string = self._initialString;
        var i, j, characterSprite;
        if (self._width > 0) {
            var stringArr = self.string.split('\n');
            var wrapString = "";
            var newWrapNum = 0;
            var oldArrLength = 0;
            for (i = 0; i < stringArr.length; i++) {
                oldArrLength = stringArr.length;
                this._checkWarp(stringArr, i, self._width * this._scaleX, newWrapNum);
                if (oldArrLength < stringArr.length) {
                    newWrapNum++;
                }
                if (i > 0)
                {
                    wrapString += "\n";
                }
                wrapString += stringArr[i];
            }
            wrapString = wrapString + String.fromCharCode(0);
            self._setString(wrapString, false);
        }
        if (self._alignment !== cc.TEXT_ALIGNMENT_LEFT) {
            i = 0;
            var lineNumber = 0;
            var strlen = self._string.length;
            var last_line = [];
            for (var ctr = 0; ctr < strlen; ctr++) {
                if (self._string[ctr].charCodeAt(0) === 10 || self._string[ctr].charCodeAt(0) === 0) {
                    var lineWidth = 0;
                    var line_length = last_line.length;
                    if (line_length === 0) {
                        lineNumber++;
                        continue;
                    }
                    var index = i + line_length - 1 + lineNumber;
                    if (index < 0) continue;
                    var lastChar = self.getChildByTag(index);
                    if (lastChar == null)
                        continue;
                    lineWidth = lastChar.getPositionX() + lastChar._getWidth() / 2;
                    var shift = 0;
                    switch (self._alignment) {
                        case cc.TEXT_ALIGNMENT_CENTER:
                            shift = self.width / 2 - lineWidth / 2;
                            break;
                        case cc.TEXT_ALIGNMENT_RIGHT:
                            shift = self.width - lineWidth;
                            break;
                        default:
                            break;
                    }
                    if (shift !== 0) {
                        for (j = 0; j < line_length; j++) {
                            index = i + j + lineNumber;
                            if (index < 0) continue;
                            characterSprite = self.getChildByTag(index);
                            if (characterSprite)
                                characterSprite.x += shift;
                        }
                    }
                    i += line_length;
                    lineNumber++;
                    last_line.length = 0;
                    continue;
                }
                last_line.push(self._string[i]);
            }
        }
    },
    setAlignment: function (alignment) {
        this._alignment = alignment;
        this.updateLabel();
    },
    _getAlignment: function () {
        return this._alignment;
    },
    setBoundingWidth: function (width) {
        this._width = width;
        this.updateLabel();
    },
    _getBoundingWidth: function () {
        return this._width;
    },
    setLineBreakWithoutSpace: function (breakWithoutSpace) {
        this._lineBreakWithoutSpaces = breakWithoutSpace;
        this.updateLabel();
    },
    setScale: function (scale, scaleY) {
        cc.Node.prototype.setScale.call(this, scale, scaleY);
        this.updateLabel();
    },
    setScaleX: function (scaleX) {
        cc.Node.prototype.setScaleX.call(this, scaleX);
        this.updateLabel();
    },
    setScaleY: function (scaleY) {
        cc.Node.prototype.setScaleY.call(this, scaleY);
        this.updateLabel();
    },
    setFntFile: function (fntFile) {
        var self = this;
        if (fntFile != null && fntFile !== self._fntFile) {
            var newConf = cc.loader.getRes(fntFile);
            if (!newConf) {
                cc.log("cc.LabelBMFont.setFntFile() : Impossible to create font. Please check file");
                return;
            }
            self._fntFile = fntFile;
            self._config = newConf;
            var texture = cc.textureCache.addImage(newConf.atlasName);
            var locIsLoaded = texture.isLoaded();
            self._textureLoaded = locIsLoaded;
            if (!locIsLoaded) {
                texture.addEventListener("load", function (sender) {
                    var self1 = this;
                    self1._textureLoaded = true;
                    self1.setTexture(sender);
                    self1.createFontChars();
                    self1._changeTextureColor();
                    self1.updateLabel();
                    self1.dispatchEvent("load");
                }, self);
            } else {
                self.setTexture(texture);
                self.createFontChars();
            }
        }
    },
    getFntFile: function () {
        return this._fntFile;
    },
    setTexture: function(texture){
        this._texture = texture;
        this._renderCmd.setTexture(texture);
    },
    setAnchorPoint: function (point, y) {
        cc.Node.prototype.setAnchorPoint.call(this, point, y);
        this.updateLabel();
    },
    _setAnchorX: function (x) {
        cc.Node.prototype._setAnchorX.call(this, x);
        this.updateLabel();
    },
    _setAnchorY: function (y) {
        cc.Node.prototype._setAnchorY.call(this, y);
        this.updateLabel();
    },
    _atlasNameFromFntFile: function (fntFile) {},
    _kerningAmountForFirst: function (first, second) {
        var ret = 0;
        var key = (first << 16) | (second & 0xffff);
        if (this._configuration.kerningDictionary) {
            var element = this._configuration.kerningDictionary[key.toString()];
            if (element)
                ret = element.amount;
        }
        return ret;
    },
    _getLetterPosXLeft: function (sp) {
        return sp.getPositionX() * this._scaleX - (sp._getWidth() * this._scaleX * sp._getAnchorX());
    },
    _getLetterPosXRight: function (sp) {
        return sp.getPositionX() * this._scaleX + (sp._getWidth() * this._scaleX * sp._getAnchorX());
    },
    _isspace_unicode: function(ch){
        ch = ch.charCodeAt(0);
        return  ((ch >= 9 && ch <= 13) || ch === 32 || ch === 133 || ch === 160 || ch === 5760
            || (ch >= 8192 && ch <= 8202) || ch === 8232 || ch === 8233 || ch === 8239
            || ch === 8287 || ch === 12288)
    },
    _utf8_trim_ws: function(str){
        var len = str.length;
        if (len <= 0)
            return;
        var last_index = len - 1;
        if (this._isspace_unicode(str[last_index])) {
            for (var i = last_index - 1; i >= 0; --i) {
                if (this._isspace_unicode(str[i])) {
                    last_index = i;
                }
                else {
                    break;
                }
            }
            this._utf8_trim_from(str, last_index);
        }
    },
    _utf8_trim_from: function(str, index){
        var len = str.length;
        if (index >= len || index < 0)
            return;
        str.splice(index, len);
    }
});
(function(){
    var p = cc.LabelBMFont.prototype;
    cc.EventHelper.prototype.apply(p);
    p.string;
    cc.defineGetterSetter(p, "string", p.getString, p._setStringForSetter);
    p.boundingWidth;
    cc.defineGetterSetter(p, "boundingWidth", p._getBoundingWidth, p.setBoundingWidth);
    p.textAlign;
    cc.defineGetterSetter(p, "textAlign", p._getAlignment, p.setAlignment);
    cc.defineGetterSetter(p, "texture", p.getTexture, p.setTexture);
})();
cc.LabelBMFont.create = function (str, fntFile, width, alignment, imageOffset) {
    return new cc.LabelBMFont(str, fntFile, width, alignment, imageOffset);
};
var _fntLoader = {
    INFO_EXP: /info [^\n]*(\n|$)/gi,
    COMMON_EXP: /common [^\n]*(\n|$)/gi,
    PAGE_EXP: /page [^\n]*(\n|$)/gi,
    CHAR_EXP: /char [^\n]*(\n|$)/gi,
    KERNING_EXP: /kerning [^\n]*(\n|$)/gi,
    ITEM_EXP: /\w+=[^ \r\n]+/gi,
    INT_EXP: /^[\-]?\d+$/,
    _parseStrToObj: function (str) {
        var arr = str.match(this.ITEM_EXP);
        var obj = {};
        if (arr) {
            for (var i = 0, li = arr.length; i < li; i++) {
                var tempStr = arr[i];
                var index = tempStr.indexOf("=");
                var key = tempStr.substring(0, index);
                var value = tempStr.substring(index + 1);
                if (value.match(this.INT_EXP)) value = parseInt(value);
                else if (value[0] === '"') value = value.substring(1, value.length - 1);
                obj[key] = value;
            }
        }
        return obj;
    },
    parseFnt: function (fntStr, url) {
        var self = this, fnt = {};
        var infoObj = self._parseStrToObj(fntStr.match(self.INFO_EXP)[0]);
        var paddingArr = infoObj["padding"].split(",");
        var padding = {
            left: parseInt(paddingArr[0]),
            top: parseInt(paddingArr[1]),
            right: parseInt(paddingArr[2]),
            bottom: parseInt(paddingArr[3])
        };
        var commonObj = self._parseStrToObj(fntStr.match(self.COMMON_EXP)[0]);
        fnt.commonHeight = commonObj["lineHeight"];
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
            var texSize = cc.configuration.getMaxTextureSize();
            if (commonObj["scaleW"] > texSize.width || commonObj["scaleH"] > texSize.height)
                cc.log("cc.LabelBMFont._parseCommonArguments(): page can't be larger than supported");
        }
        if (commonObj["pages"] !== 1) cc.log("cc.LabelBMFont._parseCommonArguments(): only supports 1 page");
        var pageObj = self._parseStrToObj(fntStr.match(self.PAGE_EXP)[0]);
        if (pageObj["id"] !== 0) cc.log("cc.LabelBMFont._parseImageFileName() : file could not be found");
        fnt.atlasName = cc.path.changeBasename(url, pageObj["file"]);
        var charLines = fntStr.match(self.CHAR_EXP);
        var fontDefDictionary = fnt.fontDefDictionary = {};
        for (var i = 0, li = charLines.length; i < li; i++) {
            var charObj = self._parseStrToObj(charLines[i]);
            var charId = charObj["id"];
            fontDefDictionary[charId] = {
                rect: {x: charObj["x"], y: charObj["y"], width: charObj["width"], height: charObj["height"]},
                xOffset: charObj["xoffset"],
                yOffset: charObj["yoffset"],
                xAdvance: charObj["xadvance"]
            };
        }
        var kerningDict = fnt.kerningDict = {};
        var kerningLines = fntStr.match(self.KERNING_EXP);
        if (kerningLines) {
            for (var i = 0, li = kerningLines.length; i < li; i++) {
                var kerningObj = self._parseStrToObj(kerningLines[i]);
                kerningDict[(kerningObj["first"] << 16) | (kerningObj["second"] & 0xffff)] = kerningObj["amount"];
            }
        }
        return fnt;
    },
    load: function (realUrl, url, res, cb) {
        var self = this;
        cc.loader.loadTxt(realUrl, function (err, txt) {
            if (err) return cb(err);
            cb(null, self.parseFnt(txt, url));
        });
    }
};
cc.loader.register(["fnt"], _fntLoader);
(function(){
    cc.LabelBMFont.CanvasRenderCmd = function(renderableObject){
        cc.Node.CanvasRenderCmd.call(this, renderableObject);
    };
    var proto = cc.LabelBMFont.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.LabelBMFont.CanvasRenderCmd;
    proto._updateCharTexture = function(fontChar, rect, key){
        if (key === 32) {
            fontChar.setTextureRect(rect, false, cc.size(0, 0));
        } else {
            fontChar.setTextureRect(rect, false);
            fontChar.visible = true;
        }
    };
    proto._updateCharColorAndOpacity = function(fontChar){
        fontChar._displayedColor = this._displayedColor;
        fontChar._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
        fontChar._displayedOpacity = this._displayedOpacity;
        fontChar._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    };
    proto.setTexture = function (texture) {
        var node = this._node;
        var locChildren = node._children;
        var locDisplayedColor = this._displayedColor;
        for (var i = 0; i < locChildren.length; i++) {
            var selChild = locChildren[i];
            var cm = selChild._renderCmd;
            var childDColor = cm._displayedColor;
            if (node._texture !== cm._texture && (childDColor.r !== locDisplayedColor.r ||
                childDColor.g !== locDisplayedColor.g || childDColor.b !== locDisplayedColor.b))
                continue;
            selChild.texture = texture;
        }
        node._texture = texture;
    };
    proto._changeTextureColor = function(){
        var node = this._node;
        var texture = node._texture,
            contentSize = texture.getContentSize();
        var oTexture = node._texture,
            oElement = oTexture.getHtmlElementObj();
        var disColor = this._displayedColor;
        var textureRect = cc.rect(0, 0, oElement.width, oElement.height);
        if (texture && contentSize.width > 0) {
            if(!oElement)
                return;
            var textureToRender = oTexture._generateColorTexture(disColor.r, disColor.g, disColor.b, textureRect);
            node.setTexture(textureToRender);
        }
    };
    proto._updateChildrenDisplayedOpacity = function(locChild){
        cc.Node.prototype.updateDisplayedOpacity.call(locChild, this._displayedOpacity);
    };
    proto._updateChildrenDisplayedColor = function(locChild){
        cc.Node.prototype.updateDisplayedColor.call(locChild, this._displayedColor);
    };
})();
(function(){
    cc.LabelAtlas.WebGLRenderCmd = function(renderable){
        cc.AtlasNode.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
    };
    var proto = cc.LabelAtlas.WebGLRenderCmd.prototype = Object.create(cc.AtlasNode.WebGLRenderCmd.prototype);
    proto.constructor = cc.LabelAtlas.WebGLRenderCmd;
    proto._updateColor = function () {
        if (this._colorF32Array) {
            var locDisplayedColor = this._displayedColor;
            var a = this._displayedOpacity / 255;
            if (this._node._opacityModifyRGB) {
                this._colorF32Array[0] = locDisplayedColor.r * a / 255;
                this._colorF32Array[1] = locDisplayedColor.g * a / 255;
                this._colorF32Array[2] = locDisplayedColor.b * a / 255;
                this._colorF32Array[3] = a;
            }
            else {
                this._colorF32Array[0] = locDisplayedColor.r / 255;
                this._colorF32Array[1] = locDisplayedColor.g / 255;
                this._colorF32Array[2] = locDisplayedColor.b / 255;
                this._colorF32Array[3] = a;
            }
        }
    };
    proto.setCascade = function(){
        var node = this._node;
        node._cascadeOpacityEnabled = true;
        node._cascadeColorEnabled = true;
    };
    proto.rendering = function(ctx){
        cc.AtlasNode.WebGLRenderCmd.prototype.rendering.call(this, ctx);
        if (cc.LABELATLAS_DEBUG_DRAW) {
            var node = this._node;
            var s = node.getContentSize();
            var locRect = node.getBoundingBoxToWorld();
            var posX = locRect.x,
                posY = locRect.y;
                s.width = locRect.width;
                s.height = locRect.height;
            var vertices = [cc.p(posX, posY), cc.p(posX+ s.width, posY),
                cc.p(s.width+posX, s.height+posY), cc.p(posX, posY+s.height)];
            cc._drawingUtil.drawPoly(vertices, 4, true);
        }
    };
    proto.updateAtlasValues = function(){
        var node = this._node;
        var locString = node._string;
        var n = locString.length;
        var locTextureAtlas = this._textureAtlas;
        var texture = locTextureAtlas.texture;
        var textureWide = texture.pixelsWidth;
        var textureHigh = texture.pixelsHeight;
        var itemWidthInPixels = node._itemWidth;
        var itemHeightInPixels = node._itemHeight;
        if (!node._ignoreContentScaleFactor) {
            itemWidthInPixels = node._itemWidth * cc.contentScaleFactor();
            itemHeightInPixels = node._itemHeight * cc.contentScaleFactor();
        }
        if (n > locTextureAtlas.getCapacity())
            cc.log("cc.LabelAtlas._updateAtlasValues(): Invalid String length");
        var quads = locTextureAtlas.quads;
        var locItemWidth = node._itemWidth;
        var locItemHeight = node._itemHeight;
        for (var i = 0, cr = -1; i < n; i++) {
            var a = locString.charCodeAt(i) - node._mapStartChar.charCodeAt(0);
            var row = a % node._itemsPerRow;
            var col = 0 | (a / node._itemsPerRow);
            if(row < 0 || col < 0)
                continue;
            if(row*locItemWidth + locItemWidth > textureWide || col*locItemHeight + locItemHeight > textureHigh)
                continue;
            cr++;
            var left, right, top, bottom;
            if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
                left = (2 * row * itemWidthInPixels + 1) / (2 * textureWide);
                right = left + (itemWidthInPixels * 2 - 2) / (2 * textureWide);
                top = (2 * col * itemHeightInPixels + 1) / (2 * textureHigh);
                bottom = top + (itemHeightInPixels * 2 - 2) / (2 * textureHigh);
            } else {
                left = row * itemWidthInPixels / textureWide;
                right = left + itemWidthInPixels / textureWide;
                top = col * itemHeightInPixels / textureHigh;
                bottom = top + itemHeightInPixels / textureHigh;
            }
            var quad = quads[i];
            var locQuadTL = quad.tl, locQuadTR = quad.tr, locQuadBL = quad.bl, locQuadBR = quad.br;
            locQuadTL.texCoords.u = left;
            locQuadTL.texCoords.v = top;
            locQuadTR.texCoords.u = right;
            locQuadTR.texCoords.v = top;
            locQuadBL.texCoords.u = left;
            locQuadBL.texCoords.v = bottom;
            locQuadBR.texCoords.u = right;
            locQuadBR.texCoords.v = bottom;
            locQuadBL.vertices.x = (cr * locItemWidth);
            locQuadBL.vertices.y = 0;
            locQuadBL.vertices.z = 0.0;
            locQuadBR.vertices.x = (cr * locItemWidth + locItemWidth);
            locQuadBR.vertices.y = 0;
            locQuadBR.vertices.z = 0.0;
            locQuadTL.vertices.x = cr * locItemWidth;
            locQuadTL.vertices.y = node._itemHeight;
            locQuadTL.vertices.z = 0.0;
            locQuadTR.vertices.x = cr * locItemWidth + locItemWidth;
            locQuadTR.vertices.y = node._itemHeight;
            locQuadTR.vertices.z = 0.0;
        }
        this._updateColor();
        this.updateContentSize(i, cr+1);
        if (n > 0) {
            locTextureAtlas.dirty = true;
            var totalQuads = locTextureAtlas.totalQuads;
            if (n > totalQuads)
                locTextureAtlas.increaseTotalQuadsWith(n - totalQuads);
        }
    };
    proto.updateContentSize = function(i, cr){
        var node = this._node,
            contentSize = node._contentSize;
        if(i !== cr && i*node._itemWidth === contentSize.width && node._itemHeight === contentSize.height){
            node.setContentSize(cr * node._itemWidth, node._itemHeight);
        }
    };
    proto.setString = function(label){
        var len = label.length;
        if (len > this._textureAtlas.totalQuads)
            this._textureAtlas.resizeCapacity(len);
    };
    proto._addChild = function(){};
})();
(function(){
    cc.LabelBMFont.WebGLRenderCmd = function(renderableObject){
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
    };
    var proto = cc.LabelBMFont.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.LabelBMFont.WebGLRenderCmd;
    proto.setTexture = function (texture) {
        this._node.setOpacityModifyRGB(this._node._texture.hasPremultipliedAlpha());
    };
    proto._updateCharTexture = function(fontChar, rect, key){
        fontChar.setTextureRect(rect, false);
        fontChar.visible = true;
    };
    proto._changeTextureColor = function(){};
    proto._updateCharColorAndOpacity = function(){};
})();
cc.MotionStreak = cc.Node.extend({
    texture:null,
    fastMode:false,
    startingPositionInitialized:false,
    _blendFunc:null,
    _stroke:0,
    _fadeDelta:0,
    _minSeg:0,
    _maxPoints:0,
    _nuPoints:0,
    _previousNuPoints:0,
    _pointVertexes:null,
    _pointState:null,
    _vertices:null,
    _colorPointer:null,
    _texCoords:null,
    _verticesBuffer:null,
    _colorPointerBuffer:null,
    _texCoordsBuffer:null,
    _className:"MotionStreak",
    ctor: function (fade, minSeg, stroke, color, texture) {
        cc.Node.prototype.ctor.call(this);
        this._positionR = cc.p(0, 0);
        this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
        this.fastMode = false;
        this.startingPositionInitialized = false;
        this.texture = null;
        this._stroke = 0;
        this._fadeDelta = 0;
        this._minSeg = 0;
        this._maxPoints = 0;
        this._nuPoints = 0;
        this._previousNuPoints = 0;
        this._pointVertexes = null;
        this._pointState = null;
        this._vertices = null;
        this._colorPointer = null;
        this._texCoords = null;
        this._verticesBuffer = null;
        this._colorPointerBuffer = null;
        this._texCoordsBuffer = null;
        if(texture !== undefined)
            this.initWithFade(fade, minSeg, stroke, color, texture);
    },
    getTexture:function () {
        return this.texture;
    },
    setTexture:function (texture) {
        if (this.texture !== texture)
            this.texture = texture;
    },
    getBlendFunc:function () {
        return this._blendFunc;
    },
    setBlendFunc:function (src, dst) {
        if (dst === undefined) {
            this._blendFunc = src;
        } else {
            this._blendFunc.src = src;
            this._blendFunc.dst = dst;
        }
    },
    getOpacity:function () {
        cc.log("cc.MotionStreak.getOpacity has not been supported.");
        return 0;
    },
    setOpacity:function (opacity) {
        cc.log("cc.MotionStreak.setOpacity has not been supported.");
    },
    setOpacityModifyRGB:function (value) {
    },
    isOpacityModifyRGB:function () {
        return false;
    },
    isFastMode:function () {
        return this.fastMode;
    },
    setFastMode:function (fastMode) {
        this.fastMode = fastMode;
    },
    isStartingPositionInitialized:function () {
        return this.startingPositionInitialized;
    },
    setStartingPositionInitialized:function (startingPositionInitialized) {
        this.startingPositionInitialized = startingPositionInitialized;
    },
    getStroke:function () {
        return this._stroke;
    },
    setStroke:function (stroke) {
        this._stroke = stroke;
    },
    initWithFade:function (fade, minSeg, stroke, color, texture) {
        if(!texture)
            throw new Error("cc.MotionStreak.initWithFade(): Invalid filename or texture");
        if (cc.isString(texture))
            texture = cc.textureCache.addImage(texture);
        cc.Node.prototype.setPosition.call(this, cc.p(0,0));
        this.anchorX = 0;
        this.anchorY = 0;
        this.ignoreAnchor = true;
        this.startingPositionInitialized = false;
        this.fastMode = true;
        this._minSeg = (minSeg === -1.0) ? (stroke / 5.0) : minSeg;
        this._minSeg *= this._minSeg;
        this._stroke = stroke;
        this._fadeDelta = 1.0 / fade;
        var locMaxPoints = (0 | (fade * 60)) + 2;
        this._maxPoints = locMaxPoints;
        this._nuPoints = 0;
        this._pointState = new Float32Array(locMaxPoints);
        this._pointVertexes = new Float32Array(locMaxPoints * 2);
        this._vertices = new Float32Array(locMaxPoints * 4);
        this._texCoords = new Float32Array(locMaxPoints * 4);
        this._colorPointer = new Uint8Array(locMaxPoints * 8);
        this._verticesBuffer = gl.createBuffer();
        this._texCoordsBuffer = gl.createBuffer();
        this._colorPointerBuffer = gl.createBuffer();
        this._blendFunc.src = gl.SRC_ALPHA;
        this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
        this.texture = texture;
        this.color = color;
        this.scheduleUpdate();
        gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordsBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._texCoords, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._colorPointerBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._colorPointer, gl.DYNAMIC_DRAW);
        return true;
    },
    tintWithColor:function (color) {
        this.color = color;
        var locColorPointer = this._colorPointer;
        for (var i = 0, len = this._nuPoints * 2; i < len; i++) {
            locColorPointer[i * 4] = color.r;
            locColorPointer[i * 4 + 1] = color.g;
            locColorPointer[i * 4 + 2] = color.b;
        }
    },
    reset:function () {
        this._nuPoints = 0;
    },
    setPosition:function (position, yValue) {
        this.startingPositionInitialized = true;
        if(yValue === undefined){
            this._positionR.x = position.x;
            this._positionR.y = position.y;
        } else {
            this._positionR.x = position;
            this._positionR.y = yValue;
        }
    },
    getPositionX:function () {
        return this._positionR.x;
    },
    setPositionX:function (x) {
        this._positionR.x = x;
        if(!this.startingPositionInitialized)
            this.startingPositionInitialized = true;
    },
    getPositionY:function () {
        return  this._positionR.y;
    },
    setPositionY:function (y) {
        this._positionR.y = y;
        if(!this.startingPositionInitialized)
            this.startingPositionInitialized = true;
    },
    update:function (delta) {
        if (!this.startingPositionInitialized)
            return;
        this._renderCmd._updateDisplayColor();
        delta *= this._fadeDelta;
        var newIdx, newIdx2, i, i2;
        var mov = 0;
        var locNuPoints = this._nuPoints;
        var locPointState = this._pointState, locPointVertexes = this._pointVertexes, locVertices = this._vertices;
        var locColorPointer = this._colorPointer;
        for (i = 0; i < locNuPoints; i++) {
            locPointState[i] -= delta;
            if (locPointState[i] <= 0)
                mov++;
            else {
                newIdx = i - mov;
                if (mov > 0) {
                    locPointState[newIdx] = locPointState[i];
                    locPointVertexes[newIdx * 2] = locPointVertexes[i * 2];
                    locPointVertexes[newIdx * 2 + 1] = locPointVertexes[i * 2 + 1];
                    i2 = i * 2;
                    newIdx2 = newIdx * 2;
                    locVertices[newIdx2 * 2] = locVertices[i2 * 2];
                    locVertices[newIdx2 * 2 + 1] = locVertices[i2 * 2 + 1];
                    locVertices[(newIdx2 + 1) * 2] = locVertices[(i2 + 1) * 2];
                    locVertices[(newIdx2 + 1) * 2 + 1] = locVertices[(i2 + 1) * 2 + 1];
                    i2 *= 4;
                    newIdx2 *= 4;
                    locColorPointer[newIdx2 + 0] = locColorPointer[i2 + 0];
                    locColorPointer[newIdx2 + 1] = locColorPointer[i2 + 1];
                    locColorPointer[newIdx2 + 2] = locColorPointer[i2 + 2];
                    locColorPointer[newIdx2 + 4] = locColorPointer[i2 + 4];
                    locColorPointer[newIdx2 + 5] = locColorPointer[i2 + 5];
                    locColorPointer[newIdx2 + 6] = locColorPointer[i2 + 6];
                } else
                    newIdx2 = newIdx * 8;
                var op = locPointState[newIdx] * 255.0;
                locColorPointer[newIdx2 + 3] = op;
                locColorPointer[newIdx2 + 7] = op;
            }
        }
        locNuPoints -= mov;
        var appendNewPoint = true;
        if (locNuPoints >= this._maxPoints)
            appendNewPoint = false;
        else if (locNuPoints > 0) {
            var a1 = cc.pDistanceSQ(cc.p(locPointVertexes[(locNuPoints - 1) * 2], locPointVertexes[(locNuPoints - 1) * 2 + 1]),
                this._positionR) < this._minSeg;
            var a2 = (locNuPoints === 1) ? false : (cc.pDistanceSQ(
                cc.p(locPointVertexes[(locNuPoints - 2) * 2], locPointVertexes[(locNuPoints - 2) * 2 + 1]), this._positionR) < (this._minSeg * 2.0));
            if (a1 || a2)
                appendNewPoint = false;
        }
        if (appendNewPoint) {
            locPointVertexes[locNuPoints * 2] = this._positionR.x;
            locPointVertexes[locNuPoints * 2 + 1] = this._positionR.y;
            locPointState[locNuPoints] = 1.0;
            var offset = locNuPoints * 8;
            var locDisplayedColor = this.getDisplayedColor();
            locColorPointer[offset] = locDisplayedColor.r;
            locColorPointer[offset + 1] = locDisplayedColor.g;
            locColorPointer[offset + 2] = locDisplayedColor.b;
            locColorPointer[offset + 4] = locDisplayedColor.r;
            locColorPointer[offset + 5] = locDisplayedColor.g;
            locColorPointer[offset + 6] = locDisplayedColor.b;
            locColorPointer[offset + 3] = 255;
            locColorPointer[offset + 7] = 255;
            if (locNuPoints > 0 && this.fastMode) {
                if (locNuPoints > 1)
                    cc.vertexLineToPolygon(locPointVertexes, this._stroke, this._vertices, locNuPoints, 1);
                else
                    cc.vertexLineToPolygon(locPointVertexes, this._stroke, this._vertices, 0, 2);
            }
            locNuPoints++;
        }
        if (!this.fastMode)
            cc.vertexLineToPolygon(locPointVertexes, this._stroke, this._vertices, 0, locNuPoints);
        if (locNuPoints && this._previousNuPoints !== locNuPoints) {
            var texDelta = 1.0 / locNuPoints;
            var locTexCoords = this._texCoords;
            for (i = 0; i < locNuPoints; i++) {
                locTexCoords[i * 4] = 0;
                locTexCoords[i * 4 + 1] = texDelta * i;
                locTexCoords[(i * 2 + 1) * 2] = 1;
                locTexCoords[(i * 2 + 1) * 2 + 1] = texDelta * i;
            }
            this._previousNuPoints = locNuPoints;
        }
        this._nuPoints = locNuPoints;
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new cc.MotionStreak.WebGLRenderCmd(this);
        else
            return null;
    }
});
cc.MotionStreak.create = function (fade, minSeg, stroke, color, texture) {
    return new cc.MotionStreak(fade, minSeg, stroke, color, texture);
};
cc.MotionStreak.WebGLRenderCmd = function(renderableObject){
    cc.Node.WebGLRenderCmd.call(this, renderableObject);
    this._needDraw = true;
    this._matrix = new cc.math.Matrix4();
    this._matrix.identity();
    this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
};
cc.MotionStreak.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
cc.MotionStreak.WebGLRenderCmd.prototype.constructor = cc.Sprite.WebGLRenderCmd;
cc.MotionStreak.WebGLRenderCmd.prototype.rendering = function(ctx){
    var node = this._node;
    if (node._nuPoints <= 1)
        return;
    if (node.texture && node.texture.isLoaded()) {
        ctx = ctx || cc._renderContext;
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
        cc.glBindTexture2D(node.texture);
        ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
        ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
        ctx.bindBuffer(ctx.ARRAY_BUFFER, node._verticesBuffer);
        ctx.bufferData(ctx.ARRAY_BUFFER, node._vertices, ctx.DYNAMIC_DRAW);
        ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, ctx.FLOAT, false, 0, 0);
        ctx.bindBuffer(ctx.ARRAY_BUFFER, node._texCoordsBuffer);
        ctx.bufferData(ctx.ARRAY_BUFFER, node._texCoords, ctx.DYNAMIC_DRAW);
        ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, ctx.FLOAT, false, 0, 0);
        ctx.bindBuffer(ctx.ARRAY_BUFFER, node._colorPointerBuffer);
        ctx.bufferData(ctx.ARRAY_BUFFER, node._colorPointer, ctx.DYNAMIC_DRAW);
        ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, ctx.UNSIGNED_BYTE, true, 0, 0);
        ctx.drawArrays(ctx.TRIANGLE_STRIP, 0, node._nuPoints * 2);
        cc.g_NumberOfDraws++;
    }
};
cc.NodeGrid = cc.Node.extend({
    grid: null,
    _target: null,
    _gridRect:null,
    ctor: function (rect) {
        cc.Node.prototype.ctor.call(this);
        if(rect === undefined) rect = cc.rect();
        this._gridRect = rect;
    },
    getGrid: function () {
        return this.grid;
    },
    setGrid: function (grid) {
        this.grid = grid;
    },
    setGridRect: function (rect) {
        this._gridRect = rect;
    },
    getGridRect: function () {
        return this._gridRect;
    },
    setTarget: function (target) {
        this._target = target;
    },
    _createRenderCmd: function(){
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new cc.NodeGrid.WebGLRenderCmd(this);
        else
            return new cc.Node.CanvasRenderCmd(this);
    }
});
var _p = cc.NodeGrid.prototype;
_p.grid;
_p.target;
cc.defineGetterSetter(_p, "target", null, _p.setTarget);
cc.NodeGrid.create = function () {
    return new cc.NodeGrid();
};
(function(){
    cc.NodeGrid.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = false;
        this._gridBeginCommand = new cc.CustomRenderCmd(this, this.onGridBeginDraw);
        this._gridEndCommand = new cc.CustomRenderCmd(this, this.onGridEndDraw);
    };
    var proto = cc.NodeGrid.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.NodeGrid.WebGLRenderCmd;
    proto.visit = function(parentCmd) {
        var node = this._node;
        if (!node._visible)
            return;
        parentCmd = parentCmd || this.getParentRenderCmd();
        if (node._parent && node._parent._renderCmd)
            this._curLevel = node._parent._renderCmd._curLevel + 1;
        var currentStack = cc.current_stack;
        currentStack.stack.push(currentStack.top);
        this._syncStatus(parentCmd);
        currentStack.top = this._stackMatrix;
        cc.renderer.pushRenderCommand(this._gridBeginCommand);
        if (node._target)
            node._target.visit();
        var locChildren = node._children;
        if (locChildren && locChildren.length > 0) {
            var childLen = locChildren.length;
            node.sortAllChildren();
            for (var i = 0; i < childLen; i++) {
                var child = locChildren[i];
                child && child.visit();
            }
        }
        cc.renderer.pushRenderCommand(this._gridEndCommand);
        this._dirtyFlag = 0;
        currentStack.top = currentStack.stack.pop();
    };
    proto.onGridBeginDraw = function(){
        var locGrid = this._node.grid;
        if (locGrid && locGrid._active)
            locGrid.beforeDraw();
    };
    proto.onGridEndDraw = function(){
        var locGrid = this._node.grid;
        if (locGrid && locGrid._active)
            locGrid.afterDraw(this._node);
    };
})();
cc.v2fzero = function () {
    return {x: 0, y: 0};
};
cc.v2f = function (x, y) {
    return {x: x, y: y};
};
cc.v2fadd = function (v0, v1) {
    return cc.v2f(v0.x + v1.x, v0.y + v1.y);
};
cc.v2fsub = function (v0, v1) {
    return cc.v2f(v0.x - v1.x, v0.y - v1.y);
};
cc.v2fmult = function (v, s) {
    return cc.v2f(v.x * s, v.y * s);
};
cc.v2fperp = function (p0) {
    return cc.v2f(-p0.y, p0.x);
};
cc.v2fneg = function (p0) {
    return cc.v2f(-p0.x, -p0.y);
};
cc.v2fdot = function (p0, p1) {
    return  p0.x * p1.x + p0.y * p1.y;
};
cc.v2fforangle = function (_a_) {
    return cc.v2f(Math.cos(_a_), Math.sin(_a_));
};
cc.v2fnormalize = function (p) {
    var r = cc.pNormalize(cc.p(p.x, p.y));
    return cc.v2f(r.x, r.y);
};
cc.__v2f = function (v) {
    return cc.v2f(v.x, v.y);
};
cc.__t = function (v) {
    return {u: v.x, v: v.y};
};
cc.DrawNode = cc.Node.extend({
    _buffer:null,
    _blendFunc:null,
    _lineWidth: 1,
    _drawColor: null,
    getBlendFunc: function () {
        return this._blendFunc;
    },
    setBlendFunc: function (blendFunc, dst) {
        if (dst === undefined) {
            this._blendFunc.src = blendFunc.src;
            this._blendFunc.dst = blendFunc.dst;
        } else {
            this._blendFunc.src = blendFunc;
            this._blendFunc.dst = dst;
        }
    },
    setLineWidth: function (width) {
        this._lineWidth = width;
    },
    getLineWidth: function () {
        return this._lineWidth;
    },
    setDrawColor: function (color) {
        var locDrawColor = this._drawColor;
        locDrawColor.r = color.r;
        locDrawColor.g = color.g;
        locDrawColor.b = color.b;
        locDrawColor.a = (color.a == null) ? 255 : color.a;
    },
    getDrawColor: function () {
        return  cc.color(this._drawColor.r, this._drawColor.g, this._drawColor.b, this._drawColor.a);
    }
});
cc.DrawNode.create = function () {
    return new cc.DrawNode();
};
cc.DrawNode.TYPE_DOT = 0;
cc.DrawNode.TYPE_SEGMENT = 1;
cc.DrawNode.TYPE_POLY = 2;
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
        cc._DrawNodeElement = function (type, verts, fillColor, lineWidth, lineColor, lineCap, isClosePolygon, isFill, isStroke) {
            var _t = this;
            _t.type = type;
            _t.verts = verts || null;
            _t.fillColor = fillColor || null;
            _t.lineWidth = lineWidth || 0;
            _t.lineColor = lineColor || null;
            _t.lineCap = lineCap || "butt";
            _t.isClosePolygon = isClosePolygon || false;
            _t.isFill = isFill || false;
            _t.isStroke = isStroke || false;
        };
        cc.extend(cc.DrawNode.prototype, {
            _className:"DrawNodeCanvas",
            ctor: function () {
                cc.Node.prototype.ctor.call(this);
                var locCmd = this._renderCmd;
                locCmd._buffer = this._buffer = [];
                locCmd._drawColor = this._drawColor = cc.color(255, 255, 255, 255);
                locCmd._blendFunc = this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
                this.init();
                this._localBB = new cc.Rect();
            },
            setLocalBB: function(rectorX, y, width, height) {
                var localBB = this._localBB;
                if(y === undefined) {
                    localBB.x = rectorX.x;
                    localBB.y = rectorX.y;
                    localBB.width = rectorX.width;
                    localBB.height = rectorX.height;
                } else {
                    localBB.x = rectorX;
                    localBB.y = y;
                    localBB.width = width;
                    localBB.height = height;
                }
            },
            drawRect: function (origin, destination, fillColor, lineWidth, lineColor) {
                lineWidth = (lineWidth == null) ? this._lineWidth : lineWidth;
                lineColor = lineColor || this.getDrawColor();
                if(lineColor.a == null)
                    lineColor.a = 255;
                var vertices = [
                    origin,
                    cc.p(destination.x, origin.y),
                    destination,
                    cc.p(origin.x, destination.y)
                ];
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = vertices;
                element.lineWidth = lineWidth;
                element.lineColor = lineColor;
                element.isClosePolygon = true;
                element.isStroke = true;
                element.lineCap = "butt";
                element.fillColor = fillColor;
                if (fillColor) {
                    if(fillColor.a == null)
                        fillColor.a = 255;
                    element.isFill = true;
                }
                this._buffer.push(element);
            },
            drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var coef = 2.0 * Math.PI / segments;
                var vertices = [];
                for (var i = 0; i <= segments; i++) {
                    var rads = i * coef;
                    var j = radius * Math.cos(rads + angle) + center.x;
                    var k = radius * Math.sin(rads + angle) + center.y;
                    vertices.push(cc.p(j, k));
                }
                if (drawLineToCenter) {
                    vertices.push(cc.p(center.x, center.y));
                }
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = vertices;
                element.lineWidth = lineWidth;
                element.lineColor = color;
                element.isClosePolygon = true;
                element.isStroke = true;
                this._buffer.push(element);
            },
            drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var vertices = [], t = 0.0;
                for (var i = 0; i < segments; i++) {
                    var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
                    var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
                    vertices.push(cc.p(x, y));
                    t += 1.0 / segments;
                }
                vertices.push(cc.p(destination.x, destination.y));
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = vertices;
                element.lineWidth = lineWidth;
                element.lineColor = color;
                element.isStroke = true;
                element.lineCap = "round";
                this._buffer.push(element);
            },
            drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var vertices = [], t = 0;
                for (var i = 0; i < segments; i++) {
                    var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
                    var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
                    vertices.push(cc.p(x, y));
                    t += 1.0 / segments;
                }
                vertices.push(cc.p(destination.x, destination.y));
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = vertices;
                element.lineWidth = lineWidth;
                element.lineColor = color;
                element.isStroke = true;
                element.lineCap = "round";
                this._buffer.push(element);
            },
            drawCatmullRom: function (points, segments, lineWidth, color) {
                this.drawCardinalSpline(points, 0.5, segments, lineWidth, color);
            },
            drawCardinalSpline: function (config, tension, segments, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if(color.a == null)
                    color.a = 255;
                var vertices = [], p, lt, deltaT = 1.0 / config.length;
                for (var i = 0; i < segments + 1; i++) {
                    var dt = i / segments;
                    if (dt === 1) {
                        p = config.length - 1;
                        lt = 1;
                    } else {
                        p = 0 | (dt / deltaT);
                        lt = (dt - deltaT * p) / deltaT;
                    }
                    var newPos = cc.cardinalSplineAt(
                        cc.getControlPointAt(config, p - 1),
                        cc.getControlPointAt(config, p - 0),
                        cc.getControlPointAt(config, p + 1),
                        cc.getControlPointAt(config, p + 2),
                        tension, lt);
                    vertices.push(newPos);
                }
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = vertices;
                element.lineWidth = lineWidth;
                element.lineColor = color;
                element.isStroke = true;
                element.lineCap = "round";
                this._buffer.push(element);
            },
            drawDot: function (pos, radius, color) {
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT);
                element.verts = [pos];
                element.lineWidth = radius;
                element.fillColor = color;
                this._buffer.push(element);
            },
            drawDots: function(points, radius, color){
                if(!points || points.length == 0)
                    return;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                for(var i = 0, len = points.length; i < len; i++)
                   this.drawDot(points[i], radius, color);
            },
            drawSegment: function (from, to, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = [from, to];
                element.lineWidth = lineWidth * 2;
                element.lineColor = color;
                element.isStroke = true;
                element.lineCap = "round";
                this._buffer.push(element);
            },
            drawPoly_: function (verts, fillColor, lineWidth, color) {
                lineWidth = (lineWidth == null ) ? this._lineWidth : lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
                element.verts = verts;
                element.fillColor = fillColor;
                element.lineWidth = lineWidth;
                element.lineColor = color;
                element.isClosePolygon = true;
                element.isStroke = true;
                element.lineCap = "round";
                if (fillColor)
                    element.isFill = true;
                this._buffer.push(element);
            },
            drawPoly: function (verts, fillColor, lineWidth, lineColor) {
                var vertsCopy = [];
                for (var i=0; i < verts.length; i++) {
                    vertsCopy.push(cc.p(verts[i].x, verts[i].y));
                }
                return this.drawPoly_(vertsCopy, fillColor, lineWidth, lineColor);
            },
            clear: function () {
                this._buffer.length = 0;
            },
            _createRenderCmd: function(){
                return new cc.DrawNode.CanvasRenderCmd(this);
            }
        });
    }
    else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        cc.extend(cc.DrawNode.prototype, {
            _bufferCapacity:0,
            _trianglesArrayBuffer:null,
            _trianglesWebBuffer:null,
            _trianglesReader:null,
            _dirty:false,
            _className:"DrawNodeWebGL",
            ctor:function () {
                cc.Node.prototype.ctor.call(this);
                this._buffer = [];
                this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
                this._drawColor = cc.color(255,255,255,255);
                this.init();
            },
            init:function () {
                if (cc.Node.prototype.init.call(this)) {
                    this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR);
                    this._ensureCapacity(64);
                    this._trianglesWebBuffer = cc._renderContext.createBuffer();
                    this._dirty = true;
                    return true;
                }
                return false;
            },
            drawRect: function (origin, destination, fillColor, lineWidth, lineColor) {
                lineWidth = (lineWidth == null) ? this._lineWidth : lineWidth;
                lineColor = lineColor || this.getDrawColor();
                if (lineColor.a == null)
                    lineColor.a = 255;
                var vertices = [origin, cc.p(destination.x, origin.y), destination, cc.p(origin.x, destination.y)];
                if(fillColor == null)
                    this._drawSegments(vertices, lineWidth, lineColor, true);
                else
                    this.drawPoly(vertices, fillColor, lineWidth, lineColor);
            },
            drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var coef = 2.0 * Math.PI / segments, vertices = [], i, len;
                for (i = 0; i <= segments; i++) {
                    var rads = i * coef;
                    var j = radius * Math.cos(rads + angle) + center.x;
                    var k = radius * Math.sin(rads + angle) + center.y;
                    vertices.push(cc.p(j, k));
                }
                if (drawLineToCenter)
                    vertices.push(cc.p(center.x, center.y));
                lineWidth *= 0.5;
                for (i = 0, len = vertices.length; i < len - 1; i++)
                    this.drawSegment(vertices[i], vertices[i + 1], lineWidth, color);
            },
            drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var vertices = [], t = 0.0;
                for (var i = 0; i < segments; i++) {
                    var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
                    var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
                    vertices.push(cc.p(x, y));
                    t += 1.0 / segments;
                }
                vertices.push(cc.p(destination.x, destination.y));
                this._drawSegments(vertices, lineWidth, color, false);
            },
            drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var vertices = [], t = 0;
                for (var i = 0; i < segments; i++) {
                    var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
                    var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
                    vertices.push(cc.p(x, y));
                    t += 1.0 / segments;
                }
                vertices.push(cc.p(destination.x, destination.y));
                this._drawSegments(vertices, lineWidth, color, false);
            },
            drawCatmullRom: function (points, segments, lineWidth, color) {
                this.drawCardinalSpline(points, 0.5, segments, lineWidth, color);
            },
            drawCardinalSpline: function (config, tension, segments, lineWidth, color) {
                lineWidth = lineWidth || this._lineWidth;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var vertices = [], p, lt, deltaT = 1.0 / config.length;
                for (var i = 0; i < segments + 1; i++) {
                    var dt = i / segments;
                    if (dt === 1) {
                        p = config.length - 1;
                        lt = 1;
                    } else {
                        p = 0 | (dt / deltaT);
                        lt = (dt - deltaT * p) / deltaT;
                    }
                    var newPos = cc.cardinalSplineAt(
                        cc.getControlPointAt(config, p - 1),
                        cc.getControlPointAt(config, p - 0),
                        cc.getControlPointAt(config, p + 1),
                        cc.getControlPointAt(config, p + 2),
                        tension, lt);
                    vertices.push(newPos);
                }
                lineWidth *= 0.5;
                for (var j = 0, len = vertices.length; j < len - 1; j++)
                    this.drawSegment(vertices[j], vertices[j + 1], lineWidth, color);
            },
            _render:function () {
                var gl = cc._renderContext;
                gl.bindBuffer(gl.ARRAY_BUFFER, this._trianglesWebBuffer);
                if (this._dirty) {
                    gl.bufferData(gl.ARRAY_BUFFER, this._trianglesArrayBuffer, gl.STREAM_DRAW);
                    this._dirty = false;
                }
                var triangleSize = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
                gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
                gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
                gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
                gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, triangleSize, 0);
                gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, triangleSize, 8);
                gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, triangleSize, 12);
                gl.drawArrays(gl.TRIANGLES, 0, this._buffer.length * 3);
                cc.incrementGLDraws(1);
            },
            _ensureCapacity:function(count){
                var _t = this;
                var locBuffer = _t._buffer;
                if(locBuffer.length + count > _t._bufferCapacity){
                    var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT;
                    _t._bufferCapacity += Math.max(_t._bufferCapacity, count);
                    if((locBuffer == null) || (locBuffer.length === 0)){
                        _t._buffer = [];
                        _t._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * _t._bufferCapacity);
                        _t._trianglesReader = new Uint8Array(_t._trianglesArrayBuffer);
                    } else {
                        var newTriangles = [];
                        var newArrayBuffer = new ArrayBuffer(TriangleLength * _t._bufferCapacity);
                        for(var i = 0; i < locBuffer.length;i++){
                            newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(locBuffer[i].a,locBuffer[i].b,locBuffer[i].c,
                                newArrayBuffer, i * TriangleLength);
                        }
                        _t._trianglesReader = new Uint8Array(newArrayBuffer);
                        _t._trianglesArrayBuffer = newArrayBuffer;
                        _t._buffer = newTriangles;
                    }
                }
            },
            drawDot:function (pos, radius, color) {
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a};
                var a = {vertices: {x: pos.x - radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: -1.0, v: -1.0}};
                var b = {vertices: {x: pos.x - radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: -1.0, v: 1.0}};
                var c = {vertices: {x: pos.x + radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: 1.0, v: 1.0}};
                var d = {vertices: {x: pos.x + radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: 1.0, v: -1.0}};
                this._ensureCapacity(2*3);
                this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, b, c, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT));
                this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, c, d, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT));
                this._dirty = true;
            },
            drawDots: function(points, radius,color) {
                if(!points || points.length === 0)
                    return;
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                for(var i = 0, len = points.length; i < len; i++)
                    this.drawDot(points[i], radius, color);
            },
            drawSegment:function (from, to, radius, color) {
                color = color || this.getDrawColor();
                if (color.a == null)
                    color.a = 255;
                radius = radius || (this._lineWidth * 0.5);
                var vertexCount = 6*3;
                this._ensureCapacity(vertexCount);
                var c4bColor = {r: 0 | color.r, g: 0 | color.g, b: 0 | color.b, a: 0 | color.a};
                var a = cc.__v2f(from), b = cc.__v2f(to);
                var n = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(b, a))), t = cc.v2fperp(n);
                var nw = cc.v2fmult(n, radius), tw = cc.v2fmult(t, radius);
                var v0 = cc.v2fsub(b, cc.v2fadd(nw, tw));
                var v1 = cc.v2fadd(b, cc.v2fsub(nw, tw));
                var v2 = cc.v2fsub(b, nw);
                var v3 = cc.v2fadd(b, nw);
                var v4 = cc.v2fsub(a, nw);
                var v5 = cc.v2fadd(a, nw);
                var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw));
                var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw));
                var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer, locBuffer = this._buffer;
                locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))},
                    {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
                    triangleBuffer, locBuffer.length * TriangleLength));
                locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
                    {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
                    triangleBuffer, locBuffer.length * TriangleLength));
                locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
                    {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
                    triangleBuffer, locBuffer.length * TriangleLength));
                locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
                    {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
                    triangleBuffer, locBuffer.length * TriangleLength));
                locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))},
                    {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
                    triangleBuffer, locBuffer.length * TriangleLength));
                locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))},
                    {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
                    triangleBuffer, locBuffer.length * TriangleLength));
                this._dirty = true;
            },
            drawPoly:function (verts, fillColor, borderWidth, borderColor) {
                if(fillColor == null){
                    this._drawSegments(verts, borderWidth, borderColor, true);
                    return;
                }
                if (fillColor.a == null)
                    fillColor.a = 255;
                if (borderColor.a == null)
                    borderColor.a = 255;
                borderWidth = (borderWidth == null)? this._lineWidth : borderWidth;
                borderWidth *= 0.5;
                var c4bFillColor = {r: 0 | fillColor.r, g: 0 | fillColor.g, b: 0 | fillColor.b, a: 0 | fillColor.a};
                var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a};
                var extrude = [], i, v0, v1, v2, count = verts.length;
                for (i = 0; i < count; i++) {
                    v0 = cc.__v2f(verts[(i - 1 + count) % count]);
                    v1 = cc.__v2f(verts[i]);
                    v2 = cc.__v2f(verts[(i + 1) % count]);
                    var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0)));
                    var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1)));
                    var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0));
                    extrude[i] = {offset: offset, n: n2};
                }
                var outline = (borderWidth > 0.0), triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount;
                this._ensureCapacity(vertexCount);
                var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer;
                var locBuffer = this._buffer;
                var inset = (outline == false ? 0.5 : 0.0);
                for (i = 0; i < count - 2; i++) {
                    v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset));
                    v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset));
                    v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset));
                    locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
                        {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
                        trianglesBuffer, locBuffer.length * triangleBytesLen));
                }
                for (i = 0; i < count; i++) {
                    var j = (i + 1) % count;
                    v0 = cc.__v2f(verts[i]);
                    v1 = cc.__v2f(verts[j]);
                    var n0 = extrude[i].n;
                    var offset0 = extrude[i].offset;
                    var offset1 = extrude[j].offset;
                    var inner0 = outline ? cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fsub(v0, cc.v2fmult(offset0, 0.5));
                    var inner1 = outline ? cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fsub(v1, cc.v2fmult(offset1, 0.5));
                    var outer0 = outline ? cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fadd(v0, cc.v2fmult(offset0, 0.5));
                    var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5));
                    if (outline) {
                        locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
                            {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
                            trianglesBuffer, locBuffer.length * triangleBytesLen));
                        locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
                            {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
                            trianglesBuffer, locBuffer.length * triangleBytesLen));
                    } else {
                        locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
                            {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)},
                            trianglesBuffer, locBuffer.length * triangleBytesLen));
                        locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
                            {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)},
                            trianglesBuffer, locBuffer.length * triangleBytesLen));
                    }
                }
                extrude = null;
                this._dirty = true;
            },
            _drawSegments: function(verts, borderWidth, borderColor, closePoly){
                borderWidth = (borderWidth == null) ? this._lineWidth : borderWidth;
                borderColor = borderColor || this._drawColor;
                if(borderColor.a == null)
                    borderColor.a = 255;
                borderWidth *= 0.5;
                if (borderWidth <= 0)
                    return;
                var c4bBorderColor = {r: 0 | borderColor.r, g: 0 | borderColor.g, b: 0 | borderColor.b, a: 0 | borderColor.a };
                var extrude = [], i, v0, v1, v2, count = verts.length;
                for (i = 0; i < count; i++) {
                    v0 = cc.__v2f(verts[(i - 1 + count) % count]);
                    v1 = cc.__v2f(verts[i]);
                    v2 = cc.__v2f(verts[(i + 1) % count]);
                    var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0)));
                    var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1)));
                    var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0));
                    extrude[i] = {offset: offset, n: n2};
                }
                var triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount;
                this._ensureCapacity(vertexCount);
                var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer;
                var locBuffer = this._buffer;
                var len = closePoly ? count : count - 1;
                for (i = 0; i < len; i++) {
                    var j = (i + 1) % count;
                    v0 = cc.__v2f(verts[i]);
                    v1 = cc.__v2f(verts[j]);
                    var n0 = extrude[i].n;
                    var offset0 = extrude[i].offset;
                    var offset1 = extrude[j].offset;
                    var inner0 = cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth));
                    var inner1 = cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth));
                    var outer0 = cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth));
                    var outer1 = cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth));
                    locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
                        {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
                        trianglesBuffer, locBuffer.length * triangleBytesLen));
                    locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
                        {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
                        trianglesBuffer, locBuffer.length * triangleBytesLen));
                }
                extrude = null;
                this._dirty = true;
            },
            clear:function () {
                this._buffer.length = 0;
                this._dirty = true;
            },
            _createRenderCmd: function () {
                return new cc.DrawNode.WebGLRenderCmd(this);
            }
        });
    }
});
(function(){
    cc.DrawNode.CanvasRenderCmd = function(renderableObject){
        cc.Node.CanvasRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._buffer = null;
        this._drawColor = null;
        this._blendFunc = null;
    };
    cc.DrawNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    cc.DrawNode.CanvasRenderCmd.prototype.constructor = cc.DrawNode.CanvasRenderCmd;
    cc.DrawNode.CanvasRenderCmd.prototype.getLocalBB = function () {
        var node = this._node;
        return node._localBB;
    };
    cc.extend( cc.DrawNode.CanvasRenderCmd.prototype, {
        rendering: function (ctx, scaleX, scaleY) {
            var wrapper = ctx || cc._renderContext, context = wrapper.getContext(), node = this._node;
            var alpha = node._displayedOpacity / 255;
            if (alpha === 0)
                return;
            wrapper.setTransform(this._worldTransform, scaleX, scaleY);
            wrapper.setGlobalAlpha(alpha);
            if ((this._blendFunc && (this._blendFunc.src === cc.SRC_ALPHA) && (this._blendFunc.dst === cc.ONE)))
                wrapper.setCompositeOperation('lighter');
            var locBuffer = this._buffer;
            for (var i = 0, len = locBuffer.length; i < len; i++) {
                var element = locBuffer[i];
                switch (element.type) {
                    case cc.DrawNode.TYPE_DOT:
                        this._drawDot(wrapper, element, scaleX, scaleY);
                        break;
                    case cc.DrawNode.TYPE_SEGMENT:
                        this._drawSegment(wrapper, element, scaleX, scaleY);
                        break;
                    case cc.DrawNode.TYPE_POLY:
                        this._drawPoly(wrapper, element, scaleX, scaleY);
                        break;
                }
            }
        },
        _drawDot: function (wrapper, element) {
            var locColor = element.fillColor, locPos = element.verts[0], locRadius = element.lineWidth;
            var ctx = wrapper.getContext();
            wrapper.setFillStyle("rgba(" + (0 | locColor.r) + "," + (0 | locColor.g) + "," + (0 | locColor.b) + "," + locColor.a / 255 + ")");
            ctx.beginPath();
            ctx.arc(locPos.x , -locPos.y , locRadius , 0, Math.PI * 2, false);
            ctx.closePath();
            ctx.fill();
        },
        _drawSegment: function (wrapper, element, scaleX) {
            var locColor = element.lineColor;
            var locFrom = element.verts[0], locTo = element.verts[1];
            var locLineWidth = element.lineWidth, locLineCap = element.lineCap;
            var ctx = wrapper.getContext();
            wrapper.setStrokeStyle("rgba(" + (0 | locColor.r) + "," + (0 | locColor.g) + "," + (0 | locColor.b) + "," + locColor.a / 255 + ")");
            ctx.lineWidth = locLineWidth * scaleX;
            ctx.beginPath();
            ctx.lineCap = locLineCap;
            ctx.moveTo(locFrom.x , -locFrom.y );
            ctx.lineTo(locTo.x , -locTo.y );
            ctx.stroke();
        },
        _drawPoly: function (wrapper, element, scaleX) {
            var locVertices = element.verts, locLineCap = element.lineCap;
            if (locVertices == null)
                return;
            var locFillColor = element.fillColor, locLineWidth = element.lineWidth;
            var locLineColor = element.lineColor, locIsClosePolygon = element.isClosePolygon;
            var locIsFill = element.isFill, locIsStroke = element.isStroke;
            var ctx = wrapper.getContext();
            var firstPoint = locVertices[0];
            ctx.lineCap = locLineCap;
            if (locFillColor)
                wrapper.setFillStyle("rgba(" + (0 | locFillColor.r) + "," + (0 | locFillColor.g) + ","
                    + (0 | locFillColor.b) + "," + locFillColor.a / 255 + ")");
            if (locLineWidth)
                ctx.lineWidth = locLineWidth * scaleX;
            if (locLineColor)
                wrapper.setStrokeStyle("rgba(" + (0 | locLineColor.r) + "," + (0 | locLineColor.g) + ","
                    + (0 | locLineColor.b) + "," + locLineColor.a / 255 + ")");
            ctx.beginPath();
            ctx.moveTo(firstPoint.x , -firstPoint.y );
            for (var i = 1, len = locVertices.length; i < len; i++)
                ctx.lineTo(locVertices[i].x , -locVertices[i].y );
            if (locIsClosePolygon)
                ctx.closePath();
            if (locIsFill)
                ctx.fill();
            if (locIsStroke)
                ctx.stroke();
        }
    });
})();
(function(){
    cc.DrawNode.WebGLRenderCmd = function (renderableObject) {
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
    };
    cc.DrawNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    cc.DrawNode.WebGLRenderCmd.prototype.constructor = cc.DrawNode.WebGLRenderCmd;
    cc.DrawNode.WebGLRenderCmd.prototype.rendering = function (ctx) {
        var node = this._node;
        if (node._buffer.length > 0) {
            var wt = this._worldTransform;
            this._matrix.mat[0] = wt.a;
            this._matrix.mat[4] = wt.c;
            this._matrix.mat[12] = wt.tx;
            this._matrix.mat[1] = wt.b;
            this._matrix.mat[5] = wt.d;
            this._matrix.mat[13] = wt.ty;
            cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
            this._shaderProgram.use();
            this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
            node._render();
        }
    };
})();
cc.stencilBits = -1;
cc.ClippingNode = cc.Node.extend({
    alphaThreshold: 0,
    inverted: false,
    _stencil: null,
    _className: "ClippingNode",
    ctor: function (stencil) {
        stencil = stencil || null;
        cc.Node.prototype.ctor.call(this);
        this._stencil = stencil;
        this.alphaThreshold = 1;
        this.inverted = false;
        this._renderCmd.initStencilBits();
    },
    /**
     * Initialization of the node, please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
     * @function
     * @param {cc.Node} [stencil=null]
     */
    init: function (stencil) {
        this._stencil = stencil;
        this.alphaThreshold = 1;
        this.inverted = false;
        this._renderCmd.initStencilBits();
        return true;
    },
    onEnter: function () {
        cc.Node.prototype.onEnter.call(this);
        this._stencil.onEnter();
    },
    onEnterTransitionDidFinish: function () {
        cc.Node.prototype.onEnterTransitionDidFinish.call(this);
        this._stencil.onEnterTransitionDidFinish();
    },
    onExitTransitionDidStart: function () {
        this._stencil.onExitTransitionDidStart();
        cc.Node.prototype.onExitTransitionDidStart.call(this);
    },
    onExit: function () {
        this._stencil.onExit();
        cc.Node.prototype.onExit.call(this);
    },
    getAlphaThreshold: function () {
        return this.alphaThreshold;
    },
    setAlphaThreshold: function (alphaThreshold) {
        this.alphaThreshold = alphaThreshold;
    },
    isInverted: function () {
        return this.inverted;
    },
    setInverted: function (inverted) {
        this.inverted = inverted;
    },
    getStencil: function () {
        return this._stencil;
    },
    setStencil: function (stencil) {
        if(this._stencil === stencil)
            return;
        this._renderCmd.setStencil(stencil);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.ClippingNode.CanvasRenderCmd(this);
        else
            return new cc.ClippingNode.WebGLRenderCmd(this);
    }
});
var _p = cc.ClippingNode.prototype;
cc.defineGetterSetter(_p, "stencil", _p.getStencil, _p.setStencil);
_p.stencil;
cc.ClippingNode.create = function (stencil) {
    return new cc.ClippingNode(stencil);
};
(function(){
    cc.ClippingNode.CanvasRenderCmd = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = false;
        this._godhelpme = false;
        this._clipElemType = false;
        this._rendererSaveCmd = new cc.CustomRenderCmd(this, this._saveCmdCallback);
        this._rendererClipCmd = new cc.CustomRenderCmd(this, this._clipCmdCallback);
        this._rendererRestoreCmd = new cc.CustomRenderCmd(this, this._restoreCmdCallback);
    };
    var proto = cc.ClippingNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.ClippingNode.CanvasRenderCmd;
    proto.initStencilBits = function(){};
    proto.setStencil = function(stencil){
        if(stencil == null)
            return;
        this._node._stencil = stencil;
        if (stencil instanceof cc.DrawNode) {
            if(stencil._buffer){
                for(var i=0; i<stencil._buffer.length; i++){
                    stencil._buffer[i].isFill = false;
                    stencil._buffer[i].isStroke = false;
                }
            }
            stencil._renderCmd.rendering = function (ctx, scaleX, scaleY) {
                return;
            };
            stencil._renderCmd._canUseDirtyRegion = true;
            this._rendererSaveCmd._canUseDirtyRegion = true;
            this._rendererClipCmd._canUseDirtyRegion = true;
            this._rendererRestoreCmd._canUseDirtyRegion = true;
        }else{
            stencil._parent = this._node;
        }
    };
    proto._saveCmdCallback  = function(ctx, scaleX, scaleY) {
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        if (this._clipElemType) {
            var locCache = cc.ClippingNode.CanvasRenderCmd._getSharedCache();
            var canvas = context.canvas;
            locCache.width = canvas.width;
            locCache.height = canvas.height;
            var locCacheCtx = locCache.getContext("2d");
            locCacheCtx.drawImage(canvas, 0, 0);
        } else {
            wrapper.save();
            wrapper.setTransform(this._worldTransform, scaleX, scaleY);
            if (this._node.inverted) {
                context.beginPath();
                context.rect(0, 0, context.canvas.width, -context.canvas.height);
                context.clip();
            }
        }
    };
    proto._setStencilCompositionOperation = function(stencil){
         if(!stencil)
            return;
        var node = this._node;
        if(stencil._renderCmd && stencil._renderCmd._blendFuncStr)
            stencil._renderCmd._blendFuncStr = (node.inverted ? "destination-out" : "destination-in");
        if(!stencil._children)
            return;
        var children = stencil._children;
        for(var i = 0, len = children.length; i < len; i++){
             this._setStencilCompositionOperation(children[i]);
        }
    };
    proto._clipCmdCallback = function(ctx) {
        var node = this._node;
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        if (this._clipElemType) {
            this._setStencilCompositionOperation(node._stencil);
        } else {
            var stencil = this._node._stencil;
            if(stencil instanceof cc.DrawNode) {
                context.beginPath();
                var t = stencil._renderCmd._transform;
                context.transform(t.a, t.b, t.c, t.d, t.tx, -t.ty);
                for (var i = 0; i < stencil._buffer.length; i++) {
                    var vertices = stencil._buffer[i].verts;
                    var firstPoint = vertices[0];
                    context.moveTo(firstPoint.x , -firstPoint.y );
                    for (var j = vertices.length - 1; j > 0; j--)
                        context.lineTo(vertices[j].x , -vertices[j].y );
                }
            }
            context.clip();
        }
    };
    proto._restoreCmdCallback = function (ctx) {
        var locCache = cc.ClippingNode.CanvasRenderCmd._getSharedCache();
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        if (this._clipElemType) {
            context.save();
            context.setTransform(1, 0, 0, 1, 0, 0);
            context.globalCompositeOperation = "destination-over";
            context.drawImage(locCache, 0, 0);
            context.restore();
            this._dirtyFlag = 0;
        } else {
            wrapper.restore();
        }
    };
    proto.transform = function(parentCmd, recursive){
        cc.Node.CanvasRenderCmd.prototype.transform.call(this, parentCmd, recursive);
        var node = this._node;
        if(node._stencil && node._stencil._renderCmd)
            node._stencil._renderCmd.transform(this, recursive);
    };
    proto._cangodhelpme = function (godhelpme) {
        if (godhelpme === true || godhelpme === false)
            cc.ClippingNode.CanvasRenderCmd.prototype._godhelpme = godhelpme;
        return cc.ClippingNode.CanvasRenderCmd.prototype._godhelpme;
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        parentCmd = parentCmd || this.getParentRenderCmd();
        if( parentCmd)
            this._curLevel = parentCmd._curLevel + 1;
        var transformRenderCmd = this;
        this._clipElemType = !(!this._cangodhelpme() && node._stencil instanceof cc.DrawNode);
        if (!node._stencil || !node._stencil.visible) {
            if (this.inverted)
                this.originVisit(parentCmd);
            return;
        }
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this._rendererSaveCmd);
        if(this._clipElemType){
            this.originVisit(parentCmd);
        }else{
            node._stencil.visit(this);
        }
        cc.renderer.pushRenderCommand(this._rendererClipCmd);
        if(this._clipElemType){
            node._stencil.visit(transformRenderCmd);
        }else{
            var i, children = node._children;
            this._cangodhelpme(true);
            var len = children.length;
            if (len > 0) {
                node.sortAllChildren();
                for (i = 0; i < len; i++)
                    children[i]._renderCmd.visit(this);
            }
            this._cangodhelpme(false);
        }
        cc.renderer.pushRenderCommand(this._rendererRestoreCmd);
        this._dirtyFlag = 0;
    };
    cc.ClippingNode.CanvasRenderCmd._sharedCache = null;
    cc.ClippingNode.CanvasRenderCmd._getSharedCache = function () {
        return (cc.ClippingNode.CanvasRenderCmd._sharedCache) || (cc.ClippingNode.CanvasRenderCmd._sharedCache = document.createElement("canvas"));
    };
})();
// ------------------------------- ClippingNode's WebGL render cmd ------------------------------
(function(){
    cc.ClippingNode.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = false;
        this._beforeVisitCmd = new cc.CustomRenderCmd(this, this._onBeforeVisit);
        this._afterDrawStencilCmd = new cc.CustomRenderCmd(this, this._onAfterDrawStencil);
        this._afterVisitCmd = new cc.CustomRenderCmd(this, this._onAfterVisit);
        this._currentStencilEnabled = null;
        this._mask_layer_le = null;
    };
    var proto = cc.ClippingNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.ClippingNode.WebGLRenderCmd;
    cc.ClippingNode.WebGLRenderCmd._init_once = null;
    cc.ClippingNode.WebGLRenderCmd._visit_once = null;
    cc.ClippingNode.WebGLRenderCmd._layer = -1;
    proto.initStencilBits = function(){
        cc.ClippingNode.WebGLRenderCmd._init_once = true;
        if (cc.ClippingNode.WebGLRenderCmd._init_once) {
            cc.stencilBits = cc._renderContext.getParameter(cc._renderContext.STENCIL_BITS);
            if (cc.stencilBits <= 0)
                cc.log("Stencil buffer is not enabled.");
            cc.ClippingNode.WebGLRenderCmd._init_once = false;
        }
    };
    proto.transform = function(parentCmd, recursive){
        var node = this._node;
        this.originTransform(parentCmd, recursive);
        if(node._stencil) {
            node._stencil._renderCmd.transform(this, recursive);
        }
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        if( node._parent && node._parent._renderCmd)
            this._curLevel = node._parent._renderCmd._curLevel + 1;
        if (cc.stencilBits < 1) {
            this.originVisit(parentCmd);
            return;
        }
        if (!node._stencil || !node._stencil.visible) {
            if (node.inverted)
                this.originVisit(parentCmd);
            return;
        }
        if (cc.ClippingNode.WebGLRenderCmd._layer + 1 === cc.stencilBits) {
            cc.ClippingNode.WebGLRenderCmd._visit_once = true;
            if (cc.ClippingNode.WebGLRenderCmd._visit_once) {
                cc.log("Nesting more than " + cc.stencilBits + "stencils is not supported. Everything will be drawn without stencil for this node and its children.");
                cc.ClippingNode.WebGLRenderCmd._visit_once = false;
            }
            this.originVisit(parentCmd);
            return;
        }
        cc.renderer.pushRenderCommand(this._beforeVisitCmd);
        var currentStack = cc.current_stack;
        currentStack.stack.push(currentStack.top);
        this._syncStatus(parentCmd);
        currentStack.top = this._stackMatrix;
        node._stencil._renderCmd.visit(this);
        cc.renderer.pushRenderCommand(this._afterDrawStencilCmd);
        var locChildren = node._children;
        if (locChildren && locChildren.length > 0) {
            var childLen = locChildren.length;
            node.sortAllChildren();
            for (var i = 0; i < childLen; i++) {
                locChildren[i]._renderCmd.visit(this);
            }
        }
        cc.renderer.pushRenderCommand(this._afterVisitCmd);
        this._dirtyFlag = 0;
        currentStack.top = currentStack.stack.pop();
    };
    proto.setStencil = function(stencil){
        var node = this._node;
        if(node._stencil)
            node._stencil._parent = null;
        node._stencil = stencil;
        if(node._stencil)
            node._stencil._parent = node;
    };
    proto._onBeforeVisit = function(ctx){
        var gl = ctx || cc._renderContext, node = this._node;
        cc.ClippingNode.WebGLRenderCmd._layer++;
        var mask_layer = 0x1 << cc.ClippingNode.WebGLRenderCmd._layer;
        var mask_layer_l = mask_layer - 1;
        this._mask_layer_le = mask_layer | mask_layer_l;
        this._currentStencilEnabled = gl.isEnabled(gl.STENCIL_TEST);
        gl.clear(gl.DEPTH_BUFFER_BIT);
        gl.enable(gl.STENCIL_TEST);
        gl.depthMask(false);
        gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
        gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
        gl.stencilMask(mask_layer);
        gl.clear(gl.STENCIL_BUFFER_BIT);
        if (node.alphaThreshold < 1) {
            var program = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
            cc.glUseProgram(program.getProgram());
            program.setUniformLocationWith1f(cc.UNIFORM_ALPHA_TEST_VALUE_S, node.alphaThreshold);
            program.setUniformLocationWithMatrix4fv(cc.UNIFORM_MVMATRIX_S, cc.renderer.mat4Identity.mat);
            cc.setProgram(node._stencil, program);
        }
    };
    proto._onAfterDrawStencil = function(ctx){
        var gl = ctx || cc._renderContext;
        gl.depthMask(true);
        gl.stencilFunc(!this._node.inverted ? gl.EQUAL : gl.NOTEQUAL, this._mask_layer_le, this._mask_layer_le);
        gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
    };
    proto._onAfterVisit = function(ctx){
        var gl = ctx || cc._renderContext;
        cc.ClippingNode.WebGLRenderCmd._layer--;
        if (this._currentStencilEnabled) {
            var mask_layer = 0x1 << cc.ClippingNode.WebGLRenderCmd._layer;
            var mask_layer_l = mask_layer - 1;
            var mask_layer_le = mask_layer | mask_layer_l;
            gl.stencilMask(mask_layer);
            gl.stencilFunc(gl.EQUAL, mask_layer_le, mask_layer_le);
        }
        else {
            gl.disable(gl.STENCIL_TEST);
        }
    };
})();
cc.GridBase = cc.Class.extend({
    _active:false,
    _reuseGrid:0,
    _gridSize:null,
    _gridRect:null,
    _texture:null,
    _step:null,
    _grabber:null,
    _isTextureFlipped:false,
    _shaderProgram:null,
    _directorProjection:0,
    _dirty:false,
    ctor:function (gridSize, texture, flipped, rect) {
        cc.sys._checkWebGLRenderMode();
        this._active=false;
        this._reuseGrid=0;
        this._gridSize=null;
        this._gridRect=new cc.rect();
        this._texture=null;
        this._step = cc.p(0, 0);
        this._grabber=null;
        this._isTextureFlipped=false;
        this._shaderProgram=null;
        this._directorProjection=0;
        this._dirty=false;
        if(gridSize !== undefined)
            this.initWithSize(gridSize, texture, flipped, rect);
    },
    isActive:function () {
        return this._active;
    },
    setActive:function (active) {
        this._active = active;
        if (!active) {
            var director = cc.director;
            var proj = director.getProjection();
            director.setProjection(proj);
        }
    },
    getReuseGrid:function () {
        return this._reuseGrid;
    },
    setReuseGrid:function (reuseGrid) {
        this._reuseGrid = reuseGrid;
    },
    getGridSize:function () {
        return cc.size(this._gridSize.width, this._gridSize.height);
    },
    setGridSize:function (gridSize) {
        this._gridSize.width = parseInt(gridSize.width);
        this._gridSize.height = parseInt(gridSize.height);
    },
    setGridRect:function (rect) {
        this._gridRect = rect;
    },
    getGridRect:function () {
        return this._gridRect;
    },
    getStep:function () {
        return cc.p(this._step.x, this._step.y);
    },
    setStep:function (step) {
        this._step.x = step.x;
        this._step.y = step.y;
    },
    isTextureFlipped:function () {
        return this._isTextureFlipped;
    },
    setTextureFlipped:function (flipped) {
        if (this._isTextureFlipped !== flipped) {
            this._isTextureFlipped = flipped;
            this.calculateVertexPoints();
        }
    },
    initWithSize:function (gridSize, texture, flipped, rect) {
        if (!texture) {
            var director = cc.director;
            var winSize = director.getWinSizeInPixels();
            var POTWide = cc.NextPOT(winSize.width);
            var POTHigh = cc.NextPOT(winSize.height);
            var data = new Uint8Array(POTWide * POTHigh * 4);
            if (!data) {
                cc.log("cocos2d: CCGrid: not enough memory.");
                return false;
            }
            texture = new cc.Texture2D();
            texture.initWithData(data, cc.Texture2D.PIXEL_FORMAT_RGBA8888, POTWide, POTHigh, winSize);
            if (!texture) {
                cc.log("cocos2d: CCGrid: error creating texture");
                return false;
            }
        }
        flipped = flipped || false;
        this._active = false;
        this._reuseGrid = 0;
        this._gridSize = gridSize;
        this._texture = texture;
        this._isTextureFlipped = flipped;
        if(rect === undefined || cc._rectEqualToZero(rect))
        {
            var size = this._texture.getContentSize();
            rect = new cc.rect(0,0,size.width,size.height);
        }
        this._gridRect = rect;
        this._step.x = this._gridRect.width / gridSize.width;
        this._step.y = this._gridRect.height / gridSize.height;
        this._grabber = new cc.Grabber();
        if (!this._grabber)
            return false;
        this._grabber.grab(this._texture);
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
        this.calculateVertexPoints();
        return true;
    },
    beforeDraw:function () {
        this._directorProjection = cc.director.getProjection();
        var size = cc.director.getWinSizeInPixels();
        gl.viewport(0, 0, size.width , size.height);
        this._grabber.beforeRender(this._texture);
    },
    afterDraw:function (target) {
        this._grabber.afterRender(this._texture);
        cc.director.setViewport();
        cc.glBindTexture2D(this._texture);
        this.beforeBlit();
        this.blit(target);
        this.afterBlit();
    },
    beforeBlit: function () {
    },
    afterBlit: function () {
    },
    blit:function () {
        cc.log("cc.GridBase.blit(): Shall be overridden in subclass.");
    },
    reuse:function () {
        cc.log("cc.GridBase.reuse(): Shall be overridden in subclass.");
    },
    calculateVertexPoints:function () {
        cc.log("cc.GridBase.calculateVertexPoints(): Shall be overridden in subclass.");
    },
    set2DProjection:function () {
        var winSize = cc.director.getWinSizeInPixels();
        var gl = cc._renderContext;
        gl.viewport(0, 0, winSize.width , winSize.height);
        cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
        cc.kmGLLoadIdentity();
        var orthoMatrix = cc.math.Matrix4.createOrthographicProjection(0, winSize.width, 0, winSize.height, -1, 1);
        cc.kmGLMultMatrix(orthoMatrix);
        cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
        cc.kmGLLoadIdentity();
        cc.setProjectionMatrixDirty()
    }
});
cc.GridBase.create = function (gridSize, texture, flipped, rect) {
    return new cc.GridBase(gridSize, texture, flipped, rect);
};
cc.Grid3D = cc.GridBase.extend({
    _texCoordinates:null,
    _vertices:null,
    _originalVertices:null,
    _indices:null,
    _texCoordinateBuffer:null,
    _verticesBuffer:null,
    _indicesBuffer:null,
    _needDepthTestForBlit: false,
    _oldDepthTestValue: false,
    _oldDepthWriteValue: false,
    ctor:function (gridSize, texture, flipped, rect) {
        cc.GridBase.prototype.ctor.call(this);
        this._texCoordinates=null;
        this._vertices=null;
        this._originalVertices=null;
        this._indices=null;
        this._texCoordinateBuffer=null;
        this._verticesBuffer=null;
        this._indicesBuffer=null;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
        if(gridSize !== undefined)
            this.initWithSize(gridSize, texture, flipped, rect);
    },
    vertex:function (pos) {
         return this.getVertex(pos);
    },
    getVertex: function(pos){
        if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
            cc.log("cc.Grid3D.vertex() : Numbers must be integers");
        var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
        var locVertices = this._vertices;
        return new cc.Vertex3F(locVertices[index], locVertices[index + 1], locVertices[index + 2]);
    },
    originalVertex:function (pos) {
        return this.getOriginalVertex(pos);
    },
    getOriginalVertex: function(pos) {
        if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
            cc.log("cc.Grid3D.originalVertex() : Numbers must be integers");
        var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
        var locOriginalVertices = this._originalVertices;
        return new cc.Vertex3F(locOriginalVertices[index], locOriginalVertices[index + 1], locOriginalVertices[index + 2]);
    },
    setVertex:function (pos, vertex) {
        if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
            cc.log("cc.Grid3D.setVertex() : Numbers must be integers");
        var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
        var vertArray = this._vertices;
        vertArray[index] = vertex.x;
        vertArray[index + 1] = vertex.y;
        vertArray[index + 2] = vertex.z;
        this._dirty = true;
    },
    beforeBlit: function () {
        if (this._needDepthTestForBlit) {
            var gl = cc._renderContext;
            this._oldDepthTestValue = gl.isEnabled(gl.DEPTH_TEST);
            this._oldDepthWriteValue = gl.getParameter(gl.DEPTH_WRITEMASK);
            gl.enable(gl.DEPTH_TEST);
            gl.depthMask(true);
        }
    },
    afterBlit: function () {
        if (this._needDepthTestForBlit) {
            var gl = cc._renderContext;
            if (this._oldDepthTestValue)
                gl.enable(gl.DEPTH_TEST);
            else
                gl.disable(gl.DEPTH_TEST);
            gl.depthMask(this._oldDepthWriteValue);
        }
    },
    blit:function (target) {
        var n = this._gridSize.width * this._gridSize.height;
        var wt = target._renderCmd._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        var gl = cc._renderContext, locDirty = this._dirty;
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
        if (locDirty)
            gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
        if (locDirty)
            gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
        if (locDirty)
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
        gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
        if (locDirty)
            this._dirty = false;
        cc.incrementGLDraws(1);
    },
    reuse:function () {
        if (this._reuseGrid > 0) {
            var locOriginalVertices = this._originalVertices, locVertices = this._vertices;
            for (var i = 0, len =  this._vertices.length; i < len; i++)
                locOriginalVertices[i] = locVertices[i];
            --this._reuseGrid;
        }
    },
    calculateVertexPoints:function () {
        var gl = cc._renderContext;
        var width = this._texture.pixelsWidth;
        var height = this._texture.pixelsHeight;
        var imageH = this._texture.getContentSizeInPixels().height;
        var locGridSize = this._gridSize;
        var numOfPoints = (locGridSize.width + 1) * (locGridSize.height + 1);
        this._vertices = new Float32Array(numOfPoints * 3);
        this._texCoordinates = new Float32Array(numOfPoints * 2);
        this._indices = new Uint16Array(locGridSize.width * locGridSize.height * 6);
        if(this._verticesBuffer)
            gl.deleteBuffer(this._verticesBuffer);
        this._verticesBuffer = gl.createBuffer();
        if(this._texCoordinateBuffer)
            gl.deleteBuffer(this._texCoordinateBuffer);
        this._texCoordinateBuffer = gl.createBuffer();
        if(this._indicesBuffer)
            gl.deleteBuffer(this._indicesBuffer);
        this._indicesBuffer = gl.createBuffer();
        var x, y, i, locIndices = this._indices, locTexCoordinates = this._texCoordinates;
        var locIsTextureFlipped = this._isTextureFlipped, locVertices = this._vertices;
        for (x = 0; x < locGridSize.width; ++x) {
            for (y = 0; y < locGridSize.height; ++y) {
                var idx = (y * locGridSize.width) + x;
                var x1 = x * this._step.x + this._gridRect.x;
                var x2 = x1 + this._step.x;
                var y1 = y * this._step.y + this._gridRect.y;
                var y2 = y1 + this._step.y;
                var a = (x * (locGridSize.height + 1) + y);
                var b = ((x + 1) * (locGridSize.height + 1) + y);
                var c = ((x + 1) * (locGridSize.height + 1) + (y + 1));
                var d = (x * (locGridSize.height + 1) + (y + 1));
                locIndices[idx * 6] = a;
                locIndices[idx * 6 + 1] = b;
                locIndices[idx * 6 + 2] = d;
                locIndices[idx * 6 + 3] = b;
                locIndices[idx * 6 + 4] = c;
                locIndices[idx * 6 + 5] = d;
                var l1 = [a * 3, b * 3, c * 3, d * 3];
                var e = {x:x1, y:y1, z:0};
                var f = {x:x2, y:y1, z:0};
                var g = {x:x2, y:y2, z:0};
                var h = {x:x1, y:y2, z:0};
                var l2 = [e, f, g, h];
                var tex1 = [a * 2, b * 2, c * 2, d * 2];
                var tex2 = [cc.p(x1, y1), cc.p(x2, y1), cc.p(x2, y2), cc.p(x1, y2)];
                for (i = 0; i < 4; ++i) {
                    locVertices[l1[i]] = l2[i].x;
                    locVertices[l1[i] + 1] = l2[i].y;
                    locVertices[l1[i] + 2] = l2[i].z;
                    locTexCoordinates[tex1[i]] = tex2[i].x / width;
                    if (locIsTextureFlipped)
                        locTexCoordinates[tex1[i] + 1] = (imageH - tex2[i].y) / height;
                    else
                        locTexCoordinates[tex1[i] + 1] = tex2[i].y / height;
                }
            }
        }
        this._originalVertices = new Float32Array(this._vertices);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
        this._dirty = true;
    },
    setNeedDepthTestForBlit: function(needDepthTest){
        this._needDepthTestForBlit = needDepthTest;
    },
    getNeedDepthTestForBlit: function(){
        return this._needDepthTestForBlit;
    }
});
cc.Grid3D.create = function (gridSize, texture, flipped) {
    return new cc.Grid3D(gridSize, texture, flipped);
};
cc.TiledGrid3D = cc.GridBase.extend({
    _texCoordinates:null,
    _vertices:null,
    _originalVertices:null,
    _indices:null,
    _texCoordinateBuffer:null,
    _verticesBuffer:null,
    _indicesBuffer:null,
    ctor:function (gridSize, texture, flipped, rect) {
        cc.GridBase.prototype.ctor.call(this);
        this._texCoordinates=null;
        this._vertices=null;
        this._originalVertices=null;
        this._indices=null;
        this._texCoordinateBuffer=null;
        this._verticesBuffer=null;
        this._indicesBuffer=null;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
        if(gridSize !== undefined)
            this.initWithSize(gridSize, texture, flipped, rect);
    },
    tile:function (pos) {
        return this.getTile(pos);
    },
    getTile: function(pos){
        if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
            cc.log("cc.TiledGrid3D.tile() : Numbers must be integers");
        var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
        var locVertices = this._vertices;
        return new cc.Quad3(new cc.Vertex3F(locVertices[idx], locVertices[idx + 1], locVertices[idx + 2]),
            new cc.Vertex3F(locVertices[idx + 3], locVertices[idx + 4], locVertices[idx + 5]),
            new cc.Vertex3F(locVertices[idx + 6 ], locVertices[idx + 7], locVertices[idx + 8]),
            new cc.Vertex3F(locVertices[idx + 9], locVertices[idx + 10], locVertices[idx + 11]));
    },
    getOriginalTile:function (pos) {
        if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
            cc.log("cc.TiledGrid3D.originalTile() : Numbers must be integers");
        var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
        var locOriginalVertices = this._originalVertices;
        return new cc.Quad3(new cc.Vertex3F(locOriginalVertices[idx], locOriginalVertices[idx + 1], locOriginalVertices[idx + 2]),
            new cc.Vertex3F(locOriginalVertices[idx + 3], locOriginalVertices[idx + 4], locOriginalVertices[idx + 5]),
            new cc.Vertex3F(locOriginalVertices[idx + 6 ], locOriginalVertices[idx + 7], locOriginalVertices[idx + 8]),
            new cc.Vertex3F(locOriginalVertices[idx + 9], locOriginalVertices[idx + 10], locOriginalVertices[idx + 11]));
    },
    originalTile: function(pos) {
        return this.getOriginalTile(pos);
    },
    setTile:function (pos, coords) {
        if(pos.x !== (0| pos.x) || pos.y !== (0| pos.y))
            cc.log("cc.TiledGrid3D.setTile() : Numbers must be integers");
        var idx = (this._gridSize.height * pos.x + pos.y) * 12;
        var locVertices = this._vertices;
        locVertices[idx] = coords.bl.x;
        locVertices[idx + 1] = coords.bl.y;
        locVertices[idx + 2] = coords.bl.z;
        locVertices[idx + 3] = coords.br.x;
        locVertices[idx + 4] = coords.br.y;
        locVertices[idx + 5] = coords.br.z;
        locVertices[idx + 6] = coords.tl.x;
        locVertices[idx + 7] = coords.tl.y;
        locVertices[idx + 8] = coords.tl.z;
        locVertices[idx + 9] = coords.tr.x;
        locVertices[idx + 10] = coords.tr.y;
        locVertices[idx + 11] = coords.tr.z;
        this._dirty = true;
    },
    blit: function (target) {
        var n = this._gridSize.width * this._gridSize.height;
        var wt = target._renderCmd._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        var gl = cc._renderContext, locDirty = this._dirty;
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
        if (locDirty)
            gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 0, this._vertices);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
        if (locDirty)
            gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, this._texCoordinates);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
        if (locDirty)
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
        gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
        if (locDirty)
            this._dirty = false;
        cc.incrementGLDraws(1);
    },
    reuse:function () {
        if (this._reuseGrid > 0) {
            var locVertices = this._vertices, locOriginalVertices = this._originalVertices;
            for (var i = 0; i < locVertices.length; i++)
                locOriginalVertices[i] = locVertices[i];
            --this._reuseGrid;
        }
    },
    calculateVertexPoints:function () {
        var width = this._texture.pixelsWidth;
        var height = this._texture.pixelsHeight;
        var imageH = this._texture.getContentSizeInPixels().height;
        var locGridSize = this._gridSize;
        var numQuads = locGridSize.width * locGridSize.height;
        this._vertices = new Float32Array(numQuads * 12);
        this._texCoordinates = new Float32Array(numQuads * 8);
        this._indices = new Uint16Array(numQuads * 6);
        var gl = cc._renderContext;
        if(this._verticesBuffer)
            gl.deleteBuffer(this._verticesBuffer);
        this._verticesBuffer = gl.createBuffer();
        if(this._texCoordinateBuffer)
            gl.deleteBuffer(this._texCoordinateBuffer);
        this._texCoordinateBuffer = gl.createBuffer();
        if(this._indicesBuffer)
            gl.deleteBuffer(this._indicesBuffer);
        this._indicesBuffer = gl.createBuffer();
        var x, y, i = 0;
        var locStep = this._step, locVertices = this._vertices, locTexCoords = this._texCoordinates, locIsTextureFlipped = this._isTextureFlipped;
        for (x = 0; x < locGridSize.width; x++) {
            for (y = 0; y < locGridSize.height; y++) {
                var x1 = x * locStep.x;
                var x2 = x1 + locStep.x;
                var y1 = y * locStep.y;
                var y2 = y1 + locStep.y;
                locVertices[i * 12] = x1;
                locVertices[i * 12 + 1] = y1;
                locVertices[i * 12 + 2] = 0;
                locVertices[i * 12 + 3] = x2;
                locVertices[i * 12 + 4] = y1;
                locVertices[i * 12 + 5] = 0;
                locVertices[i * 12 + 6] = x1;
                locVertices[i * 12 + 7] = y2;
                locVertices[i * 12 + 8] = 0;
                locVertices[i * 12 + 9] = x2;
                locVertices[i * 12 + 10] = y2;
                locVertices[i * 12 + 11] = 0;
                var newY1 = y1;
                var newY2 = y2;
                if (locIsTextureFlipped) {
                    newY1 = imageH - y1;
                    newY2 = imageH - y2;
                }
                locTexCoords[i * 8] = x1 / width;
                locTexCoords[i * 8 + 1] = newY1 / height;
                locTexCoords[i * 8 + 2] = x2 / width;
                locTexCoords[i * 8 + 3] = newY1 / height;
                locTexCoords[i * 8 + 4] = x1 / width;
                locTexCoords[i * 8 + 5] = newY2 / height;
                locTexCoords[i * 8 + 6] = x2 / width;
                locTexCoords[i * 8 + 7] = newY2 / height;
                i++;
            }
        }
        var locIndices = this._indices;
        for (x = 0; x < numQuads; x++) {
            locIndices[x * 6 + 0] = (x * 4 + 0);
            locIndices[x * 6 + 1] = (x * 4 + 1);
            locIndices[x * 6 + 2] = (x * 4 + 2);
            locIndices[x * 6 + 3] = (x * 4 + 1);
            locIndices[x * 6 + 4] = (x * 4 + 2);
            locIndices[x * 6 + 5] = (x * 4 + 3);
        }
        this._originalVertices = new Float32Array(this._vertices);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._vertices, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordinateBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, this._texCoordinates, gl.DYNAMIC_DRAW);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.DYNAMIC_DRAW);
        this._dirty = true;
    }
});
cc.TiledGrid3D.create = function (gridSize, texture, flipped) {
    return new cc.TiledGrid3D(gridSize, texture, flipped);
};
cc.Grabber = cc.Class.extend({
    _FBO:null,
    _oldFBO:null,
    _oldClearColor:null,
    _gl:null,
    ctor:function () {
        cc.sys._checkWebGLRenderMode();
        this._gl = cc._renderContext;
        this._oldClearColor = [0, 0, 0, 0];
        this._oldFBO = null;
        this._FBO = this._gl.createFramebuffer();
    },
    grab:function (texture) {
        var locGL = this._gl;
        this._oldFBO = locGL.getParameter(locGL.FRAMEBUFFER_BINDING);
        locGL.bindFramebuffer(locGL.FRAMEBUFFER, this._FBO);
        locGL.framebufferTexture2D(locGL.FRAMEBUFFER, locGL.COLOR_ATTACHMENT0, locGL.TEXTURE_2D, texture._webTextureObj, 0);
        var status = locGL.checkFramebufferStatus(locGL.FRAMEBUFFER);
        if (status !== locGL.FRAMEBUFFER_COMPLETE)
            cc.log("Frame Grabber: could not attach texture to frmaebuffer");
        locGL.bindFramebuffer(locGL.FRAMEBUFFER, this._oldFBO);
    },
    beforeRender:function (texture) {
        var locGL = this._gl;
        this._oldFBO = locGL.getParameter(locGL.FRAMEBUFFER_BINDING);
        locGL.bindFramebuffer(locGL.FRAMEBUFFER, this._FBO);
        this._oldClearColor = locGL.getParameter(locGL.COLOR_CLEAR_VALUE);
        locGL.clearColor(0, 0, 0, 0);
        locGL.clear(locGL.COLOR_BUFFER_BIT | locGL.DEPTH_BUFFER_BIT);
    },
    afterRender:function (texture) {
        var locGL = this._gl;
        locGL.bindFramebuffer(locGL.FRAMEBUFFER, this._oldFBO);
        locGL.colorMask(true, true, true, true);
    },
    destroy:function(){
        this._gl.deleteFramebuffer(this._FBO);
    }
});
cc.GridAction = cc.ActionInterval.extend({
    _gridSize:null,
    _gridNodeTarget:null,
    ctor:function(duration, gridSize){
        cc.sys._checkWebGLRenderMode();
        cc.ActionInterval.prototype.ctor.call(this);
        this._gridSize = cc.size(0,0);
        gridSize && this.initWithDuration(duration, gridSize);
    },
    _cacheTargetAsGridNode:function (target) {
        this._gridNodeTarget = target;
    },
    clone:function(){
        var action = new cc.GridAction();
        var locGridSize = this._gridSize;
        action.initWithDuration(this._duration, cc.size(locGridSize.width, locGridSize.height));
        return action;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        cc.renderer.childrenOrderDirty = true;
        this._cacheTargetAsGridNode(target);
        var newGrid = this.getGrid();
        var targetGrid = this._gridNodeTarget.getGrid();
        if (targetGrid && targetGrid.getReuseGrid() > 0) {
            var locGridSize = targetGrid.getGridSize();
            if (targetGrid.isActive() && (locGridSize.width === this._gridSize.width) && (locGridSize.height === this._gridSize.height))
                targetGrid.reuse();
        } else {
            if (targetGrid && targetGrid.isActive())
                targetGrid.setActive(false);
            this._gridNodeTarget.setGrid(newGrid);
            this._gridNodeTarget.getGrid().setActive(true);
        }
    },
    reverse:function () {
        return new cc.ReverseTime(this);
    },
    initWithDuration:function (duration, gridSize) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._gridSize.width = gridSize.width;
            this._gridSize.height = gridSize.height;
            return true;
        }
        return false;
    },
    getGrid:function () {
        cc.log("cc.GridAction.getGrid(): it should be overridden in subclass.");
    }
});
cc.gridAction = function (duration, gridSize) {
    return new cc.GridAction(duration, gridSize);
};
cc.GridAction.create = cc.gridAction;
cc.Grid3DAction = cc.GridAction.extend({
    getGrid:function () {
        return new cc.Grid3D(this._gridSize, undefined, undefined, this._gridNodeTarget.getGridRect());
    },
    getGridRect:function () {
        return this._gridNodeTarget.getGridRect();
    },
    vertex:function (position) {
        return this.getVertex(position);
    },
    getVertex: function(position){
        return this.target.grid.getVertex(position);
    },
    originalVertex:function (position) {
        return this.getOriginalVertex(position);
    },
    getOriginalVertex:function (position) {
        return this.target.grid.originalVertex(position);
    },
    setVertex:function (position, vertex) {
        this.target.grid.setVertex(position, vertex);
    }
});
cc.grid3DAction = function (duration, gridSize) {
    return new cc.Grid3DAction(duration, gridSize);
};
cc.Grid3DAction.create = cc.grid3DAction;
cc.TiledGrid3DAction = cc.GridAction.extend({
    tile:function (position) {
        return this.getTile(position);
    },
    getTile:function (position) {
        return this.target.grid.tile(position);
    },
    originalTile:function (position) {
        return this.getOriginalTile(position);
    },
    getOriginalTile:function (position) {
        return this.target.grid.originalTile(position);
    },
    setTile:function (position, coords) {
        this.target.grid.setTile(position, coords);
    },
    getGrid:function () {
        return new cc.TiledGrid3D(this._gridSize, undefined, undefined, this._gridNodeTarget.getGridRect());
    }
});
cc.tiledGrid3DAction = function (duration, gridSize) {
    return new cc.TiledGrid3DAction(duration, gridSize);
};
cc.TiledGrid3DAction.create = cc.tiledGrid3DAction;
cc.StopGrid = cc.ActionInstant.extend({
    startWithTarget:function (target) {
        cc.ActionInstant.prototype.startWithTarget.call(this, target);
        cc.renderer.childrenOrderDirty = true;
        var grid = this.target.grid;
        if (grid && grid.isActive())
            grid.setActive(false);
    }
});
cc.stopGrid = function () {
    return new cc.StopGrid();
};
cc.StopGrid.create = cc.stopGrid;
cc.ReuseGrid = cc.ActionInstant.extend({
    _times:null,
    ctor: function(times) {
        cc.ActionInstant.prototype.ctor.call(this);
        times !== undefined && this.initWithTimes(times);
    },
    initWithTimes:function (times) {
        this._times = times;
        return true;
    },
    startWithTarget:function (target) {
        cc.ActionInstant.prototype.startWithTarget.call(this, target);
        cc.renderer.childrenOrderDirty = true;
        if (this.target.grid && this.target.grid.isActive())
            this.target.grid.setReuseGrid(this.target.grid.getReuseGrid() + this._times);
    }
});
cc.reuseGrid = function (times) {
    return new cc.ReuseGrid(times);
};
cc.ReuseGrid.create = cc.reuseGrid;
cc.Waves3D = cc.Grid3DAction.extend({
    _waves: 0,
    _amplitude: 0,
    _amplitudeRate: 0,
    ctor:function (duration, gridSize, waves, amplitude) {
        cc.GridAction.prototype.ctor.call(this);
        amplitude !== undefined && this.initWithDuration(duration, gridSize, waves, amplitude);
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, waves, amplitude) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._waves = waves;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locGridSize = this._gridSize;
        var locAmplitude = this._amplitude, locPos = cc.p(0, 0);
        var locAmplitudeRate = this._amplitudeRate, locWaves = this._waves;
        for (var i = 0; i < locGridSize.width + 1; ++i) {
            for (var j = 0; j < locGridSize.height + 1; ++j) {
                locPos.x = i;
                locPos.y = j;
                var v = this.originalVertex(locPos);
                v.z += (Math.sin(Math.PI * dt * locWaves * 2 + (v.y + v.x) * 0.01) * locAmplitude * locAmplitudeRate);
                this.setVertex(locPos, v);
            }
        }
    }
});
cc.waves3D = function (duration, gridSize, waves, amplitude) {
    return new cc.Waves3D(duration, gridSize, waves, amplitude);
};
cc.Waves3D.create = cc.waves3D;
cc.FlipX3D = cc.Grid3DAction.extend({
    ctor: function(duration) {
        if (duration !== undefined)
            cc.GridAction.prototype.ctor.call(this, duration, cc.size(1, 1));
        else cc.GridAction.prototype.ctor.call(this);
    },
    initWithDuration:function (duration) {
        return cc.Grid3DAction.prototype.initWithDuration.call(this, duration, cc.size(1, 1));
    },
    initWithSize:function (gridSize, duration) {
        if (gridSize.width !== 1 || gridSize.height !== 1) {
            cc.log("Grid size must be (1,1)");
            return false;
        }
        return  cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize);
    },
    update:function (dt) {
        var angle = Math.PI * dt;
        var mz = Math.sin(angle);
        angle = angle / 2.0;
        var mx = Math.cos(angle);
        var diff = new cc.Vertex3F();
        var tempVer = cc.p(0, 0);
        tempVer.x = tempVer.y = 1;
        var v0 = this.originalVertex(tempVer);
        tempVer.x = tempVer.y = 0;
        var v1 = this.originalVertex(tempVer);
        var x0 = v0.x;
        var x1 = v1.x;
        var x;
        var a, b, c, d;
        if (x0 > x1) {
            a = cc.p(0, 0);
            b = cc.p(0, 1);
            c = cc.p(1, 0);
            d = cc.p(1, 1);
            x = x0;
        } else {
            c = cc.p(0, 0);
            d = cc.p(0, 1);
            a = cc.p(1, 0);
            b = cc.p(1, 1);
            x = x1;
        }
        diff.x = ( x - x * mx );
        diff.z = Math.abs(parseFloat((x * mz) / 4.0));
        var v = this.originalVertex(a);
        v.x = diff.x;
        v.z += diff.z;
        this.setVertex(a, v);
        v = this.originalVertex(b);
        v.x = diff.x;
        v.z += diff.z;
        this.setVertex(b, v);
        v = this.originalVertex(c);
        v.x -= diff.x;
        v.z -= diff.z;
        this.setVertex(c, v);
        v = this.originalVertex(d);
        v.x -= diff.x;
        v.z -= diff.z;
        this.setVertex(d, v);
    }
});
cc.flipX3D = function (duration) {
    return new cc.FlipX3D(duration);
};
cc.FlipX3D.create = cc.flipX3D;
cc.FlipY3D = cc.FlipX3D.extend({
    ctor: function(duration) {
        if (duration !== undefined)
            cc.GridAction.prototype.ctor.call(this, duration, cc.size(1, 1));
        else cc.GridAction.prototype.ctor.call(this);
    },
    update:function (dt) {
        var angle = Math.PI * dt;
        var mz = Math.sin(angle);
        angle = angle / 2.0;
        var my = Math.cos(angle);
        var diff = new cc.Vertex3F();
        var tempP = cc.p(0, 0);
        tempP.x = tempP.y = 1;
        var v0 = this.originalVertex(tempP);
        tempP.x = tempP.y = 0;
        var v1 = this.originalVertex(tempP);
        var y0 = v0.y;
        var y1 = v1.y;
        var y;
        var a, b, c, d;
        if (y0 > y1) {
            a = cc.p(0, 0);
            b = cc.p(0, 1);
            c = cc.p(1, 0);
            d = cc.p(1, 1);
            y = y0;
        } else {
            b = cc.p(0, 0);
            a = cc.p(0, 1);
            d = cc.p(1, 0);
            c = cc.p(1, 1);
            y = y1;
        }
        diff.y = y - y * my;
        diff.z = Math.abs(parseFloat(y * mz) / 4.0);
        var v = this.originalVertex(a);
        v.y = diff.y;
        v.z += diff.z;
        this.setVertex(a, v);
        v = this.originalVertex(b);
        v.y -= diff.y;
        v.z -= diff.z;
        this.setVertex(b, v);
        v = this.originalVertex(c);
        v.y = diff.y;
        v.z += diff.z;
        this.setVertex(c, v);
        v = this.originalVertex(d);
        v.y -= diff.y;
        v.z -= diff.z;
        this.setVertex(d, v);
    }
});
cc.flipY3D = function (duration) {
    return new cc.FlipY3D(duration);
};
cc.FlipY3D.create = cc.flipY3D;
cc.Lens3D = cc.Grid3DAction.extend({
    _position:null,
    _radius:0,
    _lensEffect:0,
    _concave:false,
    _dirty:false,
    ctor:function (duration, gridSize, position, radius) {
        cc.GridAction.prototype.ctor.call(this);
        this._position = cc.p(0, 0);
        radius !== undefined && this.initWithDuration(duration, gridSize, position, radius);
    },
    getLensEffect:function () {
        return this._lensEffect;
    },
    setLensEffect:function (lensEffect) {
        this._lensEffect = lensEffect;
    },
    setConcave:function (concave) {
        this._concave = concave;
    },
    getPosition:function () {
        return this._position;
    },
    setPosition:function (position) {
        if (!cc.pointEqualToPoint(position, this._position)) {
            this._position.x = position.x;
            this._position.y = position.y;
            this._dirty = true;
        }
    },
    initWithDuration:function (duration, gridSize, position, radius) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this.setPosition(position);
            this._radius = radius;
            this._lensEffect = 0.7;
            this._dirty = true;
            return true;
        }
        return false;
    },
    update:function (dt) {
        if (this._dirty) {
            var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height;
            var locRadius = this._radius, locLensEffect = this._lensEffect;
            var locPos = cc.p(0, 0);
            var vect = cc.p(0, 0);
            var v, r, l, new_r, pre_log;
            for (var i = 0; i < locGridSizeWidth + 1; ++i) {
                for (var j = 0; j < locGridSizeHeight + 1; ++j) {
                    locPos.x = i;
                    locPos.y = j;
                    v = this.originalVertex(locPos);
                    vect.x = this._position.x - v.x;
                    vect.y = this._position.y - v.y;
                    r = cc.pLength(vect);
                    if (r < locRadius) {
                        r = locRadius - r;
                        pre_log = r / locRadius;
                        if (pre_log === 0)
                            pre_log = 0.001;
                        l = Math.log(pre_log) * locLensEffect;
                        new_r = Math.exp(l) * locRadius;
                        r = cc.pLength(vect);
                        if (r > 0) {
                            vect.x = vect.x / r;
                            vect.y = vect.y / r;
                            vect.x = vect.x * new_r;
                            vect.y = vect.y * new_r;
                            v.z += cc.pLength(vect) * locLensEffect;
                        }
                    }
                    this.setVertex(locPos, v);
                }
            }
            this._dirty = false;
        }
    }
});
cc.lens3D = function (duration, gridSize, position, radius) {
    return new cc.Lens3D(duration, gridSize, position, radius);
};
cc.Lens3D.create = cc.lens3D;
cc.Ripple3D = cc.Grid3DAction.extend({
    _position: null,
    _radius: 0,
    _waves: 0,
    _amplitude: 0,
    _amplitudeRate: 0,
    ctor:function (duration, gridSize, position, radius, waves, amplitude) {
        cc.GridAction.prototype.ctor.call(this);
        this._position = cc.p(0, 0);
        amplitude !== undefined && this.initWithDuration(duration, gridSize, position, radius, waves, amplitude);
    },
    getPosition:function () {
        return this._position;
    },
    setPosition:function (position) {
        this._position.x = position.x;
        this._position.y = position.y;
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, position, radius, waves, amplitude) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this.setPosition(position);
            this._radius = radius;
            this._waves = waves;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height;
        var locPos = cc.p(0, 0), locRadius = this._radius;
        var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
        var v, r, tempPos = cc.p(0, 0);
        for (var i = 0; i < (locGridSizeWidth + 1); ++i) {
            for (var j = 0; j < (locGridSizeHeight + 1); ++j) {
                locPos.x = i;
                locPos.y = j;
                v = this.originalVertex(locPos);
                tempPos.x = this._position.x - v.x;
                tempPos.y = this._position.y - v.y;
                r = cc.pLength(tempPos);
                if (r < locRadius) {
                    r = locRadius - r;
                    var rate = Math.pow(r / locRadius, 2);
                    v.z += (Math.sin(dt * Math.PI * locWaves * 2 + r * 0.1) * locAmplitude * locAmplitudeRate * rate);
                }
                this.setVertex(locPos, v);
            }
        }
    }
});
cc.ripple3D = function (duration, gridSize, position, radius, waves, amplitude) {
    return new cc.Ripple3D(duration, gridSize, position, radius, waves, amplitude);
};
cc.Ripple3D.create = cc.ripple3D;
cc.Shaky3D = cc.Grid3DAction.extend({
    _randRange: 0,
    _shakeZ: false,
    ctor:function (duration, gridSize, range, shakeZ) {
        cc.GridAction.prototype.ctor.call(this);
        shakeZ !== undefined && this.initWithDuration(duration, gridSize, range, shakeZ);
    },
    initWithDuration:function (duration, gridSize, range, shakeZ) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._randRange = range;
            this._shakeZ = shakeZ;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height;
        var locRandRange = this._randRange, locShakeZ = this._shakeZ, locP = cc.p(0, 0);
        var v;
        for (var i = 0; i < (locGridSizeWidth + 1); ++i) {
            for (var j = 0; j < (locGridSizeHeight + 1); ++j) {
                locP.x = i;
                locP.y = j;
                v = this.originalVertex(locP);
                v.x += (cc.rand() % (locRandRange * 2)) - locRandRange;
                v.y += (cc.rand() % (locRandRange * 2)) - locRandRange;
                if (locShakeZ)
                    v.z += (cc.rand() % (locRandRange * 2)) - locRandRange;
                this.setVertex(locP, v);
            }
        }
    }
});
cc.shaky3D = function (duration, gridSize, range, shakeZ) {
    return new cc.Shaky3D(duration, gridSize, range, shakeZ);
};
cc.Shaky3D.create = cc.shaky3D;
cc.Liquid = cc.Grid3DAction.extend({
    _waves: 0,
    _amplitude: 0,
    _amplitudeRate: 0,
    ctor: function (duration, gridSize, waves, amplitude) {
        cc.GridAction.prototype.ctor.call(this);
        amplitude !== undefined && this.initWithDuration(duration, gridSize, waves, amplitude);
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, waves, amplitude) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._waves = waves;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0);
        var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
        var v;
        for (var i = 1; i < locSizeWidth; ++i) {
            for (var j = 1; j < locSizeHeight; ++j) {
                locPos.x = i;
                locPos.y = j;
                v = this.originalVertex(locPos);
                v.x = (v.x + (Math.sin(dt * Math.PI * locWaves * 2 + v.x * .01) * locAmplitude * locAmplitudeRate));
                v.y = (v.y + (Math.sin(dt * Math.PI * locWaves * 2 + v.y * .01) * locAmplitude * locAmplitudeRate));
                this.setVertex(locPos, v);
            }
        }
    }
});
cc.liquid = function (duration, gridSize, waves, amplitude) {
    return new cc.Liquid(duration, gridSize, waves, amplitude);
};
cc.Liquid.create = cc.liquid;
cc.Waves = cc.Grid3DAction.extend({
    _waves: 0,
    _amplitude: 0,
    _amplitudeRate: 0,
    _vertical: false,
    _horizontal: false,
    ctor: function (duration, gridSize, waves, amplitude, horizontal, vertical) {
        cc.GridAction.prototype.ctor.call(this);
        vertical !== undefined && this.initWithDuration(duration, gridSize, waves, amplitude, horizontal, vertical);
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, waves, amplitude, horizontal, vertical) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._waves = waves;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            this._horizontal = horizontal;
            this._vertical = vertical;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0);
        var locVertical = this._vertical, locHorizontal = this._horizontal;
        var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
        var v;
        for (var i = 0; i < locSizeWidth + 1; ++i) {
            for (var j = 0; j < locSizeHeight + 1; ++j) {
                locPos.x = i;
                locPos.y = j;
                v = this.originalVertex(locPos);
                if (locVertical)
                    v.x = (v.x + (Math.sin(dt * Math.PI * locWaves * 2 + v.y * .01) * locAmplitude * locAmplitudeRate));
                if (locHorizontal)
                    v.y = (v.y + (Math.sin(dt * Math.PI * locWaves * 2 + v.x * .01) * locAmplitude * locAmplitudeRate));
                this.setVertex(locPos, v);
            }
        }
    }
});
cc.waves = function (duration, gridSize, waves, amplitude, horizontal, vertical) {
    return new cc.Waves(duration, gridSize, waves, amplitude, horizontal, vertical);
};
cc.Waves.create = cc.waves;
cc.Twirl = cc.Grid3DAction.extend({
    _position: null,
    _twirls: 0,
    _amplitude: 0,
    _amplitudeRate: 0,
    ctor:function (duration, gridSize, position, twirls, amplitude) {
        cc.GridAction.prototype.ctor.call(this);
        this._position = cc.p(0, 0);
        amplitude !== undefined && this.initWithDuration(duration, gridSize, position, twirls, amplitude);
    },
    getPosition:function () {
        return this._position;
    },
    setPosition:function (position) {
        this._position.x = position.x;
        this._position.y = position.y;
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, position, twirls, amplitude) {
        if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this.setPosition(position);
            this._twirls = twirls;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var c = this._position;
        var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0);
        var amp = 0.1 * this._amplitude * this._amplitudeRate;
        var locTwirls = this._twirls;
        var v, a, dX, dY, avg = cc.p(0, 0);
        for (var i = 0; i < (locSizeWidth + 1); ++i) {
            for (var j = 0; j < (locSizeHeight + 1); ++j) {
                locPos.x = i;
                locPos.y = j;
                v = this.originalVertex(locPos);
                avg.x = i - (locSizeWidth / 2.0);
                avg.y = j - (locSizeHeight / 2.0);
                a = cc.pLength(avg) * Math.cos(Math.PI / 2.0 + dt * Math.PI * locTwirls * 2) * amp;
                dX = Math.sin(a) * (v.y - c.y) + Math.cos(a) * (v.x - c.x);
                dY = Math.cos(a) * (v.y - c.y) - Math.sin(a) * (v.x - c.x);
                v.x = c.x + dX;
                v.y = c.y + dY;
                this.setVertex(locPos, v);
            }
        }
    }
});
cc.twirl = function (duration, gridSize, position, twirls, amplitude) {
    return new cc.Twirl(duration, gridSize, position, twirls, amplitude);
};
cc.Twirl.create = cc.twirl;
cc.ShakyTiles3D = cc.TiledGrid3DAction.extend({
    _randRange:0,
    _shakeZ:false,
    ctor:function (duration, gridSize, range, shakeZ) {
        cc.GridAction.prototype.ctor.call(this);
        shakeZ !== undefined && this.initWithDuration(duration, gridSize, range, shakeZ);
    },
    initWithDuration:function (duration, gridSize, range, shakeZ) {
        if (cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._randRange = range;
            this._shakeZ = shakeZ;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locGridSize = this._gridSize, locRandRange = this._randRange;
        var locPos = cc.p(0, 0);
        for (var i = 0; i < locGridSize.width; ++i) {
            for (var j = 0; j < locGridSize.height; ++j) {
                locPos.x = i;
                locPos.y = j;
                var coords = this.originalTile(locPos);
                coords.bl.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.br.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.tl.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.tr.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.bl.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.br.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.tl.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                coords.tr.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                if (this._shakeZ) {
                    coords.bl.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.br.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.tl.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.tr.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                }
                this.setTile(locPos, coords);
            }
        }
    }
});
cc.shakyTiles3D = function (duration, gridSize, range, shakeZ) {
    return new cc.ShakyTiles3D(duration, gridSize, range, shakeZ);
};
cc.ShakyTiles3D.create = cc.shakyTiles3D;
cc.ShatteredTiles3D = cc.TiledGrid3DAction.extend({
    _randRange:0,
    _once:false,
    _shatterZ:false,
    ctor:function (duration, gridSize, range, shatterZ) {
        cc.GridAction.prototype.ctor.call(this);
        shatterZ !== undefined && this.initWithDuration(duration, gridSize, range, shatterZ);
    },
    initWithDuration:function (duration, gridSize, range, shatterZ) {
        if (cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._once = false;
            this._randRange = range;
            this._shatterZ = shatterZ;
            return true;
        }
        return false;
    },
    update:function (dt) {
        if (this._once === false) {
            var locGridSize = this._gridSize, locRandRange = this._randRange;
            var coords, locPos = cc.p(0, 0);
            for (var i = 0; i < locGridSize.width; ++i) {
                for (var j = 0; j < locGridSize.height; ++j) {
                    locPos.x = i;
                    locPos.y = j;
                    coords = this.originalTile(locPos);
                    coords.bl.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.br.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.tl.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.tr.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.bl.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.br.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.tl.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    coords.tr.y += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    if (this._shatterZ) {
                        coords.bl.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                        coords.br.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                        coords.tl.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                        coords.tr.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange;
                    }
                    this.setTile(locPos, coords);
                }
            }
            this._once = true;
        }
    }
});
cc.shatteredTiles3D = function (duration, gridSize, range, shatterZ) {
    return new cc.ShatteredTiles3D(duration, gridSize, range, shatterZ);
};
cc.ShatteredTiles3D.create = cc.shatteredTiles3D;
cc.Tile = function (position, startPosition, delta) {
    this.position = position || cc.p(0,0);
    this.startPosition = startPosition || cc.p(0,0);
    this.delta = delta || cc.p(0,0);
};
cc.ShuffleTiles = cc.TiledGrid3DAction.extend({
    _seed:0,
    _tilesCount:0,
    _tilesOrder:null,
    _tiles:null,
    ctor:function (duration, gridSize, seed) {
        cc.GridAction.prototype.ctor.call(this);
        this._tilesOrder = [];
        this._tiles = [];
        seed !== undefined && this.initWithDuration(duration, gridSize, seed);
    },
    initWithDuration:function (duration, gridSize, seed) {
        if (cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._seed = seed;
            this._tilesOrder.length = 0;
            this._tiles.length = 0;
            return true;
        }
        return false;
    },
    shuffle:function (array, len) {
        for (var i = len - 1; i >= 0; i--) {
            var j = 0 | (cc.rand() % (i + 1));
            var v = array[i];
            array[i] = array[j];
            array[j] = v;
        }
    },
    getDelta:function (pos) {
        var locGridSize = this._gridSize;
        var idx = pos.width * locGridSize.height + pos.height;
        return cc.size(((this._tilesOrder[idx] / locGridSize.height) - pos.width),
            ((this._tilesOrder[idx] % locGridSize.height) - pos.height));
    },
    placeTile:function (pos, tile) {
        var coords = this.originalTile(pos);
        var step = this.target.grid.getStep();
        var locPosition = tile.position;
        coords.bl.x += (locPosition.x * step.x);
        coords.bl.y += (locPosition.y * step.y);
        coords.br.x += (locPosition.x * step.x);
        coords.br.y += (locPosition.y * step.y);
        coords.tl.x += (locPosition.x * step.x);
        coords.tl.y += (locPosition.y * step.y);
        coords.tr.x += (locPosition.x * step.x);
        coords.tr.y += (locPosition.y * step.y);
        this.setTile(pos, coords);
    },
    startWithTarget:function (target) {
        cc.TiledGrid3DAction.prototype.startWithTarget.call(this, target);
        var locGridSize = this._gridSize;
        this._tilesCount = locGridSize.width * locGridSize.height;
        var locTilesOrder = this._tilesOrder;
        locTilesOrder.length = 0;
        for (var k = 0; k < this._tilesCount; ++k)
            locTilesOrder[k] = k;
        this.shuffle(locTilesOrder, this._tilesCount);
        var locTiles = this._tiles ;
        locTiles.length = 0;
        var tileIndex = 0, tempSize = cc.size(0,0);
        for (var i = 0; i < locGridSize.width; ++i) {
            for (var j = 0; j < locGridSize.height; ++j) {
                locTiles[tileIndex] = new cc.Tile();
                locTiles[tileIndex].position = cc.p(i, j);
                locTiles[tileIndex].startPosition = cc.p(i, j);
                tempSize.width = i;
                tempSize.height = j;
                locTiles[tileIndex].delta = this.getDelta(tempSize);
                ++tileIndex;
            }
        }
    },
    update:function (dt) {
        var tileIndex = 0, locGridSize = this._gridSize, locTiles = this._tiles;
        var selTile, locPos = cc.p(0, 0);
        for (var i = 0; i < locGridSize.width; ++i) {
            for (var j = 0; j < locGridSize.height; ++j) {
                locPos.x = i;
                locPos.y = j;
                selTile = locTiles[tileIndex];
                selTile.position.x = selTile.delta.width * dt;
                selTile.position.y = selTile.delta.height * dt;
                this.placeTile(locPos, selTile);
                ++tileIndex;
            }
        }
    }
});
cc.shuffleTiles = function (duration, gridSize, seed) {
    return new cc.ShuffleTiles(duration, gridSize, seed);
};
cc.ShuffleTiles.create = cc.shuffleTiles;
cc.FadeOutTRTiles = cc.TiledGrid3DAction.extend({
    testFunc:function (pos, time) {
        var locX = this._gridSize.width * time;
        var locY = this._gridSize.height * time;
        if (locX === this._gridSize.width && locY === this._gridSize.height) return 0.0;
        if ((locX + locY) === 0.0)
            return 1.0;
        return Math.pow((pos.x + pos.y) / (locX + locY), 6);
    },
    turnOnTile:function (pos) {
        this.setTile(pos, this.originalTile(pos));
    },
    turnOffTile:function (pos) {
        this.setTile(pos, new cc.Quad3());
    },
    transformTile:function (pos, distance) {
        var coords = this.originalTile(pos);
        var step = this.target.grid.getStep();
        coords.bl.x += (step.x / 2) * (1.0 - distance);
        coords.bl.y += (step.y / 2) * (1.0 - distance);
        coords.br.x -= (step.x / 2) * (1.0 - distance);
        coords.br.y += (step.y / 2) * (1.0 - distance);
        coords.tl.x += (step.x / 2) * (1.0 - distance);
        coords.tl.y -= (step.y / 2) * (1.0 - distance);
        coords.tr.x -= (step.x / 2) * (1.0 - distance);
        coords.tr.y -= (step.y / 2) * (1.0 - distance);
        this.setTile(pos, coords);
    },
    update:function (dt) {
        var locGridSize = this._gridSize;
        var locPos = cc.p(0, 0),  distance;
        for (var i = 0; i < locGridSize.width; ++i) {
            for (var j = 0; j < locGridSize.height; ++j) {
                locPos.x = i;
                locPos.y = j;
                distance = this.testFunc(locPos, dt);
                if (distance === 0)
                    this.turnOffTile(locPos);
                else if (distance < 1)
                    this.transformTile(locPos, distance);
                else
                    this.turnOnTile(locPos);
            }
        }
    }
});
cc.fadeOutTRTiles = function (duration, gridSize) {
    return new cc.FadeOutTRTiles(duration, gridSize);
};
cc.FadeOutTRTiles.create = cc.fadeOutTRTiles;
cc.FadeOutBLTiles = cc.FadeOutTRTiles.extend({
    testFunc:function (pos, time) {
        var locX = this._gridSize.width * (1.0 - time);
        var locY = this._gridSize.height * (1.0 - time);
        if ((locX + locY) === 0)
            return 0.0;
        if ((pos.x + pos.y) === 0)
            return 1.0;
        return Math.pow((locX + locY) / (pos.x + pos.y), 6);
    }
});
cc.fadeOutBLTiles = function (duration, gridSize) {
    return new cc.FadeOutBLTiles(duration, gridSize);
};
cc.FadeOutBLTiles.create = cc.fadeOutBLTiles;
cc.FadeOutUpTiles = cc.FadeOutTRTiles.extend({
    testFunc:function (pos, time) {
        var locY = this._gridSize.height * time;
        if( locY === this._gridSize.height) return 0.0;
        if (locY === 0.0) return 1.0;
        return Math.pow(pos.y / locY, 6);
    },
    transformTile:function (pos, distance) {
        var coords = this.originalTile(pos);
        var step = this.target.grid.getStep();
        coords.bl.y += (step.y / 2) * (1.0 - distance);
        coords.br.y += (step.y / 2) * (1.0 - distance);
        coords.tl.y -= (step.y / 2) * (1.0 - distance);
        coords.tr.y -= (step.y / 2) * (1.0 - distance);
        this.setTile(pos, coords);
    }
});
cc.fadeOutUpTiles = function (duration, gridSize) {
    return new cc.FadeOutUpTiles(duration, gridSize);
};
cc.FadeOutUpTiles.create = cc.fadeOutUpTiles;
cc.FadeOutDownTiles = cc.FadeOutUpTiles.extend({
    testFunc:function (pos, time) {
        var locY = this._gridSize.height * (1.0 - time);
        if( locY === 0.0 ) return 0.0;
        if (pos.y === 0) return 1.0;
        return Math.pow(locY / pos.y, 6);
    }
});
cc.fadeOutDownTiles = function (duration, gridSize) {
    return new cc.FadeOutDownTiles(duration, gridSize);
};
cc.FadeOutDownTiles.create = cc.fadeOutDownTiles;
cc.TurnOffTiles = cc.TiledGrid3DAction.extend({
    _seed:null,
    _tilesCount:0,
    _tilesOrder:null,
    ctor:function (duration, gridSize, seed) {
        cc.GridAction.prototype.ctor.call(this);
        this._tilesOrder = [];
        gridSize !== undefined && this.initWithDuration(duration, gridSize, seed);
    },
    initWithDuration:function (duration, gridSize, seed) {
        if (cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._seed = seed || 0;
            this._tilesOrder.length = 0;
            return true;
        }
        return false;
    },
    shuffle:function (array, len) {
        for (var i = len - 1; i >= 0; i--) {
            var j = 0 | (cc.rand() % (i + 1));
            var v = array[i];
            array[i] = array[j];
            array[j] = v;
        }
    },
    turnOnTile:function (pos) {
        this.setTile(pos, this.originalTile(pos));
    },
    turnOffTile:function (pos) {
        this.setTile(pos, new cc.Quad3());
    },
    startWithTarget:function (target) {
        cc.TiledGrid3DAction.prototype.startWithTarget.call(this, target);
        this._tilesCount = this._gridSize.width * this._gridSize.height;
        var locTilesOrder = this._tilesOrder;
        locTilesOrder.length = 0;
        for (var i = 0; i < this._tilesCount; ++i)
            locTilesOrder[i] = i;
        this.shuffle(locTilesOrder, this._tilesCount);
    },
    update:function (dt) {
        var l = 0 | (dt * this._tilesCount), locGridSize = this._gridSize;
        var t,tilePos = cc.p(0,0), locTilesOrder = this._tilesOrder;
        for (var i = 0; i < this._tilesCount; i++) {
            t = locTilesOrder[i];
            tilePos.x = 0 | (t / locGridSize.height);
            tilePos.y = t % (0 | locGridSize.height);
            if (i < l)
                this.turnOffTile(tilePos);
            else
                this.turnOnTile(tilePos);
        }
    }
});
cc.turnOffTiles = function (duration, gridSize, seed) {
    return new cc.TurnOffTiles(duration, gridSize, seed);
};
cc.TurnOffTiles.create = cc.turnOffTiles;
cc.WavesTiles3D = cc.TiledGrid3DAction.extend({
    _waves:0,
    _amplitude:0,
    _amplitudeRate:0,
    ctor:function (duration, gridSize, waves, amplitude) {
        cc.GridAction.prototype.ctor.call(this);
        amplitude !== undefined && this.initWithDuration(duration, gridSize, waves, amplitude);
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, waves, amplitude) {
        if (cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._waves = waves;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var locGridSize = this._gridSize, locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate;
        var locPos = cc.p(0, 0), coords;
        for (var i = 0; i < locGridSize.width; i++) {
            for (var j = 0; j < locGridSize.height; j++) {
                locPos.x = i;
                locPos.y = j;
                coords = this.originalTile(locPos);
                coords.bl.z = (Math.sin(dt * Math.PI * locWaves * 2 +
                    (coords.bl.y + coords.bl.x) * 0.01) * locAmplitude * locAmplitudeRate);
                coords.br.z = coords.bl.z;
                coords.tl.z = coords.bl.z;
                coords.tr.z = coords.bl.z;
                this.setTile(locPos, coords);
            }
        }
    }
});
cc.wavesTiles3D = function (duration, gridSize, waves, amplitude) {
    return new cc.WavesTiles3D(duration, gridSize, waves, amplitude);
};
cc.WavesTiles3D.create = cc.wavesTiles3D;
cc.JumpTiles3D = cc.TiledGrid3DAction.extend({
    _jumps:0,
    _amplitude:0,
    _amplitudeRate:0,
    ctor:function (duration, gridSize, numberOfJumps, amplitude) {
        cc.GridAction.prototype.ctor.call(this);
        amplitude !== undefined && this.initWithDuration(duration, gridSize, numberOfJumps, amplitude);
    },
    getAmplitude:function () {
        return this._amplitude;
    },
    setAmplitude:function (amplitude) {
        this._amplitude = amplitude;
    },
    getAmplitudeRate:function () {
        return this._amplitudeRate;
    },
    setAmplitudeRate:function (amplitudeRate) {
        this._amplitudeRate = amplitudeRate;
    },
    initWithDuration:function (duration, gridSize, numberOfJumps, amplitude) {
        if (cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) {
            this._jumps = numberOfJumps;
            this._amplitude = amplitude;
            this._amplitudeRate = 1.0;
            return true;
        }
        return false;
    },
    update:function (dt) {
        var sinz = (Math.sin(Math.PI * dt * this._jumps * 2) * this._amplitude * this._amplitudeRate );
        var sinz2 = (Math.sin(Math.PI * (dt * this._jumps * 2 + 1)) * this._amplitude * this._amplitudeRate );
        var locGridSize = this._gridSize;
        var locGrid = this.target.grid;
        var coords, locPos = cc.p(0, 0);
        for (var i = 0; i < locGridSize.width; i++) {
            for (var j = 0; j < locGridSize.height; j++) {
                locPos.x = i;
                locPos.y = j;
                coords = locGrid.originalTile(locPos);
                if (((i + j) % 2) === 0) {
                    coords.bl.z += sinz;
                    coords.br.z += sinz;
                    coords.tl.z += sinz;
                    coords.tr.z += sinz;
                } else {
                    coords.bl.z += sinz2;
                    coords.br.z += sinz2;
                    coords.tl.z += sinz2;
                    coords.tr.z += sinz2;
                }
                locGrid.setTile(locPos, coords);
            }
        }
    }
});
cc.jumpTiles3D = function (duration, gridSize, numberOfJumps, amplitude) {
    return new cc.JumpTiles3D(duration, gridSize, numberOfJumps, amplitude);
};
cc.JumpTiles3D.create = cc.jumpTiles3D;
cc.SplitRows = cc.TiledGrid3DAction.extend({
    _rows:0,
    _winSize:null,
    ctor:function (duration, rows) {
        cc.GridAction.prototype.ctor.call(this);
        rows !== undefined && this.initWithDuration(duration, rows);
    },
    initWithDuration:function (duration, rows) {
        this._rows = rows;
        return cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, cc.size(1, rows));
    },
    update:function (dt) {
        var locGridSize = this._gridSize, locWinSizeWidth = this._winSize.width;
        var coords, direction, locPos = cc.p(0, 0);
        for (var j = 0; j < locGridSize.height; ++j) {
            locPos.y = j;
            coords = this.originalTile(locPos);
            direction = 1;
            if ((j % 2 ) === 0)
                direction = -1;
            coords.bl.x += direction * locWinSizeWidth * dt;
            coords.br.x += direction * locWinSizeWidth * dt;
            coords.tl.x += direction * locWinSizeWidth * dt;
            coords.tr.x += direction * locWinSizeWidth * dt;
            this.setTile(locPos, coords);
        }
    },
    startWithTarget:function (target) {
        cc.TiledGrid3DAction.prototype.startWithTarget.call(this, target);
        this._winSize = cc.director.getWinSizeInPixels();
    }
});
cc.splitRows = function (duration, rows) {
    return new cc.SplitRows(duration, rows);
};
cc.SplitRows.create = cc.splitRows;
cc.SplitCols = cc.TiledGrid3DAction.extend({
    _cols:0,
    _winSize:null,
    ctor:function (duration, cols) {
        cc.GridAction.prototype.ctor.call(this);
        cols !== undefined && this.initWithDuration(duration, cols);
    },
    initWithDuration:function (duration, cols) {
        this._cols = cols;
        return cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, cc.size(cols, 1));
    },
    update:function (dt) {
        var locGridSizeWidth = this._gridSize.width, locWinSizeHeight = this._winSize.height;
        var coords, direction, locPos = cc.p(0, 0);
        for (var i = 0; i < locGridSizeWidth; ++i) {
            locPos.x = i;
            coords = this.originalTile(locPos);
            direction = 1;
            if ((i % 2 ) === 0)
                direction = -1;
            coords.bl.y += direction * locWinSizeHeight * dt;
            coords.br.y += direction * locWinSizeHeight * dt;
            coords.tl.y += direction * locWinSizeHeight * dt;
            coords.tr.y += direction * locWinSizeHeight * dt;
            this.setTile(locPos, coords);
        }
        cc.renderer.childrenOrderDirty = true;
    },
    startWithTarget:function (target) {
        cc.TiledGrid3DAction.prototype.startWithTarget.call(this, target);
        this._winSize = cc.director.getWinSizeInPixels();
    }
});
cc.splitCols = function (duration, cols) {
    return new cc.SplitCols(duration, cols);
};
cc.SplitCols.create = cc.splitCols;
cc.PageTurn3D = cc.Grid3DAction.extend({
    getGrid: function(){
        var result = new cc.Grid3D(this._gridSize, undefined, undefined, this._gridNodeTarget.getGridRect());
        result.setNeedDepthTestForBlit(true);
        return result;
    },
    clone: function(){
       var ret = new cc.PageTurn3D();
        ret.initWithDuration(this._duration, this._gridSize);
        return ret;
    },
    update:function (time) {
        var tt = Math.max(0, time - 0.25);
        var deltaAy = (tt * tt * 500);
        var ay = -100 - deltaAy;
        var deltaTheta = Math.sqrt(time);
        var theta = deltaTheta>0.5?Math.PI/2 *deltaTheta : Math.PI/2*(1-deltaTheta);
        var rotateByYAxis = (2-time)*Math.PI;
        var sinTheta = Math.sin(theta);
        var cosTheta = Math.cos(theta);
        var locGridSize = this._gridSize;
        var locVer = cc.p(0, 0);
        for (var i = 0; i <= locGridSize.width; ++i) {
            for (var j = 0; j <= locGridSize.height; ++j) {
                locVer.x = i;
                locVer.y = j;
                var p = this.getOriginalVertex(locVer);
                p.x -= this.getGridRect().x;
                var R = Math.sqrt((p.x * p.x) + ((p.y - ay) * (p.y - ay)));
                var r = R * sinTheta;
                var alpha = Math.asin(p.x / R);
                var beta = alpha / sinTheta;
                var cosBeta = Math.cos(beta);
                if (beta <= Math.PI)
                    p.x = ( r * Math.sin(beta));
                else
                    p.x = 0;
                p.y = ( R + ay - ( r * (1 - cosBeta) * sinTheta));
                p.z = (r * ( 1 - cosBeta ) * cosTheta);// "100" didn't work for
                p.x = p.z * Math.sin(rotateByYAxis) + p.x * Math.cos(rotateByYAxis);
                p.z = p.z * Math.cos(rotateByYAxis) - p.x * Math.cos(rotateByYAxis);
                p.z/= 7;
                if (p.z < 0.5)
                    p.z = 0.5;
                p.x+= this.getGridRect().x;
                this.setVertex(locVer, p);
            }
        }
    }
});
cc.pageTurn3D = function (duration, gridSize) {
    return new cc.PageTurn3D(duration, gridSize);
};
cc.PageTurn3D.create = cc.pageTurn3D;
cc.ProgressTimer = cc.Node.extend({
    _type:null,
    _percentage:0.0,
    _sprite:null,
    _midPoint:null,
    _barChangeRate:null,
    _reverseDirection:false,
    _className:"ProgressTimer",
    ctor: function(sprite){
        cc.Node.prototype.ctor.call(this);
        this._type = cc.ProgressTimer.TYPE_RADIAL;
        this._percentage = 0.0;
        this._midPoint = cc.p(0, 0);
        this._barChangeRate = cc.p(0, 0);
        this._reverseDirection = false;
        this._sprite = null;
        sprite && this.initWithSprite(sprite);
    },
    onEnter: function () {
        this._super();
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
            this._renderCmd.initCmd();
            this._renderCmd._updateProgress();
        }
    },
    cleanup: function () {
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
            this._renderCmd.releaseData();
        }
        this._super();
    },
    getMidpoint:function () {
        return cc.p(this._midPoint.x, this._midPoint.y);
    },
    setMidpoint:function (mpoint) {
        this._midPoint = cc.pClamp(mpoint, cc.p(0, 0), cc.p(1, 1));
    },
    getBarChangeRate:function () {
        return cc.p(this._barChangeRate.x, this._barChangeRate.y);
    },
    setBarChangeRate:function (barChangeRate) {
        this._barChangeRate = cc.pClamp(barChangeRate, cc.p(0, 0), cc.p(1, 1));
    },
    getType:function () {
        return this._type;
    },
    getPercentage:function () {
        return this._percentage;
    },
    getSprite:function () {
        return this._sprite;
    },
    setPercentage:function (percentage) {
        if (this._percentage !== percentage) {
            this._percentage = cc.clampf(percentage, 0, 100);
            this._renderCmd._updateProgress();
        }
    },
    setOpacityModifyRGB:function (bValue) {
    },
    isOpacityModifyRGB:function () {
        return false;
    },
    isReverseDirection:function () {
        return this._reverseDirection;
    },
    setColor:function (color) {
        this._sprite.color = color;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
    },
    setOpacity:function (opacity) {
        this._sprite.opacity = opacity;
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
    },
    getColor:function () {
        return this._sprite.color;
    },
    getOpacity:function () {
        return this._sprite.opacity;
    },
    setReverseProgress: function(reverse){
        if (this._reverseDirection !== reverse){
            this._reverseDirection = reverse;
            this._renderCmd.resetVertexData();
        }
    },
    setSprite: function(sprite){
        if (this._sprite !== sprite) {
            this._sprite = sprite;
            if(sprite) {
                this.setContentSize(sprite.width, sprite.height);
                sprite.ignoreAnchorPointForPosition(true);
            }
            else {
                this.setContentSize(0,0);
            }
            this._renderCmd.resetVertexData();
        }
    },
    setType: function(type){
        if (type !== this._type){
            this._type = type;
            this._renderCmd.resetVertexData();
        }
    },
    setReverseDirection: function(reverse){
        if (this._reverseDirection !== reverse){
            this._reverseDirection = reverse;
            this._renderCmd.resetVertexData();
        }
    },
    initWithSprite: function(sprite){
        this.percentage = 0;
        this.setAnchorPoint(0.5,0.5);
        this._type = cc.ProgressTimer.TYPE_RADIAL;
        this._reverseDirection = false;
        this.midPoint = cc.p(0.5, 0.5);
        this.barChangeRate = cc.p(1, 1);
        this.setSprite(sprite);
        this._renderCmd.resetVertexData();
        return true;
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.ProgressTimer.CanvasRenderCmd(this);
        else
            return new cc.ProgressTimer.WebGLRenderCmd(this);
    }
});
var _p = cc.ProgressTimer.prototype;
_p.midPoint;
cc.defineGetterSetter(_p, "midPoint", _p.getMidpoint, _p.setMidpoint);
_p.barChangeRate;
cc.defineGetterSetter(_p, "barChangeRate", _p.getBarChangeRate, _p.setBarChangeRate);
_p.type;
cc.defineGetterSetter(_p, "type", _p.getType, _p.setType);
_p.percentage;
cc.defineGetterSetter(_p, "percentage", _p.getPercentage, _p.setPercentage);
_p.sprite;
cc.defineGetterSetter(_p, "sprite", _p.getSprite, _p.setSprite);
_p.reverseDir;
cc.defineGetterSetter(_p, "reverseDir", _p.isReverseDirection, _p.setReverseDirection);
cc.ProgressTimer.create = function (sprite) {
    return new cc.ProgressTimer(sprite);
};
cc.ProgressTimer.TEXTURE_COORDS_COUNT = 4;
cc.ProgressTimer.TEXTURE_COORDS = 0x4b;
cc.ProgressTimer.TYPE_RADIAL = 0;
cc.ProgressTimer.TYPE_BAR = 1;
(function(){
    cc.ProgressTimer.CanvasRenderCmd = function(renderableObject){
        cc.Node.CanvasRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._PI180 = Math.PI / 180;
        this._barRect = cc.rect(0, 0, 0, 0);
        this._origin = cc.p(0, 0);
        this._radius = 0;
        this._startAngle = 270;
        this._endAngle = 270;
        this._counterClockWise = false;
        this._canUseDirtyRegion = true;
    };
    var proto = cc.ProgressTimer.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.ProgressTimer.CanvasRenderCmd;
    proto.rendering = function (ctx, scaleX, scaleY) {
        var wrapper = ctx || cc._renderContext,context = wrapper.getContext(), node = this._node, locSprite = node._sprite;
        var locTextureCoord = locSprite._renderCmd._textureCoord, alpha = locSprite._renderCmd._displayedOpacity / 255;
        if (locTextureCoord.width === 0 || locTextureCoord.height === 0)
            return;
        if (!locSprite._texture || !locTextureCoord.validRect || alpha === 0)
            return;
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        wrapper.setCompositeOperation(locSprite._blendFuncStr);
        wrapper.setGlobalAlpha(alpha);
        var locRect = locSprite._rect, locOffsetPosition = locSprite._offsetPosition;
        var locX = locOffsetPosition.x,
            locY = -locOffsetPosition.y - locRect.height,
            locWidth = locRect.width,
            locHeight = locRect.height;
        wrapper.save();
        if (locSprite._flippedX) {
            locX = -locX - locWidth;
            context.scale(-1, 1);
        }
        if (locSprite._flippedY) {
            locY = locOffsetPosition.y;
            context.scale(1, -1);
        }
        if (node._type === cc.ProgressTimer.TYPE_BAR) {
            var locBarRect = this._barRect;
            context.beginPath();
            context.rect(locBarRect.x , locBarRect.y , locBarRect.width , locBarRect.height );
            context.clip();
            context.closePath();
        } else if (node._type === cc.ProgressTimer.TYPE_RADIAL) {
            var locOriginX = this._origin.x ;
            var locOriginY = this._origin.y ;
            context.beginPath();
            context.arc(locOriginX, locOriginY, this._radius , this._PI180 * this._startAngle, this._PI180 * this._endAngle, this._counterClockWise);
            context.lineTo(locOriginX, locOriginY);
            context.clip();
            context.closePath();
        }
        var texture = locSprite._renderCmd._textureToRender || locSprite._texture;
        var image = texture.getHtmlElementObj();
        if (locSprite._renderCmd._colorized) {
            context.drawImage(image,
                0, 0, locTextureCoord.width, locTextureCoord.height,
                locX , locY , locWidth , locHeight );
        } else {
            context.drawImage(image,
                locTextureCoord.renderX, locTextureCoord.renderY, locTextureCoord.width, locTextureCoord.height,
                locX , locY , locWidth , locHeight );
        }
        wrapper.restore();
        cc.g_NumberOfDraws++;
    };
    proto.releaseData = function(){};
    proto.resetVertexData = function(){};
    proto._updateProgress = function(){
        this.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
        var node = this._node;
        var locSprite = node._sprite;
        var sw = locSprite.width, sh = locSprite.height;
        var locMidPoint = node._midPoint;
        if (node._type === cc.ProgressTimer.TYPE_RADIAL) {
            this._radius = Math.round(Math.sqrt(sw * sw + sh * sh));
            var locStartAngle, locEndAngle, locCounterClockWise = false, locOrigin = this._origin;
            locOrigin.x = sw * locMidPoint.x;
            locOrigin.y = -sh * locMidPoint.y;
            if (node._reverseDirection) {
                locEndAngle = 270;
                locStartAngle = 270 - 3.6 * node._percentage;
            } else {
                locStartAngle = -90;
                locEndAngle = -90 + 3.6 * node._percentage;
            }
            if (locSprite._flippedX) {
                locOrigin.x -= sw * (node._midPoint.x * 2);
                locStartAngle = -locStartAngle;
                locEndAngle = -locEndAngle;
                locStartAngle -= 180;
                locEndAngle -= 180;
                locCounterClockWise = !locCounterClockWise;
            }
            if (locSprite._flippedY) {
                locOrigin.y += sh * (node._midPoint.y * 2);
                locCounterClockWise = !locCounterClockWise;
                locStartAngle = -locStartAngle;
                locEndAngle = -locEndAngle;
            }
            this._startAngle = locStartAngle;
            this._endAngle = locEndAngle;
            this._counterClockWise = locCounterClockWise;
        } else {
            var locBarChangeRate = node._barChangeRate;
            var percentageF = node._percentage / 100;
            var locBarRect = this._barRect;
            var drewSize = cc.size((sw * (1 - locBarChangeRate.x)), (sh * (1 - locBarChangeRate.y)));
            var drawingSize = cc.size((sw - drewSize.width) * percentageF, (sh - drewSize.height) * percentageF);
            var currentDrawSize = cc.size(drewSize.width + drawingSize.width, drewSize.height + drawingSize.height);
            var startPoint = cc.p(sw * locMidPoint.x, sh * locMidPoint.y);
            var needToLeft = startPoint.x - currentDrawSize.width / 2;
            if ((locMidPoint.x > 0.5) && (currentDrawSize.width / 2 >= sw - startPoint.x))
                needToLeft = sw - currentDrawSize.width;
            var needToTop = startPoint.y - currentDrawSize.height / 2;
            if ((locMidPoint.y > 0.5) && (currentDrawSize.height / 2 >= sh - startPoint.y))
                needToTop = sh - currentDrawSize.height;
            locBarRect.x = 0;
            var flipXNeed = 1;
            if (locSprite._flippedX) {
                locBarRect.x -= currentDrawSize.width;
                flipXNeed = -1;
            }
            if (needToLeft > 0)
                locBarRect.x += needToLeft * flipXNeed;
            locBarRect.y = 0;
            var flipYNeed = 1;
            if (locSprite._flippedY) {
                locBarRect.y += currentDrawSize.height;
                flipYNeed = -1;
            }
            if (needToTop > 0)
                locBarRect.y -= needToTop * flipYNeed;
            locBarRect.width = currentDrawSize.width;
            locBarRect.height = -currentDrawSize.height;
        }
    };
    proto._syncStatus = function (parentCmd) {
        var node = this._node;
        if(!node._sprite)
            return;
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        var parentNode = parentCmd ? parentCmd._node : null;
        if(parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & flags.colorDirty))
            locFlag |= flags.colorDirty;
        if(parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & flags.opacityDirty))
            locFlag |= flags.opacityDirty;
        if(parentCmd && (parentCmd._dirtyFlag & flags.transformDirty))
            locFlag |= flags.transformDirty;
        this._dirtyFlag = locFlag;
        var spriteCmd = node._sprite._renderCmd;
        var spriteFlag = spriteCmd._dirtyFlag;
        var colorDirty = spriteFlag & flags.colorDirty,
            opacityDirty = spriteFlag & flags.opacityDirty;
        if (colorDirty){
            spriteCmd._syncDisplayColor();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.colorDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.colorDirty ^ this._dirtyFlag;
        }
        if (opacityDirty){
            spriteCmd._syncDisplayOpacity();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.opacityDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.opacityDirty ^ this._dirtyFlag;
        }
        if(colorDirty || opacityDirty){
            spriteCmd._updateColor();
        }
        if (locFlag & flags.transformDirty) {
            this.transform(parentCmd);
        }
        if (locFlag & flags.orderDirty) {
            this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
        }
    };
    proto.updateStatus = function () {
        var node = this._node;
        if(!node._sprite)
            return;
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        var spriteCmd = node._sprite._renderCmd;
        var spriteFlag = spriteCmd._dirtyFlag;
        var colorDirty = spriteFlag & flags.colorDirty,
            opacityDirty = spriteFlag & flags.opacityDirty;
        if(colorDirty){
            spriteCmd._updateDisplayColor();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.colorDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.colorDirty ^ this._dirtyFlag;
        }
        if(opacityDirty){
            spriteCmd._updateDisplayOpacity();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.opacityDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.opacityDirty ^ this._dirtyFlag;
        }
        if(colorDirty || opacityDirty){
            spriteCmd._updateColor();
        }
        if(locFlag & flags.transformDirty){
            this.transform(this.getParentRenderCmd(), true);
        }
        if(locFlag & flags.contentDirty) {
            this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
        }
        this._dirtyFlag = 0;
    };
})();
cc.ProgressTo = cc.ActionInterval.extend({
    _to:0,
    _from:0,
    ctor: function(duration, percent){
        cc.ActionInterval.prototype.ctor.call(this);
        this._to = 0;
        this._from = 0;
        percent !== undefined && this.initWithDuration(duration, percent);
    },
    initWithDuration:function (duration, percent) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._to = percent;
            return true;
        }
        return false;
    },
    clone:function(){
        var action = new cc.ProgressTo();
        action.initWithDuration(this._duration, this._to);
        return action;
    },
    reverse: function(){
        cc.log("cc.ProgressTo.reverse(): reverse hasn't been supported.");
        return null;
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._from = target.percentage;
    },
    update:function (time) {
        if (this.target  instanceof cc.ProgressTimer)
            this.target.percentage = this._from + (this._to - this._from) * time;
    }
});
cc.progressTo = function (duration, percent) {
    return new cc.ProgressTo(duration, percent);
};
cc.ProgressTo.create = cc.progressTo;
cc.ProgressFromTo = cc.ActionInterval.extend({
    _to:0,
    _from:0,
    ctor:function(duration, fromPercentage, toPercentage){
        cc.ActionInterval.prototype.ctor.call(this);
        this._to = 0;
        this._from = 0;
        toPercentage !== undefined && this.initWithDuration(duration, fromPercentage, toPercentage);
    },
    initWithDuration:function (duration, fromPercentage, toPercentage) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._to = toPercentage;
            this._from = fromPercentage;
            return true;
        }
        return false;
    },
    clone:function(){
        var action = new cc.ProgressFromTo();
        action.initWithDuration(this._duration, this._from, this._to);
        return action;
    },
    reverse:function () {
        return cc.progressFromTo(this._duration, this._to, this._from);
    },
    startWithTarget:function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
    },
    update:function (time) {
        if (this.target  instanceof cc.ProgressTimer)
            this.target.percentage = this._from + (this._to - this._from) * time;
    }
});
cc.progressFromTo = function (duration, fromPercentage, toPercentage) {
    return new cc.ProgressFromTo(duration, fromPercentage, toPercentage);
};
cc.ProgressFromTo.create = cc.progressFromTo;
(function(){
    var MAX_VERTEX_COUNT = 8;
    cc.ProgressTimer.WebGLRenderCmd = function(renderableObject){
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._progressDirty = true;
        this._bl = cc.p();
        this._tr = cc.p();
        this.initCmd();
    };
    var proto = cc.ProgressTimer.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.ProgressTimer.WebGLRenderCmd;
    proto.transform = function (parentCmd, recursive) {
        this.originTransform(parentCmd, recursive);
        var sp = this._node._sprite;
        sp._renderCmd.transform(this, recursive);
        var lx = sp._offsetPosition.x, rx = lx + sp._rect.width,
            by = sp._offsetPosition.y, ty = by + sp._rect.height,
            wt = this._worldTransform;
        this._bl.x = lx * wt.a + by * wt.c + wt.tx;
        this._bl.y = lx * wt.b + by * wt.d + wt.ty;
        this._tr.x = rx * wt.a + ty * wt.c + wt.tx;
        this._tr.y = rx * wt.b + ty * wt.d + wt.ty;
        this._updateProgressData();
    };
    proto.rendering = function (ctx) {
        var node = this._node;
        var context = ctx || cc._renderContext;
        if (this._vertexDataCount === 0 || !node._sprite)
            return;
        this._shaderProgram.use();
        this._shaderProgram._updateProjectionUniform();
        var blendFunc = node._sprite._blendFunc;
        cc.glBlendFunc(blendFunc.src, blendFunc.dst);
        cc.glBindTexture2D(node._sprite.texture);
        context.bindBuffer(context.ARRAY_BUFFER, this._vertexWebGLBuffer);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
        context.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
        if (this._vertexDataDirty) {
            context.bufferSubData(context.ARRAY_BUFFER, 0, this._float32View);
            this._vertexDataDirty = false;
        }
        var locVertexDataLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, context.FLOAT, false, locVertexDataLen, 0);
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, locVertexDataLen, 12);
        context.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, context.FLOAT, false, locVertexDataLen, 16);
        if (node._type === cc.ProgressTimer.TYPE_RADIAL)
            context.drawArrays(context.TRIANGLE_FAN, 0, this._vertexDataCount);
        else if (node._type === cc.ProgressTimer.TYPE_BAR) {
            if (!node._reverseDirection)
                context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount);
            else {
                context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount / 2);
                context.drawArrays(context.TRIANGLE_STRIP, 4, this._vertexDataCount / 2);
                cc.g_NumberOfDraws++;
            }
        }
        cc.g_NumberOfDraws++;
    };
    proto._syncStatus = function (parentCmd) {
        var node = this._node;
        if(!node._sprite)
            return;
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        var parentNode = parentCmd ? parentCmd._node : null;
        if(parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & flags.colorDirty))
            locFlag |= flags.colorDirty;
        if(parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & flags.opacityDirty))
            locFlag |= flags.opacityDirty;
        if(parentCmd && (parentCmd._dirtyFlag & flags.transformDirty))
            locFlag |= flags.transformDirty;
        this._dirtyFlag = locFlag;
        var spriteCmd = node._sprite._renderCmd;
        var spriteFlag = spriteCmd._dirtyFlag;
        var colorDirty = (locFlag | spriteFlag) & flags.colorDirty,
            opacityDirty = (locFlag | spriteFlag) & flags.opacityDirty;
        if (colorDirty){
            spriteCmd._syncDisplayColor();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.colorDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.colorDirty ^ this._dirtyFlag;
        }
        if (opacityDirty){
            spriteCmd._syncDisplayOpacity();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.opacityDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.opacityDirty ^ this._dirtyFlag;
        }
        if(colorDirty || opacityDirty){
            this._updateColor();
        }
        if (locFlag & flags.transformDirty) {
            this.transform(parentCmd);
        }
        if (locFlag & flags.textureDirty) {
            this._updateProgressData();
            this._dirtyFlag = this._dirtyFlag & flags.textureDirty ^ this._dirtyFlag;
        }
        spriteCmd._dirtyFlag = 0;
    };
    proto.updateStatus = function () {
        var node = this._node;
        if(!node._sprite)
            return;
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        var spriteCmd = node._sprite._renderCmd;
        var spriteFlag = spriteCmd._dirtyFlag;
        var colorDirty = (locFlag | spriteFlag) & flags.colorDirty,
            opacityDirty = (locFlag | spriteFlag) & flags.opacityDirty;
        if(colorDirty){
            spriteCmd._updateDisplayColor();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.colorDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.colorDirty ^ this._dirtyFlag;
        }
        if(opacityDirty){
            spriteCmd._updateDisplayOpacity();
            spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.opacityDirty ^ spriteCmd._dirtyFlag;
            this._dirtyFlag = this._dirtyFlag & flags.opacityDirty ^ this._dirtyFlag;
        }
        if(colorDirty || opacityDirty){
            this._updateColor();
        }
        if(locFlag & flags.transformDirty){
            this.transform(this.getParentRenderCmd(), true);
        }
        if (locFlag & flags.orderDirty) {
            this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
        }
        if (locFlag & flags.textureDirty) {
            this._updateProgressData();
            this._dirtyFlag = this._dirtyFlag & flags.textureDirty ^ this._dirtyFlag;
        }
    };
    proto.releaseData = function(){
        if (this._vertexData) {
            var webglBuffer = this._vertexWebGLBuffer;
            setTimeout(function () {
                cc._renderContext.deleteBuffer(webglBuffer);
            }, 0.1);
            this._vertexWebGLBuffer = null;
            this._vertexData = null;
            this._float32View = null;
            this._vertexArrayBuffer = null;
            this._vertexDataCount = 0;
        }
    };
    proto.initCmd = function () {
        if (!this._vertexData) {
            this._vertexWebGLBuffer = cc._renderContext.createBuffer();
            var vertexDataLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
            this._vertexArrayBuffer = new ArrayBuffer(MAX_VERTEX_COUNT * vertexDataLen);
            this._float32View = new Float32Array(this._vertexArrayBuffer);
            this._vertexData = [];
            for (var i = 0; i < MAX_VERTEX_COUNT; i++) {
                this._vertexData[i] = new cc.V3F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * vertexDataLen);
            }
            gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexWebGLBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, this._float32View, gl.DYNAMIC_DRAW);
            this._vertexDataCount = 0;
            this._vertexDataDirty = true;
            this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
        }
    };
    proto.resetVertexData = function () {
        this._vertexDataCount = 0;
    };
    proto._updateProgressData = function () {
        var node = this._node;
        var locType = node._type;
        if(locType === cc.ProgressTimer.TYPE_RADIAL)
            this._updateRadial();
        else if(locType === cc.ProgressTimer.TYPE_BAR)
            this._updateBar();
        this._vertexDataDirty = true;
    };
    proto._updateProgress = function () {
        this.setDirtyFlag(cc.Node._dirtyFlags.textureDirty);
    };
    proto._updateBar = function(){
        var node = this._node;
        if (!node._sprite)
            return;
        var i, alpha = node._percentage / 100.0;
        var locBarChangeRate = node._barChangeRate;
        var alphaOffset = cc.pMult(cc.p((1.0 - locBarChangeRate.x) + alpha * locBarChangeRate.x,
                (1.0 - locBarChangeRate.y) + alpha * locBarChangeRate.y), 0.5);
        var min = cc.pSub(node._midPoint, alphaOffset), max = cc.pAdd(node._midPoint, alphaOffset);
        if (min.x < 0) {
            max.x += -min.x;
            min.x = 0;
        }
        if (max.x > 1) {
            min.x -= max.x - 1;
            max.x = 1;
        }
        if (min.y < 0) {
            max.y += -min.y;
            min.y = 0;
        }
        if (max.y > 1) {
            min.y -= max.y - 1;
            max.y = 1;
        }
        var locVertexData;
        if (!this._reverseDirection) {
            if (!this._vertexDataCount) {
                this._vertexDataCount = 4;
            }
            locVertexData = this._vertexData;
            this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, min.x, max.y);
            this._vertexFromAlphaPoint(locVertexData[0].vertices, min.x, max.y);
            this._textureCoordFromAlphaPoint(locVertexData[1].texCoords, min.x, min.y);
            this._vertexFromAlphaPoint(locVertexData[1].vertices, min.x, min.y);
            this._textureCoordFromAlphaPoint(locVertexData[2].texCoords, max.x, max.y);
            this._vertexFromAlphaPoint(locVertexData[2].vertices, max.x, max.y);
            this._textureCoordFromAlphaPoint(locVertexData[3].texCoords, max.x, min.y);
            this._vertexFromAlphaPoint(locVertexData[3].vertices, max.x, min.y);
        } else {
            locVertexData = this._vertexData;
            if (!this._vertexDataCount) {
                this._vertexDataCount = 8;
                this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, 0, 1);
                this._vertexFromAlphaPoint(locVertexData[0].vertices, 0, 1);
                this._textureCoordFromAlphaPoint(locVertexData[1].texCoords, 0, 0);
                this._vertexFromAlphaPoint(locVertexData[1].vertices, 0, 0);
                this._textureCoordFromAlphaPoint(locVertexData[6].texCoords, 1, 1);
                this._vertexFromAlphaPoint(locVertexData[6].vertices, 1, 1);
                this._textureCoordFromAlphaPoint(locVertexData[7].texCoords, 1, 0);
                this._vertexFromAlphaPoint(locVertexData[7].vertices, 1, 0);
            }
            this._textureCoordFromAlphaPoint(locVertexData[2].texCoords, min.x, max.y);
            this._vertexFromAlphaPoint(locVertexData[2].vertices, min.x, max.y);
            this._textureCoordFromAlphaPoint(locVertexData[3].texCoords, min.x, min.y);
            this._vertexFromAlphaPoint(locVertexData[3].vertices, min.x, min.y);
            this._textureCoordFromAlphaPoint(locVertexData[4].texCoords, max.x, max.y);
            this._vertexFromAlphaPoint(locVertexData[4].vertices, max.x, max.y);
            this._textureCoordFromAlphaPoint(locVertexData[5].texCoords, max.x, min.y);
            this._vertexFromAlphaPoint(locVertexData[5].vertices, max.x, min.y);
        }
        this._updateColor();
    };
    proto._updateRadial = function () {
        var node = this._node;
        if (!node._sprite)
            return;
        var i, locMidPoint = node._midPoint;
        var alpha = node._percentage / 100;
        var angle = 2 * (cc.PI) * ( node._reverseDirection ? alpha : 1.0 - alpha);
        var topMid = cc.p(locMidPoint.x, 1);
        var percentagePt = cc.pRotateByAngle(topMid, locMidPoint, angle);
        var index = 0;
        var hit;
        if (alpha === 0) {
            hit = topMid;
            index = 0;
        } else if (alpha === 1) {
            hit = topMid;
            index = 4;
        } else {
            var min_t = cc.FLT_MAX;
            var locProTextCoordsCount = cc.ProgressTimer.TEXTURE_COORDS_COUNT;
            for (i = 0; i <= locProTextCoordsCount; ++i) {
                var pIndex = (i + (locProTextCoordsCount - 1)) % locProTextCoordsCount;
                var edgePtA = this._boundaryTexCoord(i % locProTextCoordsCount);
                var edgePtB = this._boundaryTexCoord(pIndex);
                if (i === 0)
                    edgePtB = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x);
                else if (i === 4)
                    edgePtA = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x);
                var retPoint = cc.p(0, 0);
                if (cc.pLineIntersect(edgePtA, edgePtB, locMidPoint, percentagePt, retPoint)) {
                    if ((i === 0 || i === 4)) {
                        if (!(0 <= retPoint.x && retPoint.x <= 1))
                            continue;
                    }
                    if (retPoint.y >= 0) {
                        if (retPoint.y < min_t) {
                            min_t = retPoint.y;
                            index = i;
                        }
                    }
                }
            }
            hit = cc.pAdd(locMidPoint, cc.pMult(cc.pSub(percentagePt, locMidPoint), min_t));
        }
        var sameIndexCount = true;
        if (this._vertexDataCount !== index + 3) {
            sameIndexCount = false;
            this._vertexDataCount = index + 3;
        }
        this._updateColor();
        var locVertexData = this._vertexData;
        if (!sameIndexCount) {
            this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, locMidPoint.x, locMidPoint.y);
            this._vertexFromAlphaPoint(locVertexData[0].vertices, locMidPoint.x, locMidPoint.y);
            this._textureCoordFromAlphaPoint(locVertexData[1].texCoords, topMid.x, topMid.y);
            this._vertexFromAlphaPoint(locVertexData[1].vertices, topMid.x, topMid.y);
            for (i = 0; i < index; i++) {
                var alphaPoint = this._boundaryTexCoord(i);
                this._textureCoordFromAlphaPoint(locVertexData[i + 2].texCoords, alphaPoint.x, alphaPoint.y);
                this._vertexFromAlphaPoint(locVertexData[i + 2].vertices, alphaPoint.x, alphaPoint.y);
            }
        }
        this._textureCoordFromAlphaPoint(locVertexData[this._vertexDataCount - 1].texCoords, hit.x, hit.y);
        this._vertexFromAlphaPoint(locVertexData[this._vertexDataCount - 1].vertices, hit.x, hit.y);
    };
    proto._boundaryTexCoord = function (index) {
        if (index < cc.ProgressTimer.TEXTURE_COORDS_COUNT) {
            var locProTextCoords = cc.ProgressTimer.TEXTURE_COORDS;
            if (this._node._reverseDirection)
                return cc.p((locProTextCoords >> (7 - (index << 1))) & 1, (locProTextCoords >> (7 - ((index << 1) + 1))) & 1);
            else
                return cc.p((locProTextCoords >> ((index << 1) + 1)) & 1, (locProTextCoords >> (index << 1)) & 1);
        }
        return cc.p(0,0);
    };
    proto._textureCoordFromAlphaPoint = function (coords, ax, ay) {
        var locSprite = this._node._sprite;
        if (!locSprite) {
            coords.u = 0;
            coords.v = 0;
            return;
        }
        var uvs = locSprite._renderCmd._vertices,
            bl = uvs[1],
            tr = uvs[2];
        var min = cc.p(bl.u, bl.v);
        var max = cc.p(tr.u, tr.v);
        if (locSprite.textureRectRotated) {
            var temp = ax;
            ax = ay;
            ay = temp;
        }
        coords.u = min.x * (1 - ax) + max.x * ax;
        coords.v = min.y * (1 - ay) + max.y * ay;
    };
    proto._vertexFromAlphaPoint = function (vertex, ax, ay) {
        vertex.x = this._bl.x * (1 - ax) + this._tr.x * ax;
        vertex.y = this._bl.y * (1 - ay) + this._tr.y * ay;
        vertex.z = this._node._vertexZ;
    };
    proto._updateColor = function(){
        var sp = this._node._sprite;
        if (!this._vertexDataCount || !sp)
            return;
        var color = this._displayedColor;
        var spColor = sp._renderCmd._displayedColor;
        var r = spColor.r;
        var g = spColor.g;
        var b = spColor.b;
        var a = sp._renderCmd._displayedOpacity / 255;
        if (sp._opacityModifyRGB) {
            r *= a;
            g *= a;
            b *= a;
        }
        color.r = r;
        color.g = g;
        color.b = b;
        color.a = sp._renderCmd._displayedOpacity;
        var locVertexData = this._vertexData;
        for (var i = 0, len = this._vertexDataCount; i < len; ++i) {
            locVertexData[i].colors = color;
        }
        this._vertexDataDirty = true;
    };
})();
cc.SCENE_FADE = 4208917214;
cc.TRANSITION_ORIENTATION_LEFT_OVER = 0;
cc.TRANSITION_ORIENTATION_RIGHT_OVER = 1;
cc.TRANSITION_ORIENTATION_UP_OVER = 0;
cc.TRANSITION_ORIENTATION_DOWN_OVER = 1;
cc.TransitionScene = cc.Scene.extend({
    _inScene:null,
    _outScene:null,
    _duration:null,
    _isInSceneOnTop:false,
    _isSendCleanupToScene:false,
    _className:"TransitionScene",
    ctor:function (t, scene) {
        cc.Scene.prototype.ctor.call(this);
        if(t !== undefined && scene !== undefined)
            this.initWithDuration(t, scene);
    },
    _setNewScene:function (dt) {
        this.unschedule(this._setNewScene);
        var director = cc.director;
        this._isSendCleanupToScene = director.isSendCleanupToScene();
        director.runScene(this._inScene);
        cc.eventManager.setEnabled(true);
        this._outScene.visible = true;
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = true;
    },
    visit:function () {
        if (this._isInSceneOnTop) {
            this._outScene.visit();
            this._inScene.visit();
        } else {
            this._inScene.visit();
            this._outScene.visit();
        }
        cc.Node.prototype.visit.call(this);
    },
    onEnter:function () {
        cc.Node.prototype.onEnter.call(this);
        cc.eventManager.setEnabled(false);
        this._outScene.onExitTransitionDidStart();
        this._inScene.onEnter();
    },
    onExit:function () {
        cc.Node.prototype.onExit.call(this);
        cc.eventManager.setEnabled(true);
        this._outScene.onExit();
        this._inScene.onEnterTransitionDidFinish();
    },
    cleanup:function () {
        cc.Node.prototype.cleanup.call(this);
        if (this._isSendCleanupToScene)
            this._outScene.cleanup();
    },
    initWithDuration:function (t, scene) {
        if(!scene)
            throw new Error("cc.TransitionScene.initWithDuration(): Argument scene must be non-nil");
        if (this.init()) {
            this._duration = t;
            this.attr({
                x: 0,
                y: 0,
                anchorX: 0,
                anchorY: 0
            });
            this._inScene = scene;
            this._outScene = cc.director.getRunningScene();
            if (!this._outScene) {
                this._outScene = new cc.Scene();
                this._outScene.init();
            }
            if(this._inScene === this._outScene)
                throw new Error("cc.TransitionScene.initWithDuration(): Incoming scene must be different from the outgoing scene");
            this._sceneOrder();
            return true;
        } else {
            return false;
        }
    },
    finish:function () {
        this._inScene.attr({
            visible: true,
            x: 0,
            y: 0,
            scale: 1.0,
            rotation: 0.0
        });
        this._outScene.attr({
            visible: false,
            x: 0,
            y: 0,
            scale: 1.0,
            rotation: 0.0
        });
        this.schedule(this._setNewScene, 0);
    },
    hideOutShowIn:function () {
        this._inScene.visible = true;
        this._outScene.visible = false;
    }
});
cc.TransitionScene.create = function (t, scene) {
    return new cc.TransitionScene(t, scene);
};
cc.TransitionSceneOriented = cc.TransitionScene.extend({
    _orientation:0,
    ctor:function (t, scene, orientation) {
        cc.TransitionScene.prototype.ctor.call(this);
        orientation != undefined && this.initWithDuration(t, scene, orientation);
    },
    initWithDuration:function (t, scene, orientation) {
        if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
            this._orientation = orientation;
        }
        return true;
    }
});
cc.TransitionSceneOriented.create = function (t, scene, orientation) {
    return new cc.TransitionSceneOriented(t, scene, orientation);
};
cc.TransitionRotoZoom = cc.TransitionScene.extend({
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this._inScene.attr({
            scale: 0.001,
            anchorX: 0.5,
            anchorY: 0.5
        });
        this._outScene.attr({
            scale: 1.0,
            anchorX: 0.5,
            anchorY: 0.5
        });
        var rotoZoom = cc.sequence(
            cc.spawn(cc.scaleBy(this._duration / 2, 0.001),
                cc.rotateBy(this._duration / 2, 360 * 2)),
            cc.delayTime(this._duration / 2));
        this._outScene.runAction(rotoZoom);
        this._inScene.runAction(
            cc.sequence(rotoZoom.reverse(),
                cc.callFunc(this.finish, this)));
    }
});
cc.TransitionRotoZoom.create = function (t, scene) {
    return new cc.TransitionRotoZoom(t, scene);
};
cc.TransitionJumpZoom = cc.TransitionScene.extend({
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        var winSize = cc.director.getWinSize();
        this._inScene.attr({
            scale: 0.5,
            x: winSize.width,
            y: 0,
            anchorX: 0.5,
            anchorY: 0.5
        });
        this._outScene.anchorX = 0.5;
        this._outScene.anchorY = 0.5;
        var jump = cc.jumpBy(this._duration / 4, cc.p(-winSize.width, 0), winSize.width / 4, 2);
        var scaleIn = cc.scaleTo(this._duration / 4, 1.0);
        var scaleOut = cc.scaleTo(this._duration / 4, 0.5);
        var jumpZoomOut = cc.sequence(scaleOut, jump);
        var jumpZoomIn = cc.sequence(jump, scaleIn);
        var delay = cc.delayTime(this._duration / 2);
        this._outScene.runAction(jumpZoomOut);
        this._inScene.runAction(cc.sequence(delay, jumpZoomIn, cc.callFunc(this.finish, this)));
    }
});
cc.TransitionJumpZoom.create = function (t, scene) {
    return new cc.TransitionJumpZoom(t, scene);
};
cc.TransitionMoveInL = cc.TransitionScene.extend({
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this.initScenes();
        var action = this.action();
        this._inScene.runAction(
            cc.sequence(this.easeActionWithAction(action), cc.callFunc(this.finish, this))
        );
    },
    initScenes:function () {
        this._inScene.setPosition(-cc.director.getWinSize().width, 0);
    },
    action:function () {
        return cc.moveTo(this._duration, cc.p(0, 0));
    },
    easeActionWithAction:function (action) {
        return new cc.EaseOut(action, 2.0);
    }
});
cc.TransitionMoveInL.create = function (t, scene) {
    return new cc.TransitionMoveInL(t, scene);
};
cc.TransitionMoveInR = cc.TransitionMoveInL.extend({
    ctor:function (t, scene) {
        cc.TransitionMoveInL.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    initScenes:function () {
        this._inScene.setPosition(cc.director.getWinSize().width, 0);
    }
});
cc.TransitionMoveInR.create = function (t, scene) {
    return new cc.TransitionMoveInR(t, scene);
};
cc.TransitionMoveInT = cc.TransitionMoveInL.extend({
    ctor:function (t, scene) {
        cc.TransitionMoveInL.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    initScenes:function () {
        this._inScene.setPosition(0, cc.director.getWinSize().height);
    }
});
cc.TransitionMoveInT.create = function (t, scene) {
    return new cc.TransitionMoveInT(t, scene);
};
cc.TransitionMoveInB = cc.TransitionMoveInL.extend({
    ctor:function (t, scene) {
        cc.TransitionMoveInL.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    initScenes:function () {
        this._inScene.setPosition(0, -cc.director.getWinSize().height);
    }
});
cc.TransitionMoveInB.create = function (t, scene) {
    return new cc.TransitionMoveInB(t, scene);
};
cc.ADJUST_FACTOR = 0.5;
cc.TransitionSlideInL = cc.TransitionScene.extend({
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = false;
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this.initScenes();
        var inA = this.action();
        var outA = this.action();
        var inAction = cc.sequence(this.easeActionWithAction(inA), cc.callFunc(this.finish, this));
        var outAction = this.easeActionWithAction(outA);
        this._inScene.runAction(inAction);
        this._outScene.runAction(outAction);
    },
    initScenes:function () {
        this._inScene.setPosition(-cc.director.getWinSize().width + cc.ADJUST_FACTOR, 0);
    },
    action:function () {
        return cc.moveBy(this._duration, cc.p(cc.director.getWinSize().width - cc.ADJUST_FACTOR, 0));
    },
    easeActionWithAction:function (action) {
        return new cc.EaseInOut(action, 2.0);
    }
});
cc.TransitionSlideInL.create = function (t, scene) {
    return new cc.TransitionSlideInL(t, scene);
};
cc.TransitionSlideInR = cc.TransitionSlideInL.extend({
    ctor:function (t, scene) {
        cc.TransitionSlideInL.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = true;
    },
    initScenes:function () {
        this._inScene.setPosition(cc.director.getWinSize().width - cc.ADJUST_FACTOR, 0);
    },
    action:function () {
        return cc.moveBy(this._duration, cc.p(-(cc.director.getWinSize().width - cc.ADJUST_FACTOR), 0));
    }
});
cc.TransitionSlideInR.create = function (t, scene) {
    return new cc.TransitionSlideInR(t, scene);
};
cc.TransitionSlideInB = cc.TransitionSlideInL.extend({
    ctor:function (t, scene) {
        cc.TransitionSlideInL.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = false;
    },
    initScenes:function () {
        this._inScene.setPosition(0, -(cc.director.getWinSize().height - cc.ADJUST_FACTOR));
    },
    action:function () {
        return cc.moveBy(this._duration, cc.p(0, cc.director.getWinSize().height - cc.ADJUST_FACTOR));
    }
});
cc.TransitionSlideInB.create = function (t, scene) {
    return new cc.TransitionSlideInB(t, scene);
};
cc.TransitionSlideInT = cc.TransitionSlideInL.extend({
    ctor:function (t, scene) {
        cc.TransitionSlideInL.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = true;
    },
    initScenes:function () {
        this._inScene.setPosition(0, cc.director.getWinSize().height - cc.ADJUST_FACTOR);
    },
    action:function () {
        return cc.moveBy(this._duration, cc.p(0, -(cc.director.getWinSize().height - cc.ADJUST_FACTOR)));
    }
});
cc.TransitionSlideInT.create = function (t, scene) {
    return new cc.TransitionSlideInT(t, scene);
};
cc.TransitionShrinkGrow = cc.TransitionScene.extend({
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this._inScene.attr({
            scale: 0.001,
            anchorX: 2 / 3.0,
            anchorY: 0.5
        });
        this._outScene.attr({
            scale: 1.0,
            anchorX: 1 / 3.0,
            anchorY: 0.5
        });
        var scaleOut = cc.scaleTo(this._duration, 0.01);
        var scaleIn = cc.scaleTo(this._duration, 1.0);
        this._inScene.runAction(cc.sequence(this.easeActionWithAction(scaleIn), cc.callFunc(this.finish, this)));
        this._outScene.runAction(this.easeActionWithAction(scaleOut));
    },
    easeActionWithAction:function (action) {
        return new cc.EaseOut(action, 2.0);
    }
});
cc.TransitionShrinkGrow.create = function (t, scene) {
    return new cc.TransitionShrinkGrow(t, scene);
};
cc.TransitionFade = cc.TransitionScene.extend({
    _color:null,
    ctor:function (t, scene, color) {
        cc.TransitionScene.prototype.ctor.call(this);
        this._color = cc.color();
        scene && this.initWithDuration(t, scene, color);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        var l = new cc.LayerColor(this._color);
        this._inScene.visible = false;
        this.addChild(l, 2, cc.SCENE_FADE);
        var f = this.getChildByTag(cc.SCENE_FADE);
        var a = cc.sequence(
            cc.fadeIn(this._duration / 2),
            cc.callFunc(this.hideOutShowIn, this),
            cc.fadeOut(this._duration / 2),
            cc.callFunc(this.finish, this)
        );
        f.runAction(a);
    },
    onExit:function () {
        cc.TransitionScene.prototype.onExit.call(this);
        this.removeChildByTag(cc.SCENE_FADE, false);
    },
    initWithDuration:function (t, scene, color) {
        color = color || cc.color.BLACK;
        if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
            this._color.r = color.r;
            this._color.g = color.g;
            this._color.b = color.b;
            this._color.a = 0;
        }
        return true;
    }
});
cc.TransitionFade.create = function (t, scene, color) {
    return new cc.TransitionFade(t, scene, color);
};
cc.TransitionCrossFade = cc.TransitionScene.extend({
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        var color = cc.color(0, 0, 0, 0);
        var winSize = cc.director.getWinSize();
        var layer = new cc.LayerColor(color);
        var inTexture = new cc.RenderTexture(winSize.width, winSize.height);
        inTexture.sprite.anchorX = 0.5;
        inTexture.sprite.anchorY = 0.5;
        inTexture.attr({
            x: winSize.width / 2,
            y: winSize.height / 2,
            anchorX: 0.5,
            anchorY: 0.5
        });
        inTexture.begin();
        this._inScene.visit();
        inTexture.end();
        var outTexture = new cc.RenderTexture(winSize.width, winSize.height);
        outTexture.setPosition(winSize.width / 2, winSize.height / 2);
        outTexture.sprite.anchorX = outTexture.anchorX = 0.5;
        outTexture.sprite.anchorY = outTexture.anchorY = 0.5;
        outTexture.begin();
        this._outScene.visit();
        outTexture.end();
        inTexture.sprite.setBlendFunc(cc.ONE, cc.ONE);
        outTexture.sprite.setBlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
        layer.addChild(inTexture);
        layer.addChild(outTexture);
        inTexture.sprite.opacity = 255;
        outTexture.sprite.opacity = 255;
        var layerAction = cc.sequence(
            cc.fadeTo(this._duration, 0), cc.callFunc(this.hideOutShowIn, this),
            cc.callFunc(this.finish, this)
        );
        outTexture.sprite.runAction(layerAction);
        this.addChild(layer, 2, cc.SCENE_FADE);
    },
    onExit:function () {
        this.removeChildByTag(cc.SCENE_FADE, false);
        cc.TransitionScene.prototype.onExit.call(this);
    },
    visit:function () {
        cc.Node.prototype.visit.call(this);
    },
    draw:function () {
    }
});
cc.TransitionCrossFade.create = function (t, scene) {
    return new cc.TransitionCrossFade(t, scene);
};
cc.TransitionTurnOffTiles = cc.TransitionScene.extend({
    _gridProxy: null,
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        this._gridProxy = new cc.NodeGrid();
        scene && this.initWithDuration(t, scene);
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = false;
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this._gridProxy.setTarget(this._outScene);
        this._gridProxy.onEnter();
        var winSize = cc.director.getWinSize();
        var aspect = winSize.width / winSize.height;
        var x = 0 | (12 * aspect);
        var y = 12;
        var toff = cc.turnOffTiles(this._duration, cc.size(x, y));
        var action = this.easeActionWithAction(toff);
        this._gridProxy.runAction(cc.sequence(action, cc.callFunc(this.finish, this), cc.stopGrid()));
    },
    visit: function(){
        this._inScene.visit();
        this._gridProxy.visit();
    },
    easeActionWithAction:function (action) {
        return action;
    }
});
cc.TransitionTurnOffTiles.create = function (t, scene) {
    return new cc.TransitionTurnOffTiles(t, scene);
};
cc.TransitionSplitCols = cc.TransitionScene.extend({
    _gridProxy: null,
    _switchTargetToInscene: function(){
        this._gridProxy.setTarget(this._inScene);
    },
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        this._gridProxy = new cc.NodeGrid();
        scene && this.initWithDuration(t, scene);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this._gridProxy.setTarget(this._outScene);
        this._gridProxy.onEnter();
        var split = this.action();
        var seq = cc.sequence(
            split, cc.callFunc(this._switchTargetToInscene, this), split.reverse());
        this._gridProxy.runAction(
            cc.sequence(this.easeActionWithAction(seq), cc.callFunc(this.finish, this), cc.stopGrid())
        );
    },
    onExit: function(){
        this._gridProxy.setTarget(null);
        this._gridProxy.onExit();
        cc.TransitionScene.prototype.onExit.call(this);
    },
    visit: function(){
        this._gridProxy.visit();
    },
    easeActionWithAction:function (action) {
        return new cc.EaseInOut(action, 3.0);
    },
    action:function () {
        return cc.splitCols(this._duration / 2.0, 3);
    }
});
cc.TransitionSplitCols.create = function (t, scene) {
    return new cc.TransitionSplitCols(t, scene);
};
cc.TransitionSplitRows = cc.TransitionSplitCols.extend({
    ctor:function (t, scene) {
        cc.TransitionSplitCols.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    action:function () {
        return cc.splitRows(this._duration / 2.0, 3);
    }
});
cc.TransitionSplitRows.create = function (t, scene) {
    return new cc.TransitionSplitRows(t, scene);
};
cc.TransitionFadeTR = cc.TransitionScene.extend({
    _gridProxy: null,
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        this._gridProxy = new cc.NodeGrid();
        scene && this.initWithDuration(t, scene);
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = false;
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this._gridProxy.setTarget(this._outScene);
        this._gridProxy.onEnter();
        var winSize = cc.director.getWinSize();
        var aspect = winSize.width / winSize.height;
        var x = 0 | (12 * aspect);
        var y = 12;
        var action = this.actionWithSize(cc.size(x, y));
        this._gridProxy.runAction(
            cc.sequence(this.easeActionWithAction(action), cc.callFunc(this.finish, this), cc.stopGrid())
        );
    },
    visit: function(){
        this._inScene.visit();
        this._gridProxy.visit();
    },
    easeActionWithAction:function (action) {
        return action;
    },
    actionWithSize:function (size) {
        return cc.fadeOutTRTiles(this._duration, size);
    }
});
cc.TransitionFadeTR.create = function (t, scene) {
    return new cc.TransitionFadeTR(t, scene);
};
cc.TransitionFadeBL = cc.TransitionFadeTR.extend({
    ctor:function (t, scene) {
        cc.TransitionFadeTR.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    actionWithSize:function (size) {
        return cc.fadeOutBLTiles(this._duration, size);
    }
});
cc.TransitionFadeBL.create = function (t, scene) {
    return new cc.TransitionFadeBL(t, scene);
};
cc.TransitionFadeUp = cc.TransitionFadeTR.extend({
    ctor:function (t, scene) {
        cc.TransitionFadeTR.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    actionWithSize:function (size) {
        return new cc.FadeOutUpTiles(this._duration, size);
    }
});
cc.TransitionFadeUp.create = function (t, scene) {
    return new cc.TransitionFadeUp(t, scene);
};
cc.TransitionFadeDown = cc.TransitionFadeTR.extend({
    ctor:function (t, scene) {
        cc.TransitionFadeTR.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    actionWithSize:function (size) {
        return cc.fadeOutDownTiles( this._duration, size);
    }
});
cc.TransitionFadeDown.create = function (t, scene) {
    return new cc.TransitionFadeDown(t, scene);
};
cc.SCENE_RADIAL = 0xc001;
cc.TransitionProgress = cc.TransitionScene.extend({
    _to:0,
    _from:0,
    _sceneToBeModified:null,
    _className:"TransitionProgress",
    ctor:function (t, scene) {
        cc.TransitionScene.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _setAttrs: function(node, x, y) {
        node.attr({
            x: x,
            y: y,
            anchorX: 0.5,
            anchorY: 0.5
        });
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        this._setupTransition();
        var winSize = cc.director.getWinSize();
        var texture = new cc.RenderTexture(winSize.width, winSize.height);
        texture.sprite.anchorX = 0.5;
        texture.sprite.anchorY = 0.5;
        this._setAttrs(texture, winSize.width / 2, winSize.height / 2);
        texture.clear(0, 0, 0, 1);
        texture.begin();
        this._sceneToBeModified.visit();
        texture.end();
        if (this._sceneToBeModified === this._outScene)
            this.hideOutShowIn();
        var pNode = this._progressTimerNodeWithRenderTexture(texture);
        var layerAction = cc.sequence(
            cc.progressFromTo(this._duration, this._from, this._to),
            cc.callFunc(this.finish, this));
        pNode.runAction(layerAction);
        this.addChild(pNode, 2, cc.SCENE_RADIAL);
    },
    onExit:function () {
        this.removeChildByTag(cc.SCENE_RADIAL, true);
        cc.TransitionScene.prototype.onExit.call(this);
    },
    _setupTransition:function () {
        this._sceneToBeModified = this._outScene;
        this._from = 100;
        this._to = 0;
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        cc.log("cc.TransitionProgress._progressTimerNodeWithRenderTexture(): should be overridden in subclass");
        return null;
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = false;
    }
});
cc.TransitionProgress.create = function (t, scene) {
    return new cc.TransitionProgress(t, scene);
};
cc.TransitionProgressRadialCCW = cc.TransitionProgress.extend({
    ctor:function (t, scene) {
        cc.TransitionProgress.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        var size = cc.director.getWinSize();
        var pNode = new cc.ProgressTimer(texture.sprite);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            pNode.sprite.flippedY = true;
        pNode.type = cc.ProgressTimer.TYPE_RADIAL;
        pNode.reverseDir = false;
        pNode.percentage = 100;
        this._setAttrs(pNode, size.width / 2, size.height / 2);
        return pNode;
    }
});
cc.TransitionProgressRadialCCW.create = function (t, scene) {
    return new cc.TransitionProgressRadialCCW(t, scene);
};
cc.TransitionProgressRadialCW = cc.TransitionProgress.extend({
    ctor:function (t, scene) {
        cc.TransitionProgress.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        var size = cc.director.getWinSize();
        var pNode = new cc.ProgressTimer(texture.sprite);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            pNode.sprite.flippedY = true;
        pNode.type = cc.ProgressTimer.TYPE_RADIAL;
        pNode.reverseDir = true;
        pNode.percentage = 100;
        this._setAttrs(pNode, size.width / 2, size.height / 2);
        return pNode;
    }
});
cc.TransitionProgressRadialCW.create = function (t, scene) {
    var tempScene = new cc.TransitionProgressRadialCW();
    if ((tempScene !== null) && (tempScene.initWithDuration(t, scene))) {
        return tempScene;
    }
    return new cc.TransitionProgressRadialCW(t, scene);
};
cc.TransitionProgressHorizontal = cc.TransitionProgress.extend({
    ctor:function (t, scene) {
        cc.TransitionProgress.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        var size = cc.director.getWinSize();
        var pNode = new cc.ProgressTimer(texture.sprite);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            pNode.sprite.flippedY = true;
        pNode.type = cc.ProgressTimer.TYPE_BAR;
        pNode.midPoint = cc.p(1, 0);
        pNode.barChangeRate = cc.p(1, 0);
        pNode.percentage = 100;
        this._setAttrs(pNode, size.width / 2, size.height / 2);
        return pNode;
    }
});
cc.TransitionProgressHorizontal.create = function (t, scene) {
    return new cc.TransitionProgressHorizontal(t, scene);
};
cc.TransitionProgressVertical = cc.TransitionProgress.extend({
    ctor:function (t, scene) {
        cc.TransitionProgress.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        var size = cc.director.getWinSize();
        var pNode = new cc.ProgressTimer(texture.sprite);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            pNode.sprite.flippedY = true;
        pNode.type = cc.ProgressTimer.TYPE_BAR;
        pNode.midPoint = cc.p(0, 0);
        pNode.barChangeRate = cc.p(0, 1);
        pNode.percentage = 100;
        this._setAttrs(pNode, size.width / 2, size.height / 2);
        return pNode;
    }
});
cc.TransitionProgressVertical.create = function (t, scene) {
    return new cc.TransitionProgressVertical(t, scene);
};
cc.TransitionProgressInOut = cc.TransitionProgress.extend({
    ctor:function (t, scene) {
        cc.TransitionProgress.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        var size = cc.director.getWinSize();
        var pNode = new cc.ProgressTimer(texture.sprite);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            pNode.sprite.flippedY = true;
        pNode.type = cc.ProgressTimer.TYPE_BAR;
        pNode.midPoint = cc.p(0.5, 0.5);
        pNode.barChangeRate = cc.p(1, 1);
        pNode.percentage = 0;
        this._setAttrs(pNode, size.width / 2, size.height / 2);
        return pNode;
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = false;
    },
    _setupTransition:function () {
        this._sceneToBeModified = this._inScene;
        this._from = 0;
        this._to = 100;
    }
});
cc.TransitionProgressInOut.create = function (t, scene) {
    return new cc.TransitionProgressInOut(t, scene);
};
cc.TransitionProgressOutIn = cc.TransitionProgress.extend({
    ctor:function (t, scene) {
        cc.TransitionProgress.prototype.ctor.call(this);
        scene && this.initWithDuration(t, scene);
    },
    _progressTimerNodeWithRenderTexture:function (texture) {
        var size = cc.director.getWinSize();
        var pNode = new cc.ProgressTimer(texture.sprite);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            pNode.sprite.flippedY = true;
        pNode.type = cc.ProgressTimer.TYPE_BAR;
        pNode.midPoint = cc.p(0.5, 0.5);
        pNode.barChangeRate = cc.p(1, 1);
        pNode.percentage = 100;
        this._setAttrs(pNode, size.width / 2, size.height / 2);
        return pNode;
    }
});
cc.TransitionProgressOutIn.create = function (t, scene) {
    return new cc.TransitionProgressOutIn(t, scene);
};
cc.TransitionPageTurn = cc.TransitionScene.extend({
    ctor:function (t, scene, backwards) {
        cc.TransitionScene.prototype.ctor.call(this);
        this._gridProxy = new cc.NodeGrid();
        this.initWithDuration(t, scene, backwards);
    },
    _back:true,
    _gridProxy: null,
    _className:"TransitionPageTurn",
    initWithDuration:function (t, scene, backwards) {
        this._back = backwards;
        if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
        }
        return true;
    },
    actionWithSize:function (vector) {
        if (this._back)
            return cc.reverseTime(cc.pageTurn3D(this._duration, vector));
        else
            return cc.pageTurn3D(this._duration, vector);
    },
    onEnter:function () {
        cc.TransitionScene.prototype.onEnter.call(this);
        var winSize = cc.director.getWinSize();
        var x, y;
        if (winSize.width > winSize.height) {
            x = 16;
            y = 12;
        } else {
            x = 12;
            y = 16;
        }
        var action = this.actionWithSize(cc.size(x, y)), gridProxy = this._gridProxy;
        if (!this._back) {
            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();
            this._inScene.visible = false;
            gridProxy.runAction(
                cc.sequence(action, cc.callFunc(this.finish, this), cc.stopGrid())
            );
            this._inScene.runAction(cc.show());
        }
    },
    visit: function(){
        if(this._back)
            this._outScene.visit();
        else
            this._inScene.visit();
        this._gridProxy.visit();
    },
    _sceneOrder:function () {
        this._isInSceneOnTop = this._back;
    }
});
cc.TransitionPageTurn.create = function (t, scene, backwards) {
    return new cc.TransitionPageTurn(t, scene, backwards);
};
cc.Codec = {name:'Jacob__Codec'};
cc.unzip = function () {
    return cc.Codec.GZip.gunzip.apply(cc.Codec.GZip, arguments);
};
cc.unzipBase64 = function () {
    var tmpInput = cc.Codec.Base64.decode.apply(cc.Codec.Base64, arguments);
    return   cc.Codec.GZip.gunzip.apply(cc.Codec.GZip, [tmpInput]);
};
cc.unzipBase64AsArray = function (input, bytes) {
    bytes = bytes || 1;
    var dec = this.unzipBase64(input),
        ar = [], i, j, len;
    for (i = 0, len = dec.length / bytes; i < len; i++) {
        ar[i] = 0;
        for (j = bytes - 1; j >= 0; --j) {
            ar[i] += dec.charCodeAt((i * bytes) + j) << (j * 8);
        }
    }
    return ar;
};
cc.unzipAsArray = function (input, bytes) {
    bytes = bytes || 1;
    var dec = this.unzip(input),
        ar = [], i, j, len;
    for (i = 0, len = dec.length / bytes; i < len; i++) {
        ar[i] = 0;
        for (j = bytes - 1; j >= 0; --j) {
            ar[i] += dec.charCodeAt((i * bytes) + j) << (j * 8);
        }
    }
    return ar;
};
cc.StringToArray = function (input) {
    var tmp = input.split(","), ar = [], i;
    for (i = 0; i < tmp.length; i++) {
        ar.push(parseInt(tmp[i]));
    }
    return ar;
};
cc.Codec.Base64 = {name:'Jacob__Codec__Base64'};
cc.Codec.Base64._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
cc.Codec.Base64.decode = function Jacob__Codec__Base64__decode(input) {
    var output = [],
        chr1, chr2, chr3,
        enc1, enc2, enc3, enc4,
        i = 0;
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    while (i < input.length) {
        enc1 = this._keyStr.indexOf(input.charAt(i++));
        enc2 = this._keyStr.indexOf(input.charAt(i++));
        enc3 = this._keyStr.indexOf(input.charAt(i++));
        enc4 = this._keyStr.indexOf(input.charAt(i++));
        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;
        output.push(String.fromCharCode(chr1));
        if (enc3 !== 64) {
            output.push(String.fromCharCode(chr2));
        }
        if (enc4 !== 64) {
            output.push(String.fromCharCode(chr3));
        }
    }
    output = output.join('');
    return output;
};
cc.Codec.Base64.decodeAsArray = function Jacob__Codec__Base64___decodeAsArray(input, bytes) {
    var dec = this.decode(input),
        ar = [], i, j, len;
    for (i = 0, len = dec.length / bytes; i < len; i++) {
        ar[i] = 0;
        for (j = bytes - 1; j >= 0; --j) {
            ar[i] += dec.charCodeAt((i * bytes) + j) << (j * 8);
        }
    }
    return ar;
};
cc.uint8ArrayToUint32Array = function(uint8Arr){
    if(uint8Arr.length % 4 !== 0)
        return null;
    var arrLen = uint8Arr.length /4;
    var retArr = window.Uint32Array? new Uint32Array(arrLen) : [];
    for(var i = 0; i < arrLen; i++){
        var offset = i * 4;
        retArr[i] = uint8Arr[offset]  + uint8Arr[offset + 1] * (1 << 8) + uint8Arr[offset + 2] * (1 << 16) + uint8Arr[offset + 3] * (1<<24);
    }
    return retArr;
};
cc.Codec.GZip = function Jacob__GZip(data) {
    this.data = data;
    this.debug = false;
    this.gpflags = undefined;
    this.files = 0;
    this.unzipped = [];
    this.buf32k = new Array(32768);
    this.bIdx = 0;
    this.modeZIP = false;
    this.bytepos = 0;
    this.bb = 1;
    this.bits = 0;
    this.nameBuf = [];
    this.fileout = undefined;
    this.literalTree = new Array(cc.Codec.GZip.LITERALS);
    this.distanceTree = new Array(32);
    this.treepos = 0;
    this.Places = null;
    this.len = 0;
    this.fpos = new Array(17);
    this.fpos[0] = 0;
    this.flens = undefined;
    this.fmax = undefined;
};
cc.Codec.GZip.gunzip = function (string) {
    if (string.constructor === Array) {
    } else if (string.constructor === String) {
    }
    var gzip = new cc.Codec.GZip(string);
    return gzip.gunzip()[0][0];
};
cc.Codec.GZip.HufNode = function () {
    this.b0 = 0;
    this.b1 = 0;
    this.jump = null;
    this.jumppos = -1;
};
cc.Codec.GZip.LITERALS = 288;
cc.Codec.GZip.NAMEMAX = 256;
cc.Codec.GZip.bitReverse = [
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
];
cc.Codec.GZip.cplens = [
    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
];
cc.Codec.GZip.cplext = [
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
];
cc.Codec.GZip.cpdist = [
    0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d,
    0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1,
    0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01,
    0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001
];
cc.Codec.GZip.cpdext = [
    0, 0, 0, 0, 1, 1, 2, 2,
    3, 3, 4, 4, 5, 5, 6, 6,
    7, 7, 8, 8, 9, 9, 10, 10,
    11, 11, 12, 12, 13, 13
];
cc.Codec.GZip.border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
cc.Codec.GZip.prototype.gunzip = function () {
    this.outputArr = [];
    this.nextFile();
    return this.unzipped;
};
cc.Codec.GZip.prototype.readByte = function () {
    this.bits += 8;
    if (this.bytepos < this.data.length) {
        return this.data.charCodeAt(this.bytepos++);
    } else {
        return -1;
    }
};
cc.Codec.GZip.prototype.byteAlign = function () {
    this.bb = 1;
};
cc.Codec.GZip.prototype.readBit = function () {
    var carry;
    this.bits++;
    carry = (this.bb & 1);
    this.bb >>= 1;
    if (this.bb === 0) {
        this.bb = this.readByte();
        carry = (this.bb & 1);
        this.bb = (this.bb >> 1) | 0x80;
    }
    return carry;
};
cc.Codec.GZip.prototype.readBits = function (a) {
    var res = 0,
        i = a;
    while (i--) res = (res << 1) | this.readBit();
    if (a) res = cc.Codec.GZip.bitReverse[res] >> (8 - a);
    return res;
};
cc.Codec.GZip.prototype.flushBuffer = function () {
    this.bIdx = 0;
};
cc.Codec.GZip.prototype.addBuffer = function (a) {
    this.buf32k[this.bIdx++] = a;
    this.outputArr.push(String.fromCharCode(a));
    if (this.bIdx === 0x8000) this.bIdx = 0;
};
cc.Codec.GZip.prototype.IsPat = function () {
    while (1) {
        if (this.fpos[this.len] >= this.fmax)       return -1;
        if (this.flens[this.fpos[this.len]] === this.len) return this.fpos[this.len]++;
        this.fpos[this.len]++;
    }
};
cc.Codec.GZip.prototype.Rec = function () {
    var curplace = this.Places[this.treepos];
    var tmp;
    if (this.len === 17) {
        return -1;
    }
    this.treepos++;
    this.len++;
    tmp = this.IsPat();
    if (tmp >= 0) {
        curplace.b0 = tmp;
    } else {
        curplace.b0 = 0x8000;
        if (this.Rec()) return -1;
    }
    tmp = this.IsPat();
    if (tmp >= 0) {
        curplace.b1 = tmp;
        curplace.jump = null;
    } else {
        curplace.b1 = 0x8000;
        curplace.jump = this.Places[this.treepos];
        curplace.jumppos = this.treepos;
        if (this.Rec()) return -1;
    }
    this.len--;
    return 0;
};
cc.Codec.GZip.prototype.CreateTree = function (currentTree, numval, lengths, show) {
    var i;
    this.Places = currentTree;
    this.treepos = 0;
    this.flens = lengths;
    this.fmax = numval;
    for (i = 0; i < 17; i++) this.fpos[i] = 0;
    this.len = 0;
    if (this.Rec()) {
        return -1;
    }
    return 0;
};
cc.Codec.GZip.prototype.DecodeValue = function (currentTree) {
    var len, i,
        xtreepos = 0,
        X = currentTree[xtreepos],
        b;
    while (1) {
        b = this.readBit();
        if (b) {
            if (!(X.b1 & 0x8000)) {
                return X.b1;
            }
            X = X.jump;
            len = currentTree.length;
            for (i = 0; i < len; i++) {
                if (currentTree[i] === X) {
                    xtreepos = i;
                    break;
                }
            }
        } else {
            if (!(X.b0 & 0x8000)) {
                return X.b0;
            }
            xtreepos++;
            X = currentTree[xtreepos];
        }
    }
    return -1;
};
cc.Codec.GZip.prototype.DeflateLoop = function () {
    var last, c, type, i, len;
    do {
        last = this.readBit();
        type = this.readBits(2);
        if (type === 0) {
            var blockLen, cSum;
            this.byteAlign();
            blockLen = this.readByte();
            blockLen |= (this.readByte() << 8);
            cSum = this.readByte();
            cSum |= (this.readByte() << 8);
            if (((blockLen ^ ~cSum) & 0xffff)) {
                document.write("BlockLen checksum mismatch\n");
            }
            while (blockLen--) {
                c = this.readByte();
                this.addBuffer(c);
            }
        } else if (type === 1) {
            var j;
            while (1) {
                j = (cc.Codec.GZip.bitReverse[this.readBits(7)] >> 1);
                if (j > 23) {
                    j = (j << 1) | this.readBit();
                    if (j > 199) {
                        j -= 128;
                        j = (j << 1) | this.readBit();
                    } else {
                        j -= 48;
                        if (j > 143) {
                            j = j + 136;
                        }
                    }
                } else {
                    j += 256;
                }
                if (j < 256) {
                    this.addBuffer(j);
                } else if (j === 256) {
                    break;
                } else {
                    var len, dist;
                    j -= 256 + 1;
                    len = this.readBits(cc.Codec.GZip.cplext[j]) + cc.Codec.GZip.cplens[j];
                    j = cc.Codec.GZip.bitReverse[this.readBits(5)] >> 3;
                    if (cc.Codec.GZip.cpdext[j] > 8) {
                        dist = this.readBits(8);
                        dist |= (this.readBits(cc.Codec.GZip.cpdext[j] - 8) << 8);
                    } else {
                        dist = this.readBits(cc.Codec.GZip.cpdext[j]);
                    }
                    dist += cc.Codec.GZip.cpdist[j];
                    for (j = 0; j < len; j++) {
                        var c = this.buf32k[(this.bIdx - dist) & 0x7fff];
                        this.addBuffer(c);
                    }
                }
            }
        } else if (type === 2) {
            var j, n, literalCodes, distCodes, lenCodes;
            var ll = new Array(288 + 32);
            literalCodes = 257 + this.readBits(5);
            distCodes = 1 + this.readBits(5);
            lenCodes = 4 + this.readBits(4);
            for (j = 0; j < 19; j++) {
                ll[j] = 0;
            }
            for (j = 0; j < lenCodes; j++) {
                ll[cc.Codec.GZip.border[j]] = this.readBits(3);
            }
            len = this.distanceTree.length;
            for (i = 0; i < len; i++) this.distanceTree[i] = new cc.Codec.GZip.HufNode();
            if (this.CreateTree(this.distanceTree, 19, ll, 0)) {
                this.flushBuffer();
                return 1;
            }
            n = literalCodes + distCodes;
            i = 0;
            var z = -1;
            while (i < n) {
                z++;
                j = this.DecodeValue(this.distanceTree);
                if (j < 16) {
                    ll[i++] = j;
                } else if (j === 16) {
                    var l;
                    j = 3 + this.readBits(2);
                    if (i + j > n) {
                        this.flushBuffer();
                        return 1;
                    }
                    l = i ? ll[i - 1] : 0;
                    while (j--) {
                        ll[i++] = l;
                    }
                } else {
                    if (j === 17) {
                        j = 3 + this.readBits(3);
                    } else {
                        j = 11 + this.readBits(7);
                    }
                    if (i + j > n) {
                        this.flushBuffer();
                        return 1;
                    }
                    while (j--) {
                        ll[i++] = 0;
                    }
                }
            }
            len = this.literalTree.length;
            for (i = 0; i < len; i++)
                this.literalTree[i] = new cc.Codec.GZip.HufNode();
            if (this.CreateTree(this.literalTree, literalCodes, ll, 0)) {
                this.flushBuffer();
                return 1;
            }
            len = this.literalTree.length;
            for (i = 0; i < len; i++) this.distanceTree[i] = new cc.Codec.GZip.HufNode();
            var ll2 = new Array();
            for (i = literalCodes; i < ll.length; i++) ll2[i - literalCodes] = ll[i];
            if (this.CreateTree(this.distanceTree, distCodes, ll2, 0)) {
                this.flushBuffer();
                return 1;
            }
            while (1) {
                j = this.DecodeValue(this.literalTree);
                if (j >= 256) {
                    var len, dist;
                    j -= 256;
                    if (j === 0) {
                        break;
                    }
                    j--;
                    len = this.readBits(cc.Codec.GZip.cplext[j]) + cc.Codec.GZip.cplens[j];
                    j = this.DecodeValue(this.distanceTree);
                    if (cc.Codec.GZip.cpdext[j] > 8) {
                        dist = this.readBits(8);
                        dist |= (this.readBits(cc.Codec.GZip.cpdext[j] - 8) << 8);
                    } else {
                        dist = this.readBits(cc.Codec.GZip.cpdext[j]);
                    }
                    dist += cc.Codec.GZip.cpdist[j];
                    while (len--) {
                        var c = this.buf32k[(this.bIdx - dist) & 0x7fff];
                        this.addBuffer(c);
                    }
                } else {
                    this.addBuffer(j);
                }
            }
        }
    } while (!last);
    this.flushBuffer();
    this.byteAlign();
    return 0;
};
cc.Codec.GZip.prototype.unzipFile = function (name) {
    var i;
    this.gunzip();
    for (i = 0; i < this.unzipped.length; i++) {
        if (this.unzipped[i][1] === name) {
            return this.unzipped[i][0];
        }
    }
};
cc.Codec.GZip.prototype.nextFile = function () {
    this.outputArr = [];
    this.modeZIP = false;
    var tmp = [];
    tmp[0] = this.readByte();
    tmp[1] = this.readByte();
    if (tmp[0] === 0x78 && tmp[1] === 0xda) {
        this.DeflateLoop();
        this.unzipped[this.files] = [this.outputArr.join(''), "geonext.gxt"];
        this.files++;
    }
    if (tmp[0] === 0x1f && tmp[1] === 0x8b) {
        this.skipdir();
        this.unzipped[this.files] = [this.outputArr.join(''), "file"];
        this.files++;
    }
    if (tmp[0] === 0x50 && tmp[1] === 0x4b) {
        this.modeZIP = true;
        tmp[2] = this.readByte();
        tmp[3] = this.readByte();
        if (tmp[2] === 0x03 && tmp[3] === 0x04) {
            tmp[0] = this.readByte();
            tmp[1] = this.readByte();
            this.gpflags = this.readByte();
            this.gpflags |= (this.readByte() << 8);
            var method = this.readByte();
            method |= (this.readByte() << 8);
            this.readByte();
            this.readByte();
            this.readByte();
            this.readByte();
            var compSize = this.readByte();
            compSize |= (this.readByte() << 8);
            compSize |= (this.readByte() << 16);
            compSize |= (this.readByte() << 24);
            var size = this.readByte();
            size |= (this.readByte() << 8);
            size |= (this.readByte() << 16);
            size |= (this.readByte() << 24);
            var filelen = this.readByte();
            filelen |= (this.readByte() << 8);
            var extralen = this.readByte();
            extralen |= (this.readByte() << 8);
            i = 0;
            this.nameBuf = [];
            while (filelen--) {
                var c = this.readByte();
                if (c === "/" | c === ":") {
                    i = 0;
                } else if (i < cc.Codec.GZip.NAMEMAX - 1) {
                    this.nameBuf[i++] = String.fromCharCode(c);
                }
            }
            if (!this.fileout) this.fileout = this.nameBuf;
            var i = 0;
            while (i < extralen) {
                c = this.readByte();
                i++;
            }
            if (method === 8) {
                this.DeflateLoop();
                this.unzipped[this.files] = [this.outputArr.join(''), this.nameBuf.join('')];
                this.files++;
            }
            this.skipdir();
        }
    }
};
cc.Codec.GZip.prototype.skipdir = function () {
    var tmp = [];
    var compSize, size, os, i, c;
    if ((this.gpflags & 8)) {
        tmp[0] = this.readByte();
        tmp[1] = this.readByte();
        tmp[2] = this.readByte();
        tmp[3] = this.readByte();
        compSize = this.readByte();
        compSize |= (this.readByte() << 8);
        compSize |= (this.readByte() << 16);
        compSize |= (this.readByte() << 24);
        size = this.readByte();
        size |= (this.readByte() << 8);
        size |= (this.readByte() << 16);
        size |= (this.readByte() << 24);
    }
    if (this.modeZIP) this.nextFile();
    tmp[0] = this.readByte();
    if (tmp[0] !== 8) {
        return 0;
    }
    this.gpflags = this.readByte();
    this.readByte();
    this.readByte();
    this.readByte();
    this.readByte();
    this.readByte();
    os = this.readByte();
    if ((this.gpflags & 4)) {
        tmp[0] = this.readByte();
        tmp[2] = this.readByte();
        this.len = tmp[0] + 256 * tmp[1];
        for (i = 0; i < this.len; i++)
            this.readByte();
    }
    if ((this.gpflags & 8)) {
        i = 0;
        this.nameBuf = [];
        while (c = this.readByte()) {
            if (c === "7" || c === ":")
                i = 0;
            if (i < cc.Codec.GZip.NAMEMAX - 1)
                this.nameBuf[i++] = c;
        }
    }
    if ((this.gpflags & 16)) {
        while (c = this.readByte()) {
        }
    }
    if ((this.gpflags & 2)) {
        this.readByte();
        this.readByte();
    }
    this.DeflateLoop();
    size = this.readByte();
    size |= (this.readByte() << 8);
    size |= (this.readByte() << 16);
    size |= (this.readByte() << 24);
    if (this.modeZIP) this.nextFile();
};
(function() {'use strict';function i(a){throw a;}var r=void 0,v=!0,aa=this;function y(a,c){var b=a.split("."),e=aa;!(b[0]in e)&&e.execScript&&e.execScript("var "+b[0]);for(var f;b.length&&(f=b.shift());)!b.length&&c!==r?e[f]=c:e=e[f]?e[f]:e[f]={}};var H="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;function ba(a){if("string"===typeof a){var c=a.split(""),b,e;b=0;for(e=c.length;b<e;b++)c[b]=(c[b].charCodeAt(0)&255)>>>0;a=c}for(var f=1,d=0,g=a.length,h,m=0;0<g;){h=1024<g?1024:g;g-=h;do f+=a[m++],d+=f;while(--h);f%=65521;d%=65521}return(d<<16|f)>>>0};function J(a,c){this.index="number"===typeof c?c:0;this.i=0;this.buffer=a instanceof(H?Uint8Array:Array)?a:new (H?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&i(Error("invalid index"));this.buffer.length<=this.index&&this.f()}J.prototype.f=function(){var a=this.buffer,c,b=a.length,e=new (H?Uint8Array:Array)(b<<1);if(H)e.set(a);else for(c=0;c<b;++c)e[c]=a[c];return this.buffer=e};
J.prototype.d=function(a,c,b){var e=this.buffer,f=this.index,d=this.i,g=e[f],h;b&&1<c&&(a=8<c?(N[a&255]<<24|N[a>>>8&255]<<16|N[a>>>16&255]<<8|N[a>>>24&255])>>32-c:N[a]>>8-c);if(8>c+d)g=g<<c|a,d+=c;else for(h=0;h<c;++h)g=g<<1|a>>c-h-1&1,8===++d&&(d=0,e[f++]=N[g],g=0,f===e.length&&(e=this.f()));e[f]=g;this.buffer=e;this.i=d;this.index=f};J.prototype.finish=function(){var a=this.buffer,c=this.index,b;0<this.i&&(a[c]<<=8-this.i,a[c]=N[a[c]],c++);H?b=a.subarray(0,c):(a.length=c,b=a);return b};
var ca=new (H?Uint8Array:Array)(256),ha;for(ha=0;256>ha;++ha){for(var R=ha,ia=R,ja=7,R=R>>>1;R;R>>>=1)ia<<=1,ia|=R&1,--ja;ca[ha]=(ia<<ja&255)>>>0}var N=ca;var ka=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];H&&new Uint32Array(ka);function la(a){this.buffer=new (H?Uint16Array:Array)(2*a);this.length=0}la.prototype.getParent=function(a){return 2*((a-2)/4|0)};la.prototype.push=function(a,c){var b,e,f=this.buffer,d;b=this.length;f[this.length++]=c;for(f[this.length++]=a;0<b;)if(e=this.getParent(b),f[b]>f[e])d=f[b],f[b]=f[e],f[e]=d,d=f[b+1],f[b+1]=f[e+1],f[e+1]=d,b=e;else break;return this.length};
la.prototype.pop=function(){var a,c,b=this.buffer,e,f,d;c=b[0];a=b[1];this.length-=2;b[0]=b[this.length];b[1]=b[this.length+1];for(d=0;;){f=2*d+2;if(f>=this.length)break;f+2<this.length&&b[f+2]>b[f]&&(f+=2);if(b[f]>b[d])e=b[d],b[d]=b[f],b[f]=e,e=b[d+1],b[d+1]=b[f+1],b[f+1]=e;else break;d=f}return{index:a,value:c,length:this.length}};function S(a){var c=a.length,b=0,e=Number.POSITIVE_INFINITY,f,d,g,h,m,j,s,n,l;for(n=0;n<c;++n)a[n]>b&&(b=a[n]),a[n]<e&&(e=a[n]);f=1<<b;d=new (H?Uint32Array:Array)(f);g=1;h=0;for(m=2;g<=b;){for(n=0;n<c;++n)if(a[n]===g){j=0;s=h;for(l=0;l<g;++l)j=j<<1|s&1,s>>=1;for(l=j;l<f;l+=m)d[l]=g<<16|n;++h}++g;h<<=1;m<<=1}return[d,b,e]};function ma(a,c){this.h=pa;this.w=0;this.input=a;this.b=0;c&&(c.lazy&&(this.w=c.lazy),"number"===typeof c.compressionType&&(this.h=c.compressionType),c.outputBuffer&&(this.a=H&&c.outputBuffer instanceof Array?new Uint8Array(c.outputBuffer):c.outputBuffer),"number"===typeof c.outputIndex&&(this.b=c.outputIndex));this.a||(this.a=new (H?Uint8Array:Array)(32768))}var pa=2,qa={NONE:0,r:1,j:pa,N:3},ra=[],T;
for(T=0;288>T;T++)switch(v){case 143>=T:ra.push([T+48,8]);break;case 255>=T:ra.push([T-144+400,9]);break;case 279>=T:ra.push([T-256+0,7]);break;case 287>=T:ra.push([T-280+192,8]);break;default:i("invalid literal: "+T)}
ma.prototype.n=function(){var a,c,b,e,f=this.input;switch(this.h){case 0:b=0;for(e=f.length;b<e;){c=H?f.subarray(b,b+65535):f.slice(b,b+65535);b+=c.length;var d=c,g=b===e,h=r,m=r,j=r,s=r,n=r,l=this.a,q=this.b;if(H){for(l=new Uint8Array(this.a.buffer);l.length<=q+d.length+5;)l=new Uint8Array(l.length<<1);l.set(this.a)}h=g?1:0;l[q++]=h|0;m=d.length;j=~m+65536&65535;l[q++]=m&255;l[q++]=m>>>8&255;l[q++]=j&255;l[q++]=j>>>8&255;if(H)l.set(d,q),q+=d.length,l=l.subarray(0,q);else{s=0;for(n=d.length;s<n;++s)l[q++]=
d[s];l.length=q}this.b=q;this.a=l}break;case 1:var E=new J(new Uint8Array(this.a.buffer),this.b);E.d(1,1,v);E.d(1,2,v);var t=sa(this,f),z,K,A;z=0;for(K=t.length;z<K;z++)if(A=t[z],J.prototype.d.apply(E,ra[A]),256<A)E.d(t[++z],t[++z],v),E.d(t[++z],5),E.d(t[++z],t[++z],v);else if(256===A)break;this.a=E.finish();this.b=this.a.length;break;case pa:var x=new J(new Uint8Array(this.a),this.b),B,k,p,D,C,da=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],W,Ma,ea,Na,na,va=Array(19),Oa,$,oa,F,Pa;B=pa;x.d(1,
1,v);x.d(B,2,v);k=sa(this,f);W=ta(this.L,15);Ma=ua(W);ea=ta(this.K,7);Na=ua(ea);for(p=286;257<p&&0===W[p-1];p--);for(D=30;1<D&&0===ea[D-1];D--);var Qa=p,Ra=D,M=new (H?Uint32Array:Array)(Qa+Ra),u,O,w,fa,L=new (H?Uint32Array:Array)(316),I,G,P=new (H?Uint8Array:Array)(19);for(u=O=0;u<Qa;u++)M[O++]=W[u];for(u=0;u<Ra;u++)M[O++]=ea[u];if(!H){u=0;for(fa=P.length;u<fa;++u)P[u]=0}u=I=0;for(fa=M.length;u<fa;u+=O){for(O=1;u+O<fa&&M[u+O]===M[u];++O);w=O;if(0===M[u])if(3>w)for(;0<w--;)L[I++]=0,P[0]++;else for(;0<
w;)G=138>w?w:138,G>w-3&&G<w&&(G=w-3),10>=G?(L[I++]=17,L[I++]=G-3,P[17]++):(L[I++]=18,L[I++]=G-11,P[18]++),w-=G;else if(L[I++]=M[u],P[M[u]]++,w--,3>w)for(;0<w--;)L[I++]=M[u],P[M[u]]++;else for(;0<w;)G=6>w?w:6,G>w-3&&G<w&&(G=w-3),L[I++]=16,L[I++]=G-3,P[16]++,w-=G}a=H?L.subarray(0,I):L.slice(0,I);na=ta(P,7);for(F=0;19>F;F++)va[F]=na[da[F]];for(C=19;4<C&&0===va[C-1];C--);Oa=ua(na);x.d(p-257,5,v);x.d(D-1,5,v);x.d(C-4,4,v);for(F=0;F<C;F++)x.d(va[F],3,v);F=0;for(Pa=a.length;F<Pa;F++)if($=a[F],x.d(Oa[$],
na[$],v),16<=$){F++;switch($){case 16:oa=2;break;case 17:oa=3;break;case 18:oa=7;break;default:i("invalid code: "+$)}x.d(a[F],oa,v)}var Sa=[Ma,W],Ta=[Na,ea],Q,Ua,ga,ya,Va,Wa,Xa,Ya;Va=Sa[0];Wa=Sa[1];Xa=Ta[0];Ya=Ta[1];Q=0;for(Ua=k.length;Q<Ua;++Q)if(ga=k[Q],x.d(Va[ga],Wa[ga],v),256<ga)x.d(k[++Q],k[++Q],v),ya=k[++Q],x.d(Xa[ya],Ya[ya],v),x.d(k[++Q],k[++Q],v);else if(256===ga)break;this.a=x.finish();this.b=this.a.length;break;default:i("invalid compression type")}return this.a};
function wa(a,c){this.length=a;this.G=c}
function xa(){var a=za;switch(v){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,a-
31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:i("invalid length: "+a)}}var Aa=[],za,Ba;
for(za=3;258>=za;za++)Ba=xa(),Aa[za]=Ba[2]<<24|Ba[1]<<16|Ba[0];var Ca=H?new Uint32Array(Aa):Aa;
function sa(a,c){function b(a,c){var b=a.G,d=[],e=0,f;f=Ca[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(v){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b-
65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>=
b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:i("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,j;h=0;for(j=d.length;h<j;++h)l[q++]=d[h];t[d[0]]++;z[d[3]]++;E=a.length+c-1;n=null}var e,f,d,g,h,m={},j,s,n,l=H?new Uint16Array(2*c.length):[],q=0,E=0,t=new (H?Uint32Array:Array)(286),z=new (H?Uint32Array:Array)(30),K=a.w,A;if(!H){for(d=0;285>=d;)t[d++]=0;for(d=0;29>=d;)z[d++]=0}t[256]=1;e=0;for(f=c.length;e<f;++e){d=h=0;
for(g=3;d<g&&e+d!==f;++d)h=h<<8|c[e+d];m[h]===r&&(m[h]=[]);j=m[h];if(!(0<E--)){for(;0<j.length&&32768<e-j[0];)j.shift();if(e+3>=f){n&&b(n,-1);d=0;for(g=f-e;d<g;++d)A=c[e+d],l[q++]=A,++t[A];break}if(0<j.length){var x=r,B=r,k=0,p=r,D=r,C=r,da=r,W=c.length,D=0,da=j.length;a:for(;D<da;D++){x=j[da-D-1];p=3;if(3<k){for(C=k;3<C;C--)if(c[x+C-1]!==c[e+C-1])continue a;p=k}for(;258>p&&e+p<W&&c[x+p]===c[e+p];)++p;p>k&&(B=x,k=p);if(258===p)break}s=new wa(k,e-B);n?n.length<s.length?(A=c[e-1],l[q++]=A,++t[A],b(s,
0)):b(n,-1):s.length<K?n=s:b(s,0)}else n?b(n,-1):(A=c[e],l[q++]=A,++t[A])}j.push(e)}l[q++]=256;t[256]++;a.L=t;a.K=z;return H?l.subarray(0,q):l}
function ta(a,c){function b(a){var c=z[a][K[a]];c===n?(b(a+1),b(a+1)):--E[c];++K[a]}var e=a.length,f=new la(572),d=new (H?Uint8Array:Array)(e),g,h,m,j,s;if(!H)for(j=0;j<e;j++)d[j]=0;for(j=0;j<e;++j)0<a[j]&&f.push(j,a[j]);g=Array(f.length/2);h=new (H?Uint32Array:Array)(f.length/2);if(1===g.length)return d[f.pop().index]=1,d;j=0;for(s=f.length/2;j<s;++j)g[j]=f.pop(),h[j]=g[j].value;var n=h.length,l=new (H?Uint16Array:Array)(c),q=new (H?Uint8Array:Array)(c),E=new (H?Uint8Array:Array)(n),t=Array(c),z=
Array(c),K=Array(c),A=(1<<c)-n,x=1<<c-1,B,k,p,D,C;l[c-1]=n;for(k=0;k<c;++k)A<x?q[k]=0:(q[k]=1,A-=x),A<<=1,l[c-2-k]=(l[c-1-k]/2|0)+n;l[0]=q[0];t[0]=Array(l[0]);z[0]=Array(l[0]);for(k=1;k<c;++k)l[k]>2*l[k-1]+q[k]&&(l[k]=2*l[k-1]+q[k]),t[k]=Array(l[k]),z[k]=Array(l[k]);for(B=0;B<n;++B)E[B]=c;for(p=0;p<l[c-1];++p)t[c-1][p]=h[p],z[c-1][p]=p;for(B=0;B<c;++B)K[B]=0;1===q[c-1]&&(--E[0],++K[c-1]);for(k=c-2;0<=k;--k){D=B=0;C=K[k+1];for(p=0;p<l[k];p++)D=t[k+1][C]+t[k+1][C+1],D>h[B]?(t[k][p]=D,z[k][p]=n,C+=2):
(t[k][p]=h[B],z[k][p]=B,++B);K[k]=0;1===q[k]&&b(k)}m=E;j=0;for(s=g.length;j<s;++j)d[g[j].index]=m[j];return d}function ua(a){var c=new (H?Uint16Array:Array)(a.length),b=[],e=[],f=0,d,g,h,m;d=0;for(g=a.length;d<g;d++)b[a[d]]=(b[a[d]]|0)+1;d=1;for(g=16;d<=g;d++)e[d]=f,f+=b[d]|0,f>1<<d&&i("overcommitted"),f<<=1;65536>f&&i("undercommitted");d=0;for(g=a.length;d<g;d++){f=e[a[d]];e[a[d]]+=1;h=c[d]=0;for(m=a[d];h<m;h++)c[d]=c[d]<<1|f&1,f>>>=1}return c};function Da(a,c){this.input=a;this.a=new (H?Uint8Array:Array)(32768);this.h=U.j;var b={},e;if((c||!(c={}))&&"number"===typeof c.compressionType)this.h=c.compressionType;for(e in c)b[e]=c[e];b.outputBuffer=this.a;this.z=new ma(this.input,b)}var U=qa;
Da.prototype.n=function(){var a,c,b,e,f,d,g,h=0;g=this.a;a=Ea;switch(a){case Ea:c=Math.LOG2E*Math.log(32768)-8;break;default:i(Error("invalid compression method"))}b=c<<4|a;g[h++]=b;switch(a){case Ea:switch(this.h){case U.NONE:f=0;break;case U.r:f=1;break;case U.j:f=2;break;default:i(Error("unsupported compression type"))}break;default:i(Error("invalid compression method"))}e=f<<6|0;g[h++]=e|31-(256*b+e)%31;d=ba(this.input);this.z.b=h;g=this.z.n();h=g.length;H&&(g=new Uint8Array(g.buffer),g.length<=
h+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,h+4));g[h++]=d>>24&255;g[h++]=d>>16&255;g[h++]=d>>8&255;g[h++]=d&255;return g};y("Zlib.Deflate",Da);y("Zlib.Deflate.compress",function(a,c){return(new Da(a,c)).n()});y("Zlib.Deflate.CompressionType",U);y("Zlib.Deflate.CompressionType.NONE",U.NONE);y("Zlib.Deflate.CompressionType.FIXED",U.r);y("Zlib.Deflate.CompressionType.DYNAMIC",U.j);function V(a,c){this.k=[];this.l=32768;this.e=this.g=this.c=this.q=0;this.input=H?new Uint8Array(a):a;this.s=!1;this.m=Fa;this.B=!1;if(c||!(c={}))c.index&&(this.c=c.index),c.bufferSize&&(this.l=c.bufferSize),c.bufferType&&(this.m=c.bufferType),c.resize&&(this.B=c.resize);switch(this.m){case Ga:this.b=32768;this.a=new (H?Uint8Array:Array)(32768+this.l+258);break;case Fa:this.b=0;this.a=new (H?Uint8Array:Array)(this.l);this.f=this.J;this.t=this.H;this.o=this.I;break;default:i(Error("invalid inflate mode"))}}
var Ga=0,Fa=1,Ha={D:Ga,C:Fa};
V.prototype.p=function(){for(;!this.s;){var a=X(this,3);a&1&&(this.s=v);a>>>=1;switch(a){case 0:var c=this.input,b=this.c,e=this.a,f=this.b,d=r,g=r,h=r,m=e.length,j=r;this.e=this.g=0;d=c[b++];d===r&&i(Error("invalid uncompressed block header: LEN (first byte)"));g=d;d=c[b++];d===r&&i(Error("invalid uncompressed block header: LEN (second byte)"));g|=d<<8;d=c[b++];d===r&&i(Error("invalid uncompressed block header: NLEN (first byte)"));h=d;d=c[b++];d===r&&i(Error("invalid uncompressed block header: NLEN (second byte)"));h|=
d<<8;g===~h&&i(Error("invalid uncompressed block header: length verify"));b+g>c.length&&i(Error("input buffer is broken"));switch(this.m){case Ga:for(;f+g>e.length;){j=m-f;g-=j;if(H)e.set(c.subarray(b,b+j),f),f+=j,b+=j;else for(;j--;)e[f++]=c[b++];this.b=f;e=this.f();f=this.b}break;case Fa:for(;f+g>e.length;)e=this.f({v:2});break;default:i(Error("invalid inflate mode"))}if(H)e.set(c.subarray(b,b+g),f),f+=g,b+=g;else for(;g--;)e[f++]=c[b++];this.c=b;this.b=f;this.a=e;break;case 1:this.o(Ia,Ja);break;
case 2:Ka(this);break;default:i(Error("unknown BTYPE: "+a))}}return this.t()};
var La=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Za=H?new Uint16Array(La):La,$a=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],ab=H?new Uint16Array($a):$a,bb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],cb=H?new Uint8Array(bb):bb,db=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],eb=H?new Uint16Array(db):db,fb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,
10,11,11,12,12,13,13],gb=H?new Uint8Array(fb):fb,hb=new (H?Uint8Array:Array)(288),Y,ib;Y=0;for(ib=hb.length;Y<ib;++Y)hb[Y]=143>=Y?8:255>=Y?9:279>=Y?7:8;var Ia=S(hb),jb=new (H?Uint8Array:Array)(30),kb,lb;kb=0;for(lb=jb.length;kb<lb;++kb)jb[kb]=5;var Ja=S(jb);function X(a,c){for(var b=a.g,e=a.e,f=a.input,d=a.c,g;e<c;)g=f[d++],g===r&&i(Error("input buffer is broken")),b|=g<<e,e+=8;g=b&(1<<c)-1;a.g=b>>>c;a.e=e-c;a.c=d;return g}
function mb(a,c){for(var b=a.g,e=a.e,f=a.input,d=a.c,g=c[0],h=c[1],m,j,s;e<h;)m=f[d++],m===r&&i(Error("input buffer is broken")),b|=m<<e,e+=8;j=g[b&(1<<h)-1];s=j>>>16;a.g=b>>s;a.e=e-s;a.c=d;return j&65535}
function Ka(a){function c(a,b,c){var d,e,f,g;for(g=0;g<a;)switch(d=mb(this,b),d){case 16:for(f=3+X(this,2);f--;)c[g++]=e;break;case 17:for(f=3+X(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+X(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}return c}var b=X(a,5)+257,e=X(a,5)+1,f=X(a,4)+4,d=new (H?Uint8Array:Array)(Za.length),g,h,m,j;for(j=0;j<f;++j)d[Za[j]]=X(a,3);g=S(d);h=new (H?Uint8Array:Array)(b);m=new (H?Uint8Array:Array)(e);a.o(S(c.call(a,b,g,h)),S(c.call(a,e,g,m)))}
V.prototype.o=function(a,c){var b=this.a,e=this.b;this.u=a;for(var f=b.length-258,d,g,h,m;256!==(d=mb(this,a));)if(256>d)e>=f&&(this.b=e,b=this.f(),e=this.b),b[e++]=d;else{g=d-257;m=ab[g];0<cb[g]&&(m+=X(this,cb[g]));d=mb(this,c);h=eb[d];0<gb[d]&&(h+=X(this,gb[d]));e>=f&&(this.b=e,b=this.f(),e=this.b);for(;m--;)b[e]=b[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e};
V.prototype.I=function(a,c){var b=this.a,e=this.b;this.u=a;for(var f=b.length,d,g,h,m;256!==(d=mb(this,a));)if(256>d)e>=f&&(b=this.f(),f=b.length),b[e++]=d;else{g=d-257;m=ab[g];0<cb[g]&&(m+=X(this,cb[g]));d=mb(this,c);h=eb[d];0<gb[d]&&(h+=X(this,gb[d]));e+m>f&&(b=this.f(),f=b.length);for(;m--;)b[e]=b[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e};
V.prototype.f=function(){var a=new (H?Uint8Array:Array)(this.b-32768),c=this.b-32768,b,e,f=this.a;if(H)a.set(f.subarray(32768,a.length));else{b=0;for(e=a.length;b<e;++b)a[b]=f[b+32768]}this.k.push(a);this.q+=a.length;if(H)f.set(f.subarray(c,c+32768));else for(b=0;32768>b;++b)f[b]=f[c+b];this.b=32768;return f};
V.prototype.J=function(a){var c,b=this.input.length/this.c+1|0,e,f,d,g=this.input,h=this.a;a&&("number"===typeof a.v&&(b=a.v),"number"===typeof a.F&&(b+=a.F));2>b?(e=(g.length-this.c)/this.u[2],d=258*(e/2)|0,f=d<h.length?h.length+d:h.length<<1):f=h.length*b;H?(c=new Uint8Array(f),c.set(h)):c=h;return this.a=c};
V.prototype.t=function(){var a=0,c=this.a,b=this.k,e,f=new (H?Uint8Array:Array)(this.q+(this.b-32768)),d,g,h,m;if(0===b.length)return H?this.a.subarray(32768,this.b):this.a.slice(32768,this.b);d=0;for(g=b.length;d<g;++d){e=b[d];h=0;for(m=e.length;h<m;++h)f[a++]=e[h]}d=32768;for(g=this.b;d<g;++d)f[a++]=c[d];this.k=[];return this.buffer=f};
V.prototype.H=function(){var a,c=this.b;H?this.B?(a=new Uint8Array(c),a.set(this.a.subarray(0,c))):a=this.a.subarray(0,c):(this.a.length>c&&(this.a.length=c),a=this.a);return this.buffer=a};function nb(a,c){var b,e;this.input=a;this.c=0;if(c||!(c={}))c.index&&(this.c=c.index),c.verify&&(this.M=c.verify);b=a[this.c++];e=a[this.c++];switch(b&15){case Ea:this.method=Ea;break;default:i(Error("unsupported compression method"))}0!==((b<<8)+e)%31&&i(Error("invalid fcheck flag:"+((b<<8)+e)%31));e&32&&i(Error("fdict flag is not supported"));this.A=new V(a,{index:this.c,bufferSize:c.bufferSize,bufferType:c.bufferType,resize:c.resize})}
nb.prototype.p=function(){var a=this.input,c,b;c=this.A.p();this.c=this.A.c;this.M&&(b=(a[this.c++]<<24|a[this.c++]<<16|a[this.c++]<<8|a[this.c++])>>>0,b!==ba(c)&&i(Error("invalid adler-32 checksum")));return c};y("Zlib.Inflate",nb);y("Zlib.Inflate.BufferType",Ha);Ha.ADAPTIVE=Ha.C;Ha.BLOCK=Ha.D;y("Zlib.Inflate.prototype.decompress",nb.prototype.p);var ob=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];H&&new Uint16Array(ob);var pb=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258];H&&new Uint16Array(pb);var qb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0];H&&new Uint8Array(qb);var rb=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577];H&&new Uint16Array(rb);
var sb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];H&&new Uint8Array(sb);var tb=new (H?Uint8Array:Array)(288),Z,ub;Z=0;for(ub=tb.length;Z<ub;++Z)tb[Z]=143>=Z?8:255>=Z?9:279>=Z?7:8;S(tb);var vb=new (H?Uint8Array:Array)(30),wb,xb;wb=0;for(xb=vb.length;wb<xb;++wb)vb[wb]=5;S(vb);var Ea=8;}).call(this);
var _p = window;
_p = _p.Zlib = _p["Zlib"];
_p.Deflate = _p["Deflate"];
_p.Deflate.compress =_p.Deflate["compress"];
_p.Inflate = _p["Inflate"];
_p.Inflate.BufferType = _p.Inflate["BufferType"];
_p.Inflate.prototype.decompress = _p.Inflate.prototype["decompress"];
cc.PNGReader = cc.Class.extend({
    ctor:function(data){
        var chunkSize, colors, delayDen, delayNum, frame, i, index, key, section, ccshort, text, _i, _j, _ref;
        this.data = data;
        this.pos = 8;
        this.palette = [];
        this.imgData = [];
        this.transparency = {};
        this.animation = null;
        this.text = {};
        frame = null;
        while (true) {
            chunkSize = this.readUInt32();
            section = ((function() {
                var _i, _results;
                _results = [];
                for (i = _i = 0; _i < 4; i = ++_i) {
                    _results.push(String.fromCharCode(this.data[this.pos++]));
                }
                return _results;
            }).call(this)).join('');
            switch (section) {
                case 'IHDR':
                    this.width = this.readUInt32();
                    this.height = this.readUInt32();
                    this.bits = this.data[this.pos++];
                    this.colorType = this.data[this.pos++];
                    this.compressionMethod = this.data[this.pos++];
                    this.filterMethod = this.data[this.pos++];
                    this.interlaceMethod = this.data[this.pos++];
                    break;
                case 'acTL':
                    this.animation = {
                        numFrames: this.readUInt32(),
                        numPlays: this.readUInt32() || Infinity,
                        frames: []
                    };
                    break;
                case 'PLTE':
                    this.palette = this.read(chunkSize);
                    break;
                case 'fcTL':
                    if (frame) {
                        this.animation.frames.push(frame);
                    }
                    this.pos += 4;
                    frame = {
                        width: this.readUInt32(),
                        height: this.readUInt32(),
                        xOffset: this.readUInt32(),
                        yOffset: this.readUInt32()
                    };
                    delayNum = this.readUInt16();
                    delayDen = this.readUInt16() || 100;
                    frame.delay = 1000 * delayNum / delayDen;
                    frame.disposeOp = this.data[this.pos++];
                    frame.blendOp = this.data[this.pos++];
                    frame.data = [];
                    break;
                case 'IDAT':
                case 'fdAT':
                    if (section === 'fdAT') {
                        this.pos += 4;
                        chunkSize -= 4;
                    }
                    data = (frame != null ? frame.data : void 0) || this.imgData;
                    for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
                        data.push(this.data[this.pos++]);
                    }
                    break;
                case 'tRNS':
                    this.transparency = {};
                    switch (this.colorType) {
                        case 3:
                            this.transparency.indexed = this.read(chunkSize);
                            ccshort = 255 - this.transparency.indexed.length;
                            if (ccshort > 0) {
                                for (i = _j = 0; 0 <= ccshort ? _j < ccshort : _j > ccshort; i = 0 <= ccshort ? ++_j : --_j) {
                                    this.transparency.indexed.push(255);
                                }
                            }
                            break;
                        case 0:
                            this.transparency.grayscale = this.read(chunkSize)[0];
                            break;
                        case 2:
                            this.transparency.rgb = this.read(chunkSize);
                    }
                    break;
                case 'tEXt':
                    text = this.read(chunkSize);
                    index = text.indexOf(0);
                    key = String.fromCharCode.apply(String, text.slice(0, index));
                    this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
                    break;
                case 'IEND':
                    if (frame) {
                        this.animation.frames.push(frame);
                    }
                    this.colors = (function() {
                        switch (this.colorType) {
                            case 0:
                            case 3:
                            case 4:
                                return 1;
                            case 2:
                            case 6:
                                return 3;
                        }
                    }).call(this);
                    this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
                    colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
                    this.pixelBitlength = this.bits * colors;
                    this.colorSpace = (function() {
                        switch (this.colors) {
                            case 1:
                                return 'DeviceGray';
                            case 3:
                                return 'DeviceRGB';
                        }
                    }).call(this);
                    if(Uint8Array != Array)
                        this.imgData = new Uint8Array(this.imgData);
                    return;
                default:
                    this.pos += chunkSize;
            }
            this.pos += 4;
            if (this.pos > this.data.length) {
                throw new Error("Incomplete or corrupt PNG file");
            }
        }
    },
    read:function(bytes){
        var i, _i, _results;
        _results = [];
        for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
            _results.push(this.data[this.pos++]);
        }
        return _results;
    },
    readUInt32:function(){
        var b1, b2, b3, b4;
        b1 = this.data[this.pos++] << 24;
        b2 = this.data[this.pos++] << 16;
        b3 = this.data[this.pos++] << 8;
        b4 = this.data[this.pos++];
        return b1 | b2 | b3 | b4;
    },
    readUInt16:function(){
        var b1, b2;
        b1 = this.data[this.pos++] << 8;
        b2 = this.data[this.pos++];
        return b1 | b2;
    },
    decodePixels:function(data){
        var ccbyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
        if (data == null) {
            data = this.imgData;
        }
        if (data.length === 0) {
            return new Uint8Array(0);
        }
        var inflate = new Zlib.Inflate(data,{index:0, verify:false});
        data = inflate.decompress();
        pixelBytes = this.pixelBitlength / 8;
        scanlineLength = pixelBytes * this.width;
        pixels = new Uint8Array(scanlineLength * this.height);
        length = data.length;
        row = 0;
        pos = 0;
        c = 0;
        while (pos < length) {
            switch (data[pos++]) {
                case 0:
                    for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
                        pixels[c++] = data[pos++];
                    }
                    break;
                case 1:
                    for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
                        ccbyte = data[pos++];
                        left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
                        pixels[c++] = (ccbyte + left) % 256;
                    }
                    break;
                case 2:
                    for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
                        ccbyte = data[pos++];
                        col = (i - (i % pixelBytes)) / pixelBytes;
                        upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
                        pixels[c++] = (upper + ccbyte) % 256;
                    }
                    break;
                case 3:
                    for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
                        ccbyte = data[pos++];
                        col = (i - (i % pixelBytes)) / pixelBytes;
                        left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
                        upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
                        pixels[c++] = (ccbyte + Math.floor((left + upper) / 2)) % 256;
                    }
                    break;
                case 4:
                    for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
                        ccbyte = data[pos++];
                        col = (i - (i % pixelBytes)) / pixelBytes;
                        left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
                        if (row === 0) {
                            upper = upperLeft = 0;
                        } else {
                            upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
                            upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)];
                        }
                        p = left + upper - upperLeft;
                        pa = Math.abs(p - left);
                        pb = Math.abs(p - upper);
                        pc = Math.abs(p - upperLeft);
                        if (pa <= pb && pa <= pc) {
                            paeth = left;
                        } else if (pb <= pc) {
                            paeth = upper;
                        } else {
                            paeth = upperLeft;
                        }
                        pixels[c++] = (ccbyte + paeth) % 256;
                    }
                    break;
                default:
                    throw new Error("Invalid filter algorithm: " + data[pos - 1]);
            }
            row++;
        }
        return pixels;
    },
    copyToImageData:function(imageData,pixels){
        var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
        colors = this.colors;
        palette = null;
        alpha = this.hasAlphaChannel;
        if (this.palette.length) {
            palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
            colors = 4;
            alpha = true;
        }
        data = imageData.data || imageData;
        length = data.length;
        input = palette || pixels;
        i = j = 0;
        if (colors === 1) {
            while (i < length) {
                k = palette ? pixels[i / 4] * 4 : j;
                v = input[k++];
                data[i++] = v;
                data[i++] = v;
                data[i++] = v;
                data[i++] = alpha ? input[k++] : 255;
                j = k;
            }
        } else {
            while (i < length) {
                k = palette ? pixels[i / 4] * 4 : j;
                data[i++] = input[k++];
                data[i++] = input[k++];
                data[i++] = input[k++];
                data[i++] = alpha ? input[k++] : 255;
                j = k;
            }
        }
    },
    decodePalette:function(){
        var c, i, palette, pos, ret, transparency, _i, _ref, _ref1;
        palette = this.palette;
        transparency = this.transparency.indexed || [];
        ret = new Uint8Array((transparency.length || 0) + palette.length);
        pos = 0;
        c = 0;
        for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
            ret[pos++] = palette[i];
            ret[pos++] = palette[i + 1];
            ret[pos++] = palette[i + 2];
            ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
        }
        return ret;
    },
    render: function (canvas) {
        var ctx, data;
        canvas.width = this.width;
        canvas.height = this.height;
        ctx = canvas.getContext("2d");
        data = ctx.createImageData(this.width, this.height);
        this.copyToImageData(data, this.decodePixels());
        return ctx.putImageData(data, 0, 0);
    }
});
cc.tiffReader = {
    _littleEndian: false,
    _tiffData: null,
    _fileDirectories: [],
    getUint8: function (offset) {
        return this._tiffData[offset];
    },
    getUint16: function (offset) {
        if (this._littleEndian)
            return (this._tiffData[offset + 1] << 8) | (this._tiffData[offset]);
        else
            return (this._tiffData[offset] << 8) | (this._tiffData[offset + 1]);
    },
    getUint32: function (offset) {
        var a = this._tiffData;
        if (this._littleEndian)
            return (a[offset + 3] << 24) | (a[offset + 2] << 16) | (a[offset + 1] << 8) | (a[offset]);
        else
            return (a[offset] << 24) | (a[offset + 1] << 16) | (a[offset + 2] << 8) | (a[offset + 3]);
    },
    checkLittleEndian: function () {
        var BOM = this.getUint16(0);
        if (BOM === 0x4949) {
            this.littleEndian = true;
        } else if (BOM === 0x4D4D) {
            this.littleEndian = false;
        } else {
            console.log(BOM);
            throw TypeError("Invalid byte order value.");
        }
        return this.littleEndian;
    },
    hasTowel: function () {
        if (this.getUint16(2) !== 42) {
            throw RangeError("You forgot your towel!");
            return false;
        }
        return true;
    },
    getFieldTypeName: function (fieldType) {
        var typeNames = this.fieldTypeNames;
        if (fieldType in typeNames) {
            return typeNames[fieldType];
        }
        return null;
    },
    getFieldTagName: function (fieldTag) {
        var tagNames = this.fieldTagNames;
        if (fieldTag in tagNames) {
            return tagNames[fieldTag];
        } else {
            console.log("Unknown Field Tag:", fieldTag);
            return "Tag" + fieldTag;
        }
    },
    getFieldTypeLength: function (fieldTypeName) {
        if (['BYTE', 'ASCII', 'SBYTE', 'UNDEFINED'].indexOf(fieldTypeName) !== -1) {
            return 1;
        } else if (['SHORT', 'SSHORT'].indexOf(fieldTypeName) !== -1) {
            return 2;
        } else if (['LONG', 'SLONG', 'FLOAT'].indexOf(fieldTypeName) !== -1) {
            return 4;
        } else if (['RATIONAL', 'SRATIONAL', 'DOUBLE'].indexOf(fieldTypeName) !== -1) {
            return 8;
        }
        return null;
    },
    getFieldValues: function (fieldTagName, fieldTypeName, typeCount, valueOffset) {
        var fieldValues = [];
        var fieldTypeLength = this.getFieldTypeLength(fieldTypeName);
        var fieldValueSize = fieldTypeLength * typeCount;
        if (fieldValueSize <= 4) {
            if (this.littleEndian === false)
                fieldValues.push(valueOffset >>> ((4 - fieldTypeLength) * 8));
            else
                fieldValues.push(valueOffset);
        } else {
            for (var i = 0; i < typeCount; i++) {
                var indexOffset = fieldTypeLength * i;
                if (fieldTypeLength >= 8) {
                    if (['RATIONAL', 'SRATIONAL'].indexOf(fieldTypeName) !== -1) {
                        fieldValues.push(this.getUint32(valueOffset + indexOffset));
                        fieldValues.push(this.getUint32(valueOffset + indexOffset + 4));
                    } else {
                        cc.log("Can't handle this field type or size");
                    }
                } else {
                    fieldValues.push(this.getBytes(fieldTypeLength, valueOffset + indexOffset));
                }
            }
        }
        if (fieldTypeName === 'ASCII') {
            fieldValues.forEach(function (e, i, a) {
                a[i] = String.fromCharCode(e);
            });
        }
        return fieldValues;
    },
    getBytes: function (numBytes, offset) {
        if (numBytes <= 0) {
            cc.log("No bytes requested");
        } else if (numBytes <= 1) {
            return this.getUint8(offset);
        } else if (numBytes <= 2) {
            return this.getUint16(offset);
        } else if (numBytes <= 3) {
            return this.getUint32(offset) >>> 8;
        } else if (numBytes <= 4) {
            return this.getUint32(offset);
        } else {
            cc.log("Too many bytes requested");
        }
    },
    getBits: function (numBits, byteOffset, bitOffset) {
        bitOffset = bitOffset || 0;
        var extraBytes = Math.floor(bitOffset / 8);
        var newByteOffset = byteOffset + extraBytes;
        var totalBits = bitOffset + numBits;
        var shiftRight = 32 - numBits;
        var shiftLeft,rawBits;
        if (totalBits <= 0) {
            console.log("No bits requested");
        } else if (totalBits <= 8) {
            shiftLeft = 24 + bitOffset;
            rawBits = this.getUint8(newByteOffset);
        } else if (totalBits <= 16) {
            shiftLeft = 16 + bitOffset;
            rawBits = this.getUint16(newByteOffset);
        } else if (totalBits <= 32) {
            shiftLeft = bitOffset;
            rawBits = this.getUint32(newByteOffset);
        } else {
            console.log( "Too many bits requested" );
        }
        return {
            'bits': ((rawBits << shiftLeft) >>> shiftRight),
            'byteOffset': newByteOffset + Math.floor(totalBits / 8),
            'bitOffset': totalBits % 8
        };
    },
    parseFileDirectory: function (byteOffset) {
        var numDirEntries = this.getUint16(byteOffset);
        var tiffFields = [];
        for (var i = byteOffset + 2, entryCount = 0; entryCount < numDirEntries; i += 12, entryCount++) {
            var fieldTag = this.getUint16(i);
            var fieldType = this.getUint16(i + 2);
            var typeCount = this.getUint32(i + 4);
            var valueOffset = this.getUint32(i + 8);
            var fieldTagName = this.getFieldTagName(fieldTag);
            var fieldTypeName = this.getFieldTypeName(fieldType);
            var fieldValues = this.getFieldValues(fieldTagName, fieldTypeName, typeCount, valueOffset);
            tiffFields[fieldTagName] = { type: fieldTypeName, values: fieldValues };
        }
        this._fileDirectories.push(tiffFields);
        var nextIFDByteOffset = this.getUint32(i);
        if (nextIFDByteOffset !== 0x00000000) {
            this.parseFileDirectory(nextIFDByteOffset);
        }
    },
    clampColorSample: function(colorSample, bitsPerSample) {
        var multiplier = Math.pow(2, 8 - bitsPerSample);
        return Math.floor((colorSample * multiplier) + (multiplier - 1));
    },
    parseTIFF: function (tiffData, canvas) {
        canvas = canvas || document.createElement('canvas');
        this._tiffData = tiffData;
        this.canvas = canvas;
        this.checkLittleEndian();
        if (!this.hasTowel()) {
            return;
        }
        var firstIFDByteOffset = this.getUint32(4);
        this._fileDirectories.length = 0;
        this.parseFileDirectory(firstIFDByteOffset);
        var fileDirectory = this._fileDirectories[0];
        var imageWidth = fileDirectory['ImageWidth'].values[0];
        var imageLength = fileDirectory['ImageLength'].values[0];
        this.canvas.width = imageWidth;
        this.canvas.height = imageLength;
        var strips = [];
        var compression = (fileDirectory['Compression']) ? fileDirectory['Compression'].values[0] : 1;
        var samplesPerPixel = fileDirectory['SamplesPerPixel'].values[0];
        var sampleProperties = [];
        var bitsPerPixel = 0;
        var hasBytesPerPixel = false;
        fileDirectory['BitsPerSample'].values.forEach(function (bitsPerSample, i, bitsPerSampleValues) {
            sampleProperties[i] = {
                bitsPerSample: bitsPerSample,
                hasBytesPerSample: false,
                bytesPerSample: undefined
            };
            if ((bitsPerSample % 8) === 0) {
                sampleProperties[i].hasBytesPerSample = true;
                sampleProperties[i].bytesPerSample = bitsPerSample / 8;
            }
            bitsPerPixel += bitsPerSample;
        }, this);
        if ((bitsPerPixel % 8) === 0) {
            hasBytesPerPixel = true;
            var bytesPerPixel = bitsPerPixel / 8;
        }
        var stripOffsetValues = fileDirectory['StripOffsets'].values;
        var numStripOffsetValues = stripOffsetValues.length;
        if (fileDirectory['StripByteCounts']) {
            var stripByteCountValues = fileDirectory['StripByteCounts'].values;
        } else {
            cc.log("Missing StripByteCounts!");
            if (numStripOffsetValues === 1) {
                var stripByteCountValues = [Math.ceil((imageWidth * imageLength * bitsPerPixel) / 8)];
            } else {
                throw Error("Cannot recover from missing StripByteCounts");
            }
        }
        for (var i = 0; i < numStripOffsetValues; i++) {
            var stripOffset = stripOffsetValues[i];
            strips[i] = [];
            var stripByteCount = stripByteCountValues[i];
            for (var byteOffset = 0, bitOffset = 0, jIncrement = 1, getHeader = true, pixel = [], numBytes = 0, sample = 0, currentSample = 0;
                 byteOffset < stripByteCount; byteOffset += jIncrement) {
                switch (compression) {
                    case 1:
                        for (var m = 0, pixel = []; m < samplesPerPixel; m++) {
                            if (sampleProperties[m].hasBytesPerSample) {
                                var sampleOffset = sampleProperties[m].bytesPerSample * m;
                                pixel.push(this.getBytes(sampleProperties[m].bytesPerSample, stripOffset + byteOffset + sampleOffset));
                            } else {
                                var sampleInfo = this.getBits(sampleProperties[m].bitsPerSample, stripOffset + byteOffset, bitOffset);
                                pixel.push(sampleInfo.bits);
                                byteOffset = sampleInfo.byteOffset - stripOffset;
                                bitOffset = sampleInfo.bitOffset;
                                throw RangeError("Cannot handle sub-byte bits per sample");
                            }
                        }
                        strips[i].push(pixel);
                        if (hasBytesPerPixel) {
                            jIncrement = bytesPerPixel;
                        } else {
                            jIncrement = 0;
                            throw RangeError("Cannot handle sub-byte bits per pixel");
                        }
                        break;
                    case 2:
                        break;
                    case 3:
                        break;
                    case 4:
                        break;
                    case 5:
                        break;
                    case 6:
                        break;
                    case 7:
                        break;
                    case 32773:
                        if (getHeader) {
                            getHeader = false;
                            var blockLength = 1;
                            var iterations = 1;
                            var header = this.getInt8(stripOffset + byteOffset);
                            if ((header >= 0) && (header <= 127)) {
                                blockLength = header + 1;
                            } else if ((header >= -127) && (header <= -1)) {
                                iterations = -header + 1;
                            } else  {
                                getHeader = true;
                            }
                        } else {
                            var currentByte = this.getUint8(stripOffset + byteOffset);
                            for (var m = 0; m < iterations; m++) {
                                if (sampleProperties[sample].hasBytesPerSample) {
                                    currentSample = (currentSample << (8 * numBytes)) | currentByte;
                                    numBytes++;
                                    if (numBytes === sampleProperties[sample].bytesPerSample) {
                                        pixel.push(currentSample);
                                        currentSample = numBytes = 0;
                                        sample++;
                                    }
                                } else {
                                    throw RangeError("Cannot handle sub-byte bits per sample");
                                }
                                if (sample === samplesPerPixel) {
                                    strips[i].push(pixel);
                                    pixel = [];
                                    sample = 0;
                                }
                            }
                            blockLength--;
                            if (blockLength === 0) {
                                getHeader = true;
                            }
                        }
                        jIncrement = 1;
                        break;
                    default:
                        break;
                }
            }
        }
        if (canvas.getContext) {
            var ctx = this.canvas.getContext("2d");
            ctx.fillStyle = "rgba(255, 255, 255, 0)";
            var rowsPerStrip = fileDirectory['RowsPerStrip'] ? fileDirectory['RowsPerStrip'].values[0] : imageLength;
            var numStrips = strips.length;
            var imageLengthModRowsPerStrip = imageLength % rowsPerStrip;
            var rowsInLastStrip = (imageLengthModRowsPerStrip === 0) ? rowsPerStrip : imageLengthModRowsPerStrip;
            var numRowsInStrip = rowsPerStrip;
            var numRowsInPreviousStrip = 0;
            var photometricInterpretation = fileDirectory['PhotometricInterpretation'].values[0];
            var extraSamplesValues = [];
            var numExtraSamples = 0;
            if (fileDirectory['ExtraSamples']) {
                extraSamplesValues = fileDirectory['ExtraSamples'].values;
                numExtraSamples = extraSamplesValues.length;
            }
            if (fileDirectory['ColorMap']) {
                var colorMapValues = fileDirectory['ColorMap'].values;
                var colorMapSampleSize = Math.pow(2, sampleProperties[0].bitsPerSample);
            }
            for (var i = 0; i < numStrips; i++) {
                if ((i + 1) === numStrips) {
                    numRowsInStrip = rowsInLastStrip;
                }
                var numPixels = strips[i].length;
                var yPadding = numRowsInPreviousStrip * i;
                for (var y = 0, j = 0; y < numRowsInStrip, j < numPixels; y++) {
                    for (var x = 0; x < imageWidth; x++, j++) {
                        var pixelSamples = strips[i][j];
                        var red = 0;
                        var green = 0;
                        var blue = 0;
                        var opacity = 1.0;
                        if (numExtraSamples > 0) {
                            for (var k = 0; k < numExtraSamples; k++) {
                                if (extraSamplesValues[k] === 1 || extraSamplesValues[k] === 2) {
                                    opacity = pixelSamples[3 + k] / 256;
                                    break;
                                }
                            }
                        }
                        switch (photometricInterpretation) {
                            case 0:
                                if (sampleProperties[0].hasBytesPerSample) {
                                    var invertValue = Math.pow(0x10, sampleProperties[0].bytesPerSample * 2);
                                }
                                pixelSamples.forEach(function (sample, index, samples) {
                                    samples[index] = invertValue - sample;
                                });
                            case 1:
                                red = green = blue = this.clampColorSample(pixelSamples[0], sampleProperties[0].bitsPerSample);
                                break;
                            case 2:
                                red = this.clampColorSample(pixelSamples[0], sampleProperties[0].bitsPerSample);
                                green = this.clampColorSample(pixelSamples[1], sampleProperties[1].bitsPerSample);
                                blue = this.clampColorSample(pixelSamples[2], sampleProperties[2].bitsPerSample);
                                break;
                            case 3:
                                if (colorMapValues === undefined) {
                                    throw Error("Palette image missing color map");
                                }
                                var colorMapIndex = pixelSamples[0];
                                red = this.clampColorSample(colorMapValues[colorMapIndex], 16);
                                green = this.clampColorSample(colorMapValues[colorMapSampleSize + colorMapIndex], 16);
                                blue = this.clampColorSample(colorMapValues[(2 * colorMapSampleSize) + colorMapIndex], 16);
                                break;
                            default:
                                throw RangeError('Unknown Photometric Interpretation:', photometricInterpretation);
                                break;
                        }
                        ctx.fillStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity + ")";
                        ctx.fillRect(x, yPadding + y, 1, 1);
                    }
                }
                numRowsInPreviousStrip = numRowsInStrip;
            }
        }
        return this.canvas;
    },
    fieldTagNames: {
        0x013B: 'Artist',
        0x0102: 'BitsPerSample',
        0x0109: 'CellLength',
        0x0108: 'CellWidth',
        0x0140: 'ColorMap',
        0x0103: 'Compression',
        0x8298: 'Copyright',
        0x0132: 'DateTime',
        0x0152: 'ExtraSamples',
        0x010A: 'FillOrder',
        0x0121: 'FreeByteCounts',
        0x0120: 'FreeOffsets',
        0x0123: 'GrayResponseCurve',
        0x0122: 'GrayResponseUnit',
        0x013C: 'HostComputer',
        0x010E: 'ImageDescription',
        0x0101: 'ImageLength',
        0x0100: 'ImageWidth',
        0x010F: 'Make',
        0x0119: 'MaxSampleValue',
        0x0118: 'MinSampleValue',
        0x0110: 'Model',
        0x00FE: 'NewSubfileType',
        0x0112: 'Orientation',
        0x0106: 'PhotometricInterpretation',
        0x011C: 'PlanarConfiguration',
        0x0128: 'ResolutionUnit',
        0x0116: 'RowsPerStrip',
        0x0115: 'SamplesPerPixel',
        0x0131: 'Software',
        0x0117: 'StripByteCounts',
        0x0111: 'StripOffsets',
        0x00FF: 'SubfileType',
        0x0107: 'Threshholding',
        0x011A: 'XResolution',
        0x011B: 'YResolution',
        0x0146: 'BadFaxLines',
        0x0147: 'CleanFaxData',
        0x0157: 'ClipPath',
        0x0148: 'ConsecutiveBadFaxLines',
        0x01B1: 'Decode',
        0x01B2: 'DefaultImageColor',
        0x010D: 'DocumentName',
        0x0150: 'DotRange',
        0x0141: 'HalftoneHints',
        0x015A: 'Indexed',
        0x015B: 'JPEGTables',
        0x011D: 'PageName',
        0x0129: 'PageNumber',
        0x013D: 'Predictor',
        0x013F: 'PrimaryChromaticities',
        0x0214: 'ReferenceBlackWhite',
        0x0153: 'SampleFormat',
        0x022F: 'StripRowCounts',
        0x014A: 'SubIFDs',
        0x0124: 'T4Options',
        0x0125: 'T6Options',
        0x0145: 'TileByteCounts',
        0x0143: 'TileLength',
        0x0144: 'TileOffsets',
        0x0142: 'TileWidth',
        0x012D: 'TransferFunction',
        0x013E: 'WhitePoint',
        0x0158: 'XClipPathUnits',
        0x011E: 'XPosition',
        0x0211: 'YCbCrCoefficients',
        0x0213: 'YCbCrPositioning',
        0x0212: 'YCbCrSubSampling',
        0x0159: 'YClipPathUnits',
        0x011F: 'YPosition',
        0x9202: 'ApertureValue',
        0xA001: 'ColorSpace',
        0x9004: 'DateTimeDigitized',
        0x9003: 'DateTimeOriginal',
        0x8769: 'Exif IFD',
        0x9000: 'ExifVersion',
        0x829A: 'ExposureTime',
        0xA300: 'FileSource',
        0x9209: 'Flash',
        0xA000: 'FlashpixVersion',
        0x829D: 'FNumber',
        0xA420: 'ImageUniqueID',
        0x9208: 'LightSource',
        0x927C: 'MakerNote',
        0x9201: 'ShutterSpeedValue',
        0x9286: 'UserComment',
        0x83BB: 'IPTC',
        0x8773: 'ICC Profile',
        0x02BC: 'XMP',
        0xA480: 'GDAL_METADATA',
        0xA481: 'GDAL_NODATA',
        0x8649: 'Photoshop'
    },
    fieldTypeNames: {
        0x0001: 'BYTE',
        0x0002: 'ASCII',
        0x0003: 'SHORT',
        0x0004: 'LONG',
        0x0005: 'RATIONAL',
        0x0006: 'SBYTE',
        0x0007: 'UNDEFINED',
        0x0008: 'SSHORT',
        0x0009: 'SLONG',
        0x000A: 'SRATIONAL',
        0x000B: 'FLOAT',
        0x000C: 'DOUBLE'
    }
};
cc.Particle = function (pos, startPos, color, deltaColor, size, deltaSize, rotation, deltaRotation, timeToLive, atlasIndex, modeA, modeB) {
    this.pos = pos ? pos : cc.p(0,0);
    this.startPos = startPos ? startPos : cc.p(0,0);
    this.color = color ? color : {r:0, g: 0, b:0, a:255};
    this.deltaColor = deltaColor ? deltaColor : {r:0, g: 0, b:0, a:255} ;
    this.size = size || 0;
    this.deltaSize = deltaSize || 0;
    this.rotation = rotation || 0;
    this.deltaRotation = deltaRotation || 0;
    this.timeToLive = timeToLive || 0;
    this.atlasIndex = atlasIndex || 0;
    this.modeA = modeA ? modeA : new cc.Particle.ModeA();
    this.modeB = modeB ? modeB : new cc.Particle.ModeB();
    this.isChangeColor = false;
    this.drawPos = cc.p(0, 0);
};
cc.Particle.ModeA = function (dir, radialAccel, tangentialAccel) {
    this.dir = dir ? dir : cc.p(0,0);
    this.radialAccel = radialAccel || 0;
    this.tangentialAccel = tangentialAccel || 0;
};
cc.Particle.ModeB = function (angle, degreesPerSecond, radius, deltaRadius) {
    this.angle = angle || 0;
    this.degreesPerSecond = degreesPerSecond || 0;
    this.radius = radius || 0;
    this.deltaRadius = deltaRadius || 0;
};
cc.Particle.TemporaryPoints = [
    cc.p(),
    cc.p(),
    cc.p(),
    cc.p()
];
cc.ParticleSystem = cc.Node.extend({
    _className:"ParticleSystem",
    _plistFile: "",
    _elapsed: 0,
    _dontTint: false,
    modeA: null,
    modeB: null,
    _pointZeroForParticle: cc.p(0, 0),
    _particles: null,
    _emitCounter: 0,
    _particleIdx: 0,
    _batchNode: null,
    atlasIndex: 0,
    _transformSystemDirty: false,
    _allocatedParticles: 0,
    _isActive: false,
    particleCount: 0,
    duration: 0,
    _sourcePosition: null,
    _posVar: null,
    life: 0,
    lifeVar: 0,
    angle: 0,
    angleVar: 0,
    startSize: 0,
    startSizeVar: 0,
    endSize: 0,
    endSizeVar: 0,
    _startColor: null,
    _startColorVar: null,
    _endColor: null,
    _endColorVar: null,
    startSpin: 0,
    startSpinVar: 0,
    endSpin: 0,
    endSpinVar: 0,
    emissionRate: 0,
    _totalParticles: 0,
    _texture: null,
    _blendFunc: null,
    _opacityModifyRGB: false,
    positionType: null,
    autoRemoveOnFinish: false,
    emitterMode: 0,
    _textureLoaded: null,
    ctor:function (plistFile) {
        cc.Node.prototype.ctor.call(this);
        this.emitterMode = cc.ParticleSystem.MODE_GRAVITY;
        this.modeA = new cc.ParticleSystem.ModeA();
        this.modeB = new cc.ParticleSystem.ModeB();
        this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST};
        this._particles = [];
        this._sourcePosition = cc.p(0, 0);
        this._posVar = cc.p(0, 0);
        this._startColor = cc.color(255, 255, 255, 255);
        this._startColorVar = cc.color(255, 255, 255, 255);
        this._endColor = cc.color(255, 255, 255, 255);
        this._endColorVar = cc.color(255, 255, 255, 255);
        this._plistFile = "";
        this._elapsed = 0;
        this._dontTint = false;
        this._pointZeroForParticle = cc.p(0, 0);
        this._emitCounter = 0;
        this._particleIdx = 0;
        this._batchNode = null;
        this.atlasIndex = 0;
        this._transformSystemDirty = false;
        this._allocatedParticles = 0;
        this._isActive = false;
        this.particleCount = 0;
        this.duration = 0;
        this.life = 0;
        this.lifeVar = 0;
        this.angle = 0;
        this.angleVar = 0;
        this.startSize = 0;
        this.startSizeVar = 0;
        this.endSize = 0;
        this.endSizeVar = 0;
        this.startSpin = 0;
        this.startSpinVar = 0;
        this.endSpin = 0;
        this.endSpinVar = 0;
        this.emissionRate = 0;
        this._totalParticles = 0;
        this._texture = null;
        this._opacityModifyRGB = false;
        this.positionType = cc.ParticleSystem.TYPE_FREE;
        this.autoRemoveOnFinish = false;
        this._textureLoaded = true;
        if (!plistFile || cc.isNumber(plistFile)) {
            var ton = plistFile || 100;
            this.setDrawMode(cc.ParticleSystem.TEXTURE_MODE);
            this.initWithTotalParticles(ton);
        } else if (cc.isString(plistFile)) {
            this.initWithFile(plistFile);
        } else if (cc.isObject(plistFile)) {
            this.initWithDictionary(plistFile, "");
        }
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.ParticleSystem.CanvasRenderCmd(this);
        else
            return new cc.ParticleSystem.WebGLRenderCmd(this);
    },
    ignoreColor: function(ignore){
       this._dontTint = ignore;
    },
    initTexCoordsWithRect:function (pointRect) {
        this._renderCmd.initTexCoordsWithRect(pointRect);
    },
    getBatchNode:function () {
        return this._batchNode;
    },
    setBatchNode:function (batchNode) {
        this._renderCmd.setBatchNode(batchNode);
    },
    getAtlasIndex:function () {
        return this.atlasIndex;
    },
    setAtlasIndex:function (atlasIndex) {
        this.atlasIndex = atlasIndex;
    },
    getDrawMode:function () {
        return this._renderCmd.getDrawMode();
    },
    setDrawMode:function (drawMode) {
        this._renderCmd.setDrawMode(drawMode);
    },
    getShapeType:function () {
        return this._renderCmd.getShapeType();
    },
    setShapeType:function (shapeType) {
        this._renderCmd.setShapeType(shapeType);
    },
    isActive:function () {
        return this._isActive;
    },
    getParticleCount:function () {
        return this.particleCount;
    },
    setParticleCount:function (particleCount) {
        this.particleCount = particleCount;
    },
    getDuration:function () {
        return this.duration;
    },
    setDuration:function (duration) {
        this.duration = duration;
    },
    getSourcePosition:function () {
        return {x: this._sourcePosition.x, y: this._sourcePosition.y};
    },
    setSourcePosition:function (sourcePosition) {
        this._sourcePosition = sourcePosition;
    },
    getPosVar:function () {
        return {x: this._posVar.x, y: this._posVar.y};
    },
    setPosVar:function (posVar) {
        this._posVar = posVar;
    },
    getLife:function () {
        return this.life;
    },
    setLife:function (life) {
        this.life = life;
    },
    getLifeVar:function () {
        return this.lifeVar;
    },
    setLifeVar:function (lifeVar) {
        this.lifeVar = lifeVar;
    },
    getAngle:function () {
        return this.angle;
    },
    setAngle:function (angle) {
        this.angle = angle;
    },
    getAngleVar:function () {
        return this.angleVar;
    },
    setAngleVar:function (angleVar) {
        this.angleVar = angleVar;
    },
    getGravity:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getGravity() : Particle Mode should be Gravity");
        var locGravity = this.modeA.gravity;
        return cc.p(locGravity.x, locGravity.y);
    },
    setGravity:function (gravity) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setGravity() : Particle Mode should be Gravity");
        this.modeA.gravity = gravity;
    },
    getSpeed:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getSpeed() : Particle Mode should be Gravity");
        return this.modeA.speed;
    },
    setSpeed:function (speed) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setSpeed() : Particle Mode should be Gravity");
        this.modeA.speed = speed;
    },
    getSpeedVar:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getSpeedVar() : Particle Mode should be Gravity");
        return this.modeA.speedVar;
    },
    setSpeedVar:function (speedVar) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setSpeedVar() : Particle Mode should be Gravity");
        this.modeA.speedVar = speedVar;
    },
    getTangentialAccel:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getTangentialAccel() : Particle Mode should be Gravity");
        return this.modeA.tangentialAccel;
    },
    setTangentialAccel:function (tangentialAccel) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setTangentialAccel() : Particle Mode should be Gravity");
        this.modeA.tangentialAccel = tangentialAccel;
    },
    getTangentialAccelVar:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getTangentialAccelVar() : Particle Mode should be Gravity");
        return this.modeA.tangentialAccelVar;
    },
    setTangentialAccelVar:function (tangentialAccelVar) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setTangentialAccelVar() : Particle Mode should be Gravity");
        this.modeA.tangentialAccelVar = tangentialAccelVar;
    },
    getRadialAccel:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getRadialAccel() : Particle Mode should be Gravity");
        return this.modeA.radialAccel;
    },
    setRadialAccel:function (radialAccel) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setRadialAccel() : Particle Mode should be Gravity");
        this.modeA.radialAccel = radialAccel;
    },
    getRadialAccelVar:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getRadialAccelVar() : Particle Mode should be Gravity");
        return this.modeA.radialAccelVar;
    },
    setRadialAccelVar:function (radialAccelVar) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setRadialAccelVar() : Particle Mode should be Gravity");
        this.modeA.radialAccelVar = radialAccelVar;
    },
    getRotationIsDir: function(){
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.getRotationIsDir() : Particle Mode should be Gravity");
        return this.modeA.rotationIsDir;
    },
    setRotationIsDir: function(t){
        if(this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
            cc.log("cc.ParticleBatchNode.setRotationIsDir() : Particle Mode should be Gravity");
        this.modeA.rotationIsDir = t;
    },
    getStartRadius:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.getStartRadius() : Particle Mode should be Radius");
        return this.modeB.startRadius;
    },
    setStartRadius:function (startRadius) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.setStartRadius() : Particle Mode should be Radius");
        this.modeB.startRadius = startRadius;
    },
    getStartRadiusVar:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.getStartRadiusVar() : Particle Mode should be Radius");
        return this.modeB.startRadiusVar;
    },
    setStartRadiusVar:function (startRadiusVar) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.setStartRadiusVar() : Particle Mode should be Radius");
        this.modeB.startRadiusVar = startRadiusVar;
    },
    getEndRadius:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.getEndRadius() : Particle Mode should be Radius");
        return this.modeB.endRadius;
    },
    setEndRadius:function (endRadius) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.setEndRadius() : Particle Mode should be Radius");
        this.modeB.endRadius = endRadius;
    },
    getEndRadiusVar:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.getEndRadiusVar() : Particle Mode should be Radius");
        return this.modeB.endRadiusVar;
    },
    setEndRadiusVar:function (endRadiusVar) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.setEndRadiusVar() : Particle Mode should be Radius");
        this.modeB.endRadiusVar = endRadiusVar;
    },
    getRotatePerSecond:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.getRotatePerSecond() : Particle Mode should be Radius");
        return this.modeB.rotatePerSecond;
    },
    setRotatePerSecond:function (degrees) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.setRotatePerSecond() : Particle Mode should be Radius");
        this.modeB.rotatePerSecond = degrees;
    },
    getRotatePerSecondVar:function () {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.getRotatePerSecondVar() : Particle Mode should be Radius");
        return this.modeB.rotatePerSecondVar;
    },
    setRotatePerSecondVar:function (degrees) {
        if(this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
            cc.log("cc.ParticleBatchNode.setRotatePerSecondVar() : Particle Mode should be Radius");
        this.modeB.rotatePerSecondVar = degrees;
    },
    setScale:function (scale, scaleY) {
        this._transformSystemDirty = true;
        cc.Node.prototype.setScale.call(this, scale, scaleY);
    },
    setRotation:function (newRotation) {
        this._transformSystemDirty = true;
        cc.Node.prototype.setRotation.call(this, newRotation);
    },
    setScaleX:function (newScaleX) {
        this._transformSystemDirty = true;
        cc.Node.prototype.setScaleX.call(this, newScaleX);
    },
    setScaleY:function (newScaleY) {
        this._transformSystemDirty = true;
        cc.Node.prototype.setScaleY.call(this, newScaleY);
    },
    getStartSize:function () {
        return this.startSize;
    },
    setStartSize:function (startSize) {
        this.startSize = startSize;
    },
    getStartSizeVar:function () {
        return this.startSizeVar;
    },
    setStartSizeVar:function (startSizeVar) {
        this.startSizeVar = startSizeVar;
    },
    getEndSize:function () {
        return this.endSize;
    },
    setEndSize:function (endSize) {
        this.endSize = endSize;
    },
    getEndSizeVar:function () {
        return this.endSizeVar;
    },
    setEndSizeVar:function (endSizeVar) {
        this.endSizeVar = endSizeVar;
    },
    getStartColor:function () {
        return cc.color(this._startColor.r, this._startColor.g, this._startColor.b, this._startColor.a);
    },
    setStartColor:function (startColor) {
        this._startColor = cc.color(startColor);
    },
    getStartColorVar:function () {
        return cc.color(this._startColorVar.r, this._startColorVar.g, this._startColorVar.b, this._startColorVar.a);
    },
    setStartColorVar:function (startColorVar) {
        this._startColorVar = cc.color(startColorVar);
    },
    getEndColor:function () {
        return cc.color(this._endColor.r, this._endColor.g, this._endColor.b, this._endColor.a);
    },
    setEndColor:function (endColor) {
        this._endColor = cc.color(endColor);
    },
    getEndColorVar:function () {
        return cc.color(this._endColorVar.r, this._endColorVar.g, this._endColorVar.b, this._endColorVar.a);
    },
    setEndColorVar:function (endColorVar) {
        this._endColorVar = cc.color(endColorVar);
    },
    getStartSpin:function () {
        return this.startSpin;
    },
    setStartSpin:function (startSpin) {
        this.startSpin = startSpin;
    },
    getStartSpinVar:function () {
        return this.startSpinVar;
    },
    setStartSpinVar:function (startSpinVar) {
        this.startSpinVar = startSpinVar;
    },
    getEndSpin:function () {
        return this.endSpin;
    },
    setEndSpin:function (endSpin) {
        this.endSpin = endSpin;
    },
    getEndSpinVar:function () {
        return this.endSpinVar;
    },
    setEndSpinVar:function (endSpinVar) {
        this.endSpinVar = endSpinVar;
    },
    getEmissionRate:function () {
        return this.emissionRate;
    },
    setEmissionRate:function (emissionRate) {
        this.emissionRate = emissionRate;
    },
    getTotalParticles:function () {
        return this._totalParticles;
    },
    setTotalParticles:function (tp) {
        this._renderCmd.setTotalParticles(tp);
    },
    getTexture:function () {
        return this._texture;
    },
    setTexture:function (texture) {
        if(!texture)
            return;
        if(texture.isLoaded()){
            this.setTextureWithRect(texture, cc.rect(0, 0, texture.width, texture.height));
        } else {
            this._textureLoaded = false;
            texture.addEventListener("load", function(sender){
                this._textureLoaded = true;
                this.setTextureWithRect(sender, cc.rect(0, 0, sender.width, sender.height));
            }, this);
        }
    },
    getBlendFunc:function () {
        return this._blendFunc;
    },
    setBlendFunc:function (src, dst) {
        if (dst === undefined) {
            if (this._blendFunc !== src) {
                this._blendFunc = src;
                this._updateBlendFunc();
            }
        } else {
            if (this._blendFunc.src !== src || this._blendFunc.dst !== dst) {
                this._blendFunc = {src:src, dst:dst};
                this._updateBlendFunc();
            }
        }
    },
    isOpacityModifyRGB:function () {
        return this._opacityModifyRGB;
    },
    setOpacityModifyRGB:function (newValue) {
        this._opacityModifyRGB = newValue;
    },
    isBlendAdditive:function () {
        return (( this._blendFunc.src === cc.SRC_ALPHA && this._blendFunc.dst === cc.ONE) || (this._blendFunc.src === cc.ONE && this._blendFunc.dst === cc.ONE));
    },
    setBlendAdditive:function (isBlendAdditive) {
        var locBlendFunc = this._blendFunc;
        if (isBlendAdditive) {
            locBlendFunc.src = cc.SRC_ALPHA;
            locBlendFunc.dst = cc.ONE;
        } else {
            this._renderCmd._setBlendAdditive();
        }
    },
    getPositionType:function () {
        return this.positionType;
    },
    setPositionType:function (positionType) {
        this.positionType = positionType;
    },
    isAutoRemoveOnFinish:function () {
        return this.autoRemoveOnFinish;
    },
    setAutoRemoveOnFinish:function (isAutoRemoveOnFinish) {
        this.autoRemoveOnFinish = isAutoRemoveOnFinish;
    },
    getEmitterMode:function () {
        return this.emitterMode;
    },
    setEmitterMode:function (emitterMode) {
        this.emitterMode = emitterMode;
    },
    init:function () {
        return this.initWithTotalParticles(150);
    },
    initWithFile:function (plistFile) {
        this._plistFile = plistFile;
        var dict = cc.loader.getRes(plistFile);
        if(!dict){
            cc.log("cc.ParticleSystem.initWithFile(): Particles: file not found");
            return false;
        }
        return this.initWithDictionary(dict, "");
    },
    getBoundingBoxToWorld:function () {
        return cc.rect(0, 0, cc._canvas.width, cc._canvas.height);
    },
    initWithDictionary:function (dictionary, dirname) {
        var ret = false;
        var buffer = null;
        var image = null;
        var locValueForKey = this._valueForKey;
        var maxParticles = parseInt(locValueForKey("maxParticles", dictionary));
        if (this.initWithTotalParticles(maxParticles)) {
            this.angle = parseFloat(locValueForKey("angle", dictionary));
            this.angleVar = parseFloat(locValueForKey("angleVariance", dictionary));
            this.duration = parseFloat(locValueForKey("duration", dictionary));
            this._blendFunc.src = parseInt(locValueForKey("blendFuncSource", dictionary));
            this._blendFunc.dst = parseInt(locValueForKey("blendFuncDestination", dictionary));
            var locStartColor = this._startColor;
            locStartColor.r = parseFloat(locValueForKey("startColorRed", dictionary)) * 255;
            locStartColor.g = parseFloat(locValueForKey("startColorGreen", dictionary)) * 255;
            locStartColor.b = parseFloat(locValueForKey("startColorBlue", dictionary)) * 255;
            locStartColor.a = parseFloat(locValueForKey("startColorAlpha", dictionary)) * 255;
            var locStartColorVar = this._startColorVar;
            locStartColorVar.r = parseFloat(locValueForKey("startColorVarianceRed", dictionary)) * 255;
            locStartColorVar.g = parseFloat(locValueForKey("startColorVarianceGreen", dictionary)) * 255;
            locStartColorVar.b = parseFloat(locValueForKey("startColorVarianceBlue", dictionary)) * 255;
            locStartColorVar.a = parseFloat(locValueForKey("startColorVarianceAlpha", dictionary)) * 255;
            var locEndColor = this._endColor;
            locEndColor.r = parseFloat(locValueForKey("finishColorRed", dictionary)) * 255;
            locEndColor.g = parseFloat(locValueForKey("finishColorGreen", dictionary)) * 255;
            locEndColor.b = parseFloat(locValueForKey("finishColorBlue", dictionary)) * 255;
            locEndColor.a = parseFloat(locValueForKey("finishColorAlpha", dictionary)) * 255;
            var locEndColorVar = this._endColorVar;
            locEndColorVar.r = parseFloat(locValueForKey("finishColorVarianceRed", dictionary)) * 255;
            locEndColorVar.g = parseFloat(locValueForKey("finishColorVarianceGreen", dictionary)) * 255;
            locEndColorVar.b = parseFloat(locValueForKey("finishColorVarianceBlue", dictionary)) * 255;
            locEndColorVar.a = parseFloat(locValueForKey("finishColorVarianceAlpha", dictionary)) * 255;
            this.startSize = parseFloat(locValueForKey("startParticleSize", dictionary));
            this.startSizeVar = parseFloat(locValueForKey("startParticleSizeVariance", dictionary));
            this.endSize = parseFloat(locValueForKey("finishParticleSize", dictionary));
            this.endSizeVar = parseFloat(locValueForKey("finishParticleSizeVariance", dictionary));
            this.setPosition(parseFloat(locValueForKey("sourcePositionx", dictionary)),
                              parseFloat(locValueForKey("sourcePositiony", dictionary)));
            this._posVar.x = parseFloat(locValueForKey("sourcePositionVariancex", dictionary));
            this._posVar.y = parseFloat(locValueForKey("sourcePositionVariancey", dictionary));
            this.startSpin = parseFloat(locValueForKey("rotationStart", dictionary));
            this.startSpinVar = parseFloat(locValueForKey("rotationStartVariance", dictionary));
            this.endSpin = parseFloat(locValueForKey("rotationEnd", dictionary));
            this.endSpinVar = parseFloat(locValueForKey("rotationEndVariance", dictionary));
            this.emitterMode = parseInt(locValueForKey("emitterType", dictionary));
            if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
                var locModeA = this.modeA;
                locModeA.gravity.x = parseFloat(locValueForKey("gravityx", dictionary));
                locModeA.gravity.y = parseFloat(locValueForKey("gravityy", dictionary));
                locModeA.speed = parseFloat(locValueForKey("speed", dictionary));
                locModeA.speedVar = parseFloat(locValueForKey("speedVariance", dictionary));
                var pszTmp = locValueForKey("radialAcceleration", dictionary);
                locModeA.radialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
                pszTmp = locValueForKey("radialAccelVariance", dictionary);
                locModeA.radialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
                pszTmp = locValueForKey("tangentialAcceleration", dictionary);
                locModeA.tangentialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
                pszTmp = locValueForKey("tangentialAccelVariance", dictionary);
                locModeA.tangentialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
                var locRotationIsDir = locValueForKey("rotationIsDir", dictionary).toLowerCase();
                locModeA.rotationIsDir = (locRotationIsDir != null && (locRotationIsDir === "true" || locRotationIsDir === "1"));
            } else if (this.emitterMode === cc.ParticleSystem.MODE_RADIUS) {
                var locModeB = this.modeB;
                locModeB.startRadius = parseFloat(locValueForKey("maxRadius", dictionary));
                locModeB.startRadiusVar = parseFloat(locValueForKey("maxRadiusVariance", dictionary));
                locModeB.endRadius = parseFloat(locValueForKey("minRadius", dictionary));
                locModeB.endRadiusVar = 0;
                locModeB.rotatePerSecond = parseFloat(locValueForKey("rotatePerSecond", dictionary));
                locModeB.rotatePerSecondVar = parseFloat(locValueForKey("rotatePerSecondVariance", dictionary));
            } else {
                cc.log("cc.ParticleSystem.initWithDictionary(): Invalid emitterType in config file");
                return false;
            }
            this.life = parseFloat(locValueForKey("particleLifespan", dictionary));
            this.lifeVar = parseFloat(locValueForKey("particleLifespanVariance", dictionary));
            this.emissionRate = this._totalParticles / this.life;
            if (!this._batchNode) {
                this._opacityModifyRGB = false;
                var textureName = locValueForKey("textureFileName", dictionary);
                var imgPath = cc.path.changeBasename(this._plistFile, textureName);
                var tex = cc.textureCache.getTextureForKey(imgPath);
                if (tex) {
                    this.setTexture(tex);
                } else {
                    var textureData = locValueForKey("textureImageData", dictionary);
                    if (!textureData || textureData.length === 0) {
                        tex = cc.textureCache.addImage(imgPath);
                        if (!tex)
                            return false;
                        this.setTexture(tex);
                    } else {
                        buffer = cc.unzipBase64AsArray(textureData, 1);
                        if (!buffer) {
                            cc.log("cc.ParticleSystem: error decoding or ungzipping textureImageData");
                            return false;
                        }
                        var imageFormat = cc.getImageFormatByData(buffer);
                        if(imageFormat !== cc.FMT_TIFF && imageFormat !== cc.FMT_PNG){
                            cc.log("cc.ParticleSystem: unknown image format with Data");
                            return false;
                        }
                        var canvasObj = document.createElement("canvas");
                        if(imageFormat === cc.FMT_PNG){
                            var myPngObj = new cc.PNGReader(buffer);
                            myPngObj.render(canvasObj);
                        } else {
                            var myTIFFObj = cc.tiffReader;
                            myTIFFObj.parseTIFF(buffer,canvasObj);
                        }
                        cc.textureCache.cacheImage(imgPath, canvasObj);
                        var addTexture = cc.textureCache.getTextureForKey(imgPath);
                        if(!addTexture)
                            cc.log("cc.ParticleSystem.initWithDictionary() : error loading the texture");
                        this.setTexture(addTexture);
                    }
                }
            }
            ret = true;
        }
        return ret;
    },
    initWithTotalParticles:function (numberOfParticles) {
        this._totalParticles = numberOfParticles;
        var i, locParticles = this._particles;
        locParticles.length = 0;
        for(i = 0; i< numberOfParticles; i++){
            locParticles[i] = new cc.Particle();
        }
        if (!locParticles) {
            cc.log("Particle system: not enough memory");
            return false;
        }
        this._allocatedParticles = numberOfParticles;
        if (this._batchNode)
            for (i = 0; i < this._totalParticles; i++)
                locParticles[i].atlasIndex = i;
        this._isActive = true;
        this._blendFunc.src = cc.BLEND_SRC;
        this._blendFunc.dst = cc.BLEND_DST;
        this.positionType = cc.ParticleSystem.TYPE_FREE;
        this.emitterMode = cc.ParticleSystem.MODE_GRAVITY;
        this.autoRemoveOnFinish = false;
        this._transformSystemDirty = false;
        this.scheduleUpdateWithPriority(1);
        this._renderCmd._initWithTotalParticles(numberOfParticles);
        return true;
    },
    destroyParticleSystem:function () {
        this.unscheduleUpdate();
    },
    addParticle: function () {
        if (this.isFull())
            return false;
        var particle = this._renderCmd.addParticle();
        this.initParticle(particle);
        ++this.particleCount;
        return true;
    },
    initParticle:function (particle) {
        var locRandomMinus11 = cc.randomMinus1To1;
        particle.timeToLive = this.life + this.lifeVar * locRandomMinus11();
        particle.timeToLive = Math.max(0, particle.timeToLive);
        particle.pos.x = this._sourcePosition.x + this._posVar.x * locRandomMinus11();
        particle.pos.y = this._sourcePosition.y + this._posVar.y * locRandomMinus11();
        var start, end;
        var locStartColor = this._startColor, locStartColorVar = this._startColorVar;
        var locEndColor = this._endColor, locEndColorVar = this._endColorVar;
        start = {
            r: cc.clampf(locStartColor.r + locStartColorVar.r * locRandomMinus11(), 0, 255),
            g: cc.clampf(locStartColor.g + locStartColorVar.g * locRandomMinus11(), 0, 255),
            b: cc.clampf(locStartColor.b + locStartColorVar.b * locRandomMinus11(), 0, 255),
            a: cc.clampf(locStartColor.a + locStartColorVar.a * locRandomMinus11(), 0, 255)
        };
        end = {
            r: cc.clampf(locEndColor.r + locEndColorVar.r * locRandomMinus11(), 0, 255),
            g: cc.clampf(locEndColor.g + locEndColorVar.g * locRandomMinus11(), 0, 255),
            b: cc.clampf(locEndColor.b + locEndColorVar.b * locRandomMinus11(), 0, 255),
            a: cc.clampf(locEndColor.a + locEndColorVar.a * locRandomMinus11(), 0, 255)
        };
        particle.color = start;
        var locParticleDeltaColor = particle.deltaColor, locParticleTimeToLive = particle.timeToLive;
        locParticleDeltaColor.r = (end.r - start.r) / locParticleTimeToLive;
        locParticleDeltaColor.g = (end.g - start.g) / locParticleTimeToLive;
        locParticleDeltaColor.b = (end.b - start.b) / locParticleTimeToLive;
        locParticleDeltaColor.a = (end.a - start.a) / locParticleTimeToLive;
        var startS = this.startSize + this.startSizeVar * locRandomMinus11();
        startS = Math.max(0, startS);
        particle.size = startS;
        if (this.endSize === cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE) {
            particle.deltaSize = 0;
        } else {
            var endS = this.endSize + this.endSizeVar * locRandomMinus11();
            endS = Math.max(0, endS);
            particle.deltaSize = (endS - startS) / locParticleTimeToLive;
        }
        var startA = this.startSpin + this.startSpinVar * locRandomMinus11();
        var endA = this.endSpin + this.endSpinVar * locRandomMinus11();
        particle.rotation = startA;
        particle.deltaRotation = (endA - startA) / locParticleTimeToLive;
        if (this.positionType === cc.ParticleSystem.TYPE_FREE)
            particle.startPos = this.convertToWorldSpace(this._pointZeroForParticle);
        else if (this.positionType === cc.ParticleSystem.TYPE_RELATIVE){
            particle.startPos.x = this._position.x;
            particle.startPos.y = this._position.y;
        }
        var a = cc.degreesToRadians(this.angle + this.angleVar * locRandomMinus11());
        if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
            var locModeA = this.modeA, locParticleModeA = particle.modeA;
            var s = locModeA.speed + locModeA.speedVar * locRandomMinus11();
            locParticleModeA.dir.x = Math.cos(a);
            locParticleModeA.dir.y = Math.sin(a);
            cc.pMultIn(locParticleModeA.dir, s);
            locParticleModeA.radialAccel = locModeA.radialAccel + locModeA.radialAccelVar * locRandomMinus11();
            locParticleModeA.tangentialAccel = locModeA.tangentialAccel + locModeA.tangentialAccelVar * locRandomMinus11();
            if(locModeA.rotationIsDir)
                particle.rotation = -cc.radiansToDegrees(cc.pToAngle(locParticleModeA.dir));
        } else {
            var locModeB = this.modeB, locParitlceModeB = particle.modeB;
            var startRadius = locModeB.startRadius + locModeB.startRadiusVar * locRandomMinus11();
            var endRadius = locModeB.endRadius + locModeB.endRadiusVar * locRandomMinus11();
            locParitlceModeB.radius = startRadius;
            locParitlceModeB.deltaRadius = (locModeB.endRadius === cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS) ? 0 : (endRadius - startRadius) / locParticleTimeToLive;
            locParitlceModeB.angle = a;
            locParitlceModeB.degreesPerSecond = cc.degreesToRadians(locModeB.rotatePerSecond + locModeB.rotatePerSecondVar * locRandomMinus11());
        }
    },
    stopSystem:function () {
        this._isActive = false;
        this._elapsed = this.duration;
        this._emitCounter = 0;
    },
    resetSystem:function () {
        this._isActive = true;
        this._elapsed = 0;
        var locParticles = this._particles;
        for (this._particleIdx = 0; this._particleIdx < this.particleCount; ++this._particleIdx)
            locParticles[this._particleIdx].timeToLive = 0 ;
    },
    isFull:function () {
        return (this.particleCount >= this._totalParticles);
    },
    updateQuadWithParticle:function (particle, newPosition) {
        this._renderCmd.updateQuadWithParticle(particle, newPosition);
    },
    postStep:function () {
        this._renderCmd.postStep();
    },
    update:function (dt) {
        if (this._isActive && this.emissionRate) {
            var rate = 1.0 / this.emissionRate;
            if (this.particleCount < this._totalParticles)
                this._emitCounter += dt;
            while ((this.particleCount < this._totalParticles) && (this._emitCounter > rate)) {
                this.addParticle();
                this._emitCounter -= rate;
            }
            this._elapsed += dt;
            if (this.duration !== -1 && this.duration < this._elapsed)
                this.stopSystem();
        }
        this._particleIdx = 0;
        var currentPosition = cc.Particle.TemporaryPoints[0];
        if (this.positionType === cc.ParticleSystem.TYPE_FREE) {
            cc.pIn(currentPosition, this.convertToWorldSpace(this._pointZeroForParticle));
        } else if (this.positionType === cc.ParticleSystem.TYPE_RELATIVE) {
            currentPosition.x = this._position.x;
            currentPosition.y = this._position.y;
        }
        if (this._visible) {
            var tpa = cc.Particle.TemporaryPoints[1],
                tpb = cc.Particle.TemporaryPoints[2],
                tpc = cc.Particle.TemporaryPoints[3];
            var locParticles = this._particles;
            while (this._particleIdx < this.particleCount) {
                cc.pZeroIn(tpa);
                cc.pZeroIn(tpb);
                cc.pZeroIn(tpc);
                var selParticle = locParticles[this._particleIdx];
                selParticle.timeToLive -= dt;
                if (selParticle.timeToLive > 0) {
                    if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
                        var tmp = tpc, radial = tpa, tangential = tpb;
                        if (selParticle.pos.x || selParticle.pos.y) {
                            cc.pIn(radial, selParticle.pos);
                            cc.pNormalizeIn(radial);
                        } else {
                            cc.pZeroIn(radial);
                        }
                        cc.pIn(tangential, radial);
                        cc.pMultIn(radial, selParticle.modeA.radialAccel);
                        var newy = tangential.x;
                        tangential.x = -tangential.y;
                        tangential.y = newy;
                        cc.pMultIn(tangential, selParticle.modeA.tangentialAccel);
                        cc.pIn(tmp, radial);
                        cc.pAddIn(tmp, tangential);
                        cc.pAddIn(tmp, this.modeA.gravity);
                        cc.pMultIn(tmp, dt);
                        cc.pAddIn(selParticle.modeA.dir, tmp);
                        cc.pIn(tmp, selParticle.modeA.dir);
                        cc.pMultIn(tmp, dt);
                        cc.pAddIn(selParticle.pos, tmp);
                    } else {
                        var selModeB = selParticle.modeB;
                        selModeB.angle += selModeB.degreesPerSecond * dt;
                        selModeB.radius += selModeB.deltaRadius * dt;
                        selParticle.pos.x = -Math.cos(selModeB.angle) * selModeB.radius;
                        selParticle.pos.y = -Math.sin(selModeB.angle) * selModeB.radius;
                    }
                    this._renderCmd._updateDeltaColor(selParticle, dt);
                    selParticle.size += (selParticle.deltaSize * dt);
                    selParticle.size = Math.max(0, selParticle.size);
                    selParticle.rotation += (selParticle.deltaRotation * dt);
                    var newPos = tpa;
                    if (this.positionType === cc.ParticleSystem.TYPE_FREE || this.positionType === cc.ParticleSystem.TYPE_RELATIVE) {
                        var diff = tpb;
                        cc.pIn(diff, currentPosition);
                        cc.pSubIn(diff, selParticle.startPos);
                        cc.pIn(newPos, selParticle.pos);
                        cc.pSubIn(newPos, diff);
                    } else {
                        cc.pIn(newPos, selParticle.pos);
                    }
                    if (this._batchNode) {
                        newPos.x += this._position.x;
                        newPos.y += this._position.y;
                    }
                    this._renderCmd.updateParticlePosition(selParticle, newPos);
                    ++this._particleIdx;
                } else {
                    var currentIndex = selParticle.atlasIndex;
                    if(this._particleIdx !== this.particleCount -1){
                         var deadParticle = locParticles[this._particleIdx];
                        locParticles[this._particleIdx] = locParticles[this.particleCount -1];
                        locParticles[this.particleCount -1] = deadParticle;
                    }
                    if (this._batchNode) {
                        this._batchNode.disableParticle(this.atlasIndex + currentIndex);
                        locParticles[this.particleCount - 1].atlasIndex = currentIndex;
                    }
                    --this.particleCount;
                    if (this.particleCount === 0 && this.autoRemoveOnFinish) {
                        this.unscheduleUpdate();
                        this._parent.removeChild(this, true);
                        return;
                    }
                }
            }
            this._transformSystemDirty = false;
        }
        if (!this._batchNode)
            this.postStep();
    },
    updateWithNoTime:function () {
        this.update(0);
    },
    _valueForKey:function (key, dict) {
        if (dict) {
            var pString = dict[key];
            return pString != null ? pString : "";
        }
        return "";
    },
    _updateBlendFunc:function () {
        if(this._batchNode){
            cc.log("Can't change blending functions when the particle is being batched");
            return;
        }
        var locTexture = this._texture;
        if (locTexture && locTexture instanceof cc.Texture2D) {
            this._opacityModifyRGB = false;
            var locBlendFunc = this._blendFunc;
            if (locBlendFunc.src === cc.BLEND_SRC && locBlendFunc.dst === cc.BLEND_DST) {
                if (locTexture.hasPremultipliedAlpha()) {
                    this._opacityModifyRGB = true;
                } else {
                    locBlendFunc.src = cc.SRC_ALPHA;
                    locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
                }
            }
        }
    },
    clone:function () {
        var retParticle = new cc.ParticleSystem();
        if (retParticle.initWithTotalParticles(this.getTotalParticles())) {
            retParticle.setAngle(this.getAngle());
            retParticle.setAngleVar(this.getAngleVar());
            retParticle.setDuration(this.getDuration());
            var blend = this.getBlendFunc();
            retParticle.setBlendFunc(blend.src,blend.dst);
            retParticle.setStartColor(this.getStartColor());
            retParticle.setStartColorVar(this.getStartColorVar());
            retParticle.setEndColor(this.getEndColor());
            retParticle.setEndColorVar(this.getEndColorVar());
            retParticle.setStartSize(this.getStartSize());
            retParticle.setStartSizeVar(this.getStartSizeVar());
            retParticle.setEndSize(this.getEndSize());
            retParticle.setEndSizeVar(this.getEndSizeVar());
            retParticle.setPosition(cc.p(this.x, this.y));
            retParticle.setPosVar(cc.p(this.getPosVar().x,this.getPosVar().y));
            retParticle.setPositionType(this.getPositionType());
            retParticle.setStartSpin(this.getStartSpin()||0);
            retParticle.setStartSpinVar(this.getStartSpinVar()||0);
            retParticle.setEndSpin(this.getEndSpin()||0);
            retParticle.setEndSpinVar(this.getEndSpinVar()||0);
            retParticle.setEmitterMode(this.getEmitterMode());
            if (this.getEmitterMode() === cc.ParticleSystem.MODE_GRAVITY) {
                var gra = this.getGravity();
                retParticle.setGravity(cc.p(gra.x,gra.y));
                retParticle.setSpeed(this.getSpeed());
                retParticle.setSpeedVar(this.getSpeedVar());
                retParticle.setRadialAccel(this.getRadialAccel());
                retParticle.setRadialAccelVar(this.getRadialAccelVar());
                retParticle.setTangentialAccel(this.getTangentialAccel());
                retParticle.setTangentialAccelVar(this.getTangentialAccelVar());
            } else if (this.getEmitterMode() === cc.ParticleSystem.MODE_RADIUS) {
                retParticle.setStartRadius(this.getStartRadius());
                retParticle.setStartRadiusVar(this.getStartRadiusVar());
                retParticle.setEndRadius(this.getEndRadius());
                retParticle.setEndRadiusVar(this.getEndRadiusVar());
                retParticle.setRotatePerSecond(this.getRotatePerSecond());
                retParticle.setRotatePerSecondVar(this.getRotatePerSecondVar());
            }
            retParticle.setLife(this.getLife());
            retParticle.setLifeVar(this.getLifeVar());
            retParticle.setEmissionRate(this.getEmissionRate());
            if (!this.getBatchNode()) {
                retParticle.setOpacityModifyRGB(this.isOpacityModifyRGB());
                var texture = this.getTexture();
                if(texture){
                    var size = texture.getContentSize();
                    retParticle.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height));
                }
            }
        }
        return retParticle;
    },
    setDisplayFrame: function (spriteFrame) {
        if (!spriteFrame)
            return;
        var locOffset = spriteFrame.getOffsetInPixels();
        if (locOffset.x !== 0 || locOffset.y !== 0)
            cc.log("cc.ParticleSystem.setDisplayFrame(): QuadParticle only supports SpriteFrames with no offsets");
        var texture = spriteFrame.getTexture(), locTexture = this._texture;
        if (locTexture !== texture)
            this.setTexture(texture);
    },
    setTextureWithRect: function (texture, rect) {
        var locTexture = this._texture;
        if (locTexture !== texture) {
            this._texture = texture;
            this._updateBlendFunc();
        }
        this.initTexCoordsWithRect(rect);
    },
    listenBackToForeground:function (obj) {
    }
});
var _p = cc.ParticleSystem.prototype;
_p.opacityModifyRGB;
cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB, _p.setOpacityModifyRGB);
_p.batchNode;
cc.defineGetterSetter(_p, "batchNode", _p.getBatchNode, _p.setBatchNode);
_p.drawMode;
cc.defineGetterSetter(_p, "drawMode", _p.getDrawMode, _p.setDrawMode);
_p.shapeType;
cc.defineGetterSetter(_p, "shapeType", _p.getShapeType, _p.setShapeType);
_p.active;
cc.defineGetterSetter(_p, "active", _p.isActive);
_p.sourcePos;
cc.defineGetterSetter(_p, "sourcePos", _p.getSourcePosition, _p.setSourcePosition);
_p.posVar;
cc.defineGetterSetter(_p, "posVar", _p.getPosVar, _p.setPosVar);
_p.gravity;
cc.defineGetterSetter(_p, "gravity", _p.getGravity, _p.setGravity);
_p.speed;
cc.defineGetterSetter(_p, "speed", _p.getSpeed, _p.setSpeed);
_p.speedVar;
cc.defineGetterSetter(_p, "speedVar", _p.getSpeedVar, _p.setSpeedVar);
_p.tangentialAccel;
cc.defineGetterSetter(_p, "tangentialAccel", _p.getTangentialAccel, _p.setTangentialAccel);
_p.tangentialAccelVar;
cc.defineGetterSetter(_p, "tangentialAccelVar", _p.getTangentialAccelVar, _p.setTangentialAccelVar);
_p.radialAccel;
cc.defineGetterSetter(_p, "radialAccel", _p.getRadialAccel, _p.setRadialAccel);
_p.radialAccelVar;
cc.defineGetterSetter(_p, "radialAccelVar", _p.getRadialAccelVar, _p.setRadialAccelVar);
_p.rotationIsDir;
cc.defineGetterSetter(_p, "rotationIsDir", _p.getRotationIsDir, _p.setRotationIsDir);
_p.startRadius;
cc.defineGetterSetter(_p, "startRadius", _p.getStartRadius, _p.setStartRadius);
_p.startRadiusVar;
cc.defineGetterSetter(_p, "startRadiusVar", _p.getStartRadiusVar, _p.setStartRadiusVar);
_p.endRadius;
cc.defineGetterSetter(_p, "endRadius", _p.getEndRadius, _p.setEndRadius);
_p.endRadiusVar;
cc.defineGetterSetter(_p, "endRadiusVar", _p.getEndRadiusVar, _p.setEndRadiusVar);
_p.rotatePerS;
cc.defineGetterSetter(_p, "rotatePerS", _p.getRotatePerSecond, _p.setRotatePerSecond);
_p.rotatePerSVar;
cc.defineGetterSetter(_p, "rotatePerSVar", _p.getRotatePerSecondVar, _p.setRotatePerSecondVar);
_p.startColor;
cc.defineGetterSetter(_p, "startColor", _p.getStartColor, _p.setStartColor);
_p.startColorVar;
cc.defineGetterSetter(_p, "startColorVar", _p.getStartColorVar, _p.setStartColorVar);
_p.endColor;
cc.defineGetterSetter(_p, "endColor", _p.getEndColor, _p.setEndColor);
_p.endColorVar;
cc.defineGetterSetter(_p, "endColorVar", _p.getEndColorVar, _p.setEndColorVar);
_p.totalParticles;
cc.defineGetterSetter(_p, "totalParticles", _p.getTotalParticles, _p.setTotalParticles);
_p.texture;
cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
cc.ParticleSystem.create = function (plistFile) {
    return new cc.ParticleSystem(plistFile);
};
cc.ParticleSystem.createWithTotalParticles = cc.ParticleSystem.create;
cc.ParticleSystem.ModeA = function (gravity, speed, speedVar, tangentialAccel, tangentialAccelVar, radialAccel, radialAccelVar, rotationIsDir) {
    this.gravity = gravity ? gravity : cc.p(0,0);
    this.speed = speed || 0;
    this.speedVar = speedVar || 0;
    this.tangentialAccel = tangentialAccel || 0;
    this.tangentialAccelVar = tangentialAccelVar || 0;
    this.radialAccel = radialAccel || 0;
    this.radialAccelVar = radialAccelVar || 0;
    this.rotationIsDir = rotationIsDir || false;
};
cc.ParticleSystem.ModeB = function (startRadius, startRadiusVar, endRadius, endRadiusVar, rotatePerSecond, rotatePerSecondVar) {
    this.startRadius = startRadius || 0;
    this.startRadiusVar = startRadiusVar || 0;
    this.endRadius = endRadius || 0;
    this.endRadiusVar = endRadiusVar || 0;
    this.rotatePerSecond = rotatePerSecond || 0;
    this.rotatePerSecondVar = rotatePerSecondVar || 0;
};
cc.ParticleSystem.SHAPE_MODE = 0;
cc.ParticleSystem.TEXTURE_MODE = 1;
cc.ParticleSystem.STAR_SHAPE = 0;
cc.ParticleSystem.BALL_SHAPE = 1;
cc.ParticleSystem.DURATION_INFINITY = -1;
cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE = -1;
cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS = -1;
cc.ParticleSystem.MODE_GRAVITY = 0;
cc.ParticleSystem.MODE_RADIUS = 1;
cc.ParticleSystem.TYPE_FREE = 0;
cc.ParticleSystem.TYPE_RELATIVE = 1;
cc.ParticleSystem.TYPE_GROUPED = 2;
(function(){
    cc.ParticleSystem.CanvasRenderCmd = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._drawMode = cc.ParticleSystem.TEXTURE_MODE;
        this._shapeType = cc.ParticleSystem.BALL_SHAPE;
        this._pointRect = cc.rect(0, 0, 0, 0);
        this._tintCache = document.createElement("canvas");
    };
    var proto = cc.ParticleSystem.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.ParticleSystem.CanvasRenderCmd;
    proto.getDrawMode = function(){
        return this._drawMode;
    };
    proto.setDrawMode = function(drawMode){
        this._drawMode = drawMode;
    };
    proto.getShapeType = function(){
        return this._shapeType;
    };
    proto.setShapeType = function(shapeType){
        this._shapeType = shapeType;
    };
    proto.setBatchNode = function(batchNode){
        if (this._batchNode !== batchNode) {
            this._node._batchNode = batchNode;
        }
    };
    proto.updateQuadWithParticle = function (particle, newPosition) {
    };
    proto.updateParticlePosition = function(particle, position){
        cc.pIn(particle.drawPos, position);
    };
    proto.rendering = function (ctx, scaleX, scaleY) {
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext(),
            node = this._node, pointRect = this._pointRect;
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        wrapper.save();
        if (node.isBlendAdditive())
            context.globalCompositeOperation = 'lighter';
        else
            context.globalCompositeOperation = 'source-over';
        var i, particle, lpx, alpha;
        var particleCount = this._node.particleCount, particles = this._node._particles;
        if (node.drawMode !== cc.ParticleSystem.SHAPE_MODE && node._texture) {
            if (!node._texture._textureLoaded) {
                wrapper.restore();
                return;
            }
            var element = node._texture.getHtmlElementObj();
            if (!element.width || !element.height) {
                wrapper.restore();
                return;
            }
            var drawElement = element;
            for (i = 0; i < particleCount; i++) {
                particle = particles[i];
                lpx = (0 | (particle.size * 0.5));
                alpha = particle.color.a / 255;
                if (alpha === 0) continue;
                context.globalAlpha = alpha;
                context.save();
                context.translate((0 | particle.drawPos.x), -(0 | particle.drawPos.y));
                var size = Math.floor(particle.size / 4) * 4;
                var w = pointRect.width;
                var h = pointRect.height;
                context.scale(Math.max((1 / w) * size, 0.000001), Math.max((1 / h) * size, 0.000001));
                if (particle.rotation)
                    context.rotate(cc.degreesToRadians(particle.rotation));
                drawElement = particle.isChangeColor ? this._changeTextureColor(node._texture, particle.color, this._pointRect) : element;
                context.drawImage(drawElement, -(0 | (w / 2)), -(0 | (h / 2)));
                context.restore();
            }
        } else {
            var drawTool = cc._drawingUtil;
            for (i = 0; i < particleCount; i++) {
                particle = particles[i];
                lpx = (0 | (particle.size * 0.5));
                alpha = particle.color.a / 255;
                if (alpha === 0) continue;
                context.globalAlpha = alpha;
                context.save();
                context.translate(0 | particle.drawPos.x, -(0 | particle.drawPos.y));
                if (node.shapeType === cc.ParticleSystem.STAR_SHAPE) {
                    if (particle.rotation)
                        context.rotate(cc.degreesToRadians(particle.rotation));
                    drawTool.drawStar(wrapper, lpx, particle.color);
                } else
                    drawTool.drawColorBall(wrapper, lpx, particle.color);
                context.restore();
            }
        }
        wrapper.restore();
        cc.g_NumberOfDraws++;
    };
    proto._changeTextureColor = function(texture, color, rect){
        var tintCache = this._tintCache;
        var textureContentSize = texture.getContentSize();
        tintCache.width = textureContentSize.width;
        tintCache.height = textureContentSize.height;
        return texture._generateColorTexture(color.r, color.g, color.b, rect, tintCache);
    };
    proto.initTexCoordsWithRect = function(pointRect){
        this._pointRect = pointRect;
    };
    proto.setTotalParticles = function(tp){
        this._node._totalParticles = (tp < 200) ? tp : 200;
    };
    proto.addParticle = function(){
        var node = this._node,
            particles = node._particles,
            particle;
        if (node.particleCount < particles.length) {
            particle = particles[node.particleCount];
        } else {
            particle = new cc.Particle();
            particles.push(particle);
        }
        return particle;
    };
    proto._setupVBO = function(){};
    proto._allocMemory = function(){
        return true;
    };
    proto.postStep = function(){};
    proto._setBlendAdditive = function(){
        var locBlendFunc = this._node._blendFunc;
        locBlendFunc.src = cc.BLEND_SRC;
        locBlendFunc.dst = cc.BLEND_DST;
    };
    proto._initWithTotalParticles = function(totalParticles){};
    proto._updateDeltaColor = function(selParticle, dt){
        if (!this._node._dontTint) {
            selParticle.color.r += selParticle.deltaColor.r * dt;
            selParticle.color.g += selParticle.deltaColor.g * dt;
            selParticle.color.b += selParticle.deltaColor.b * dt;
            selParticle.color.a += selParticle.deltaColor.a * dt;
            selParticle.isChangeColor = true;
        }
    };
})();
cc.ParticleFire = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 300 : 150);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setRadialAccel(0);
            this.setRadialAccelVar(0);
            this.setSpeed(60);
            this.setSpeedVar(20);
            this.setAngle(90);
            this.setAngleVar(10);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, 60);
            this.setPosVar(cc.p(40, 20));
            this.setLife(3);
            this.setLifeVar(0.25);
            this.setStartSize(54.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(194,64,31,255));
            this.setStartColorVar(cc.color(0,0,0,0));
            this.setEndColor(cc.color(0,0,0,255));
            this.setEndColorVar(cc.color(0,0,0,0));
            this.setBlendAdditive(true);
            return true;
        }
        return false;
    }
});
cc.ParticleFire.create = function () {
    return new cc.ParticleFire();
};
cc.ParticleFireworks = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 1500 : 150);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, -90));
            this.setRadialAccel(0);
            this.setRadialAccelVar(0);
            this.setSpeed(180);
            this.setSpeedVar(50);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setAngle(90);
            this.setAngleVar(20);
            this.setLife(3.5);
            this.setLifeVar(1);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(128,128,128,255));
            this.setStartColorVar(cc.color(128,128,128,255));
            this.setEndColor(cc.color(26,26,26,51));
            this.setEndColorVar(cc.color(26,26,26,51));
            this.setStartSize(8.0);
            this.setStartSizeVar(2.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setBlendAdditive(false);
            return true;
        }
        return false;
    }
});
cc.ParticleFireworks.create = function () {
    return new cc.ParticleFireworks();
};
cc.ParticleSun = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 350 : 150);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setBlendAdditive(true);
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setRadialAccel(0);
            this.setRadialAccelVar(0);
            this.setSpeed(20);
            this.setSpeedVar(5);
            this.setAngle(90);
            this.setAngleVar(360);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setPosVar(cc.p(0,0));
            this.setLife(1);
            this.setLifeVar(0.5);
            this.setStartSize(30.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(194, 64, 31, 255));
            this.setStartColorVar(cc.color(0, 0, 0, 0));
            this.setEndColor(cc.color(0, 0, 0, 255));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            return true;
        }
        return false;
    }
});
cc.ParticleSun.create = function () {
    return new cc.ParticleSun();
};
cc.ParticleGalaxy = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 200 : 100);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setSpeed(60);
            this.setSpeedVar(10);
            this.setRadialAccel(-80);
            this.setRadialAccelVar(0);
            this.setTangentialAccel(80);
            this.setTangentialAccelVar(0);
            this.setAngle(90);
            this.setAngleVar(360);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setPosVar(cc.p(0,0));
            this.setLife(4);
            this.setLifeVar(1);
            this.setStartSize(37.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(31, 64, 194, 255));
            this.setStartColorVar(cc.color(0, 0, 0, 0));
            this.setEndColor(cc.color(0, 0, 0, 255));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            this.setBlendAdditive(true);
            return true;
        }
        return false;
    }
});
cc.ParticleGalaxy.create = function () {
    return new cc.ParticleGalaxy();
};
cc.ParticleFlower = cc.ParticleSystem.extend({
    ctor : function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 250 : 100);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setSpeed(80);
            this.setSpeedVar(10);
            this.setRadialAccel(-60);
            this.setRadialAccelVar(0);
            this.setTangentialAccel(15);
            this.setTangentialAccelVar(0);
            this.setAngle(90);
            this.setAngleVar(360);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setPosVar(cc.p(0,0));
            this.setLife(4);
            this.setLifeVar(1);
            this.setStartSize(30.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(128, 128, 128, 255));
            this.setStartColorVar(cc.color(128, 128, 128, 128));
            this.setEndColor(cc.color(0, 0, 0, 255));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            this.setBlendAdditive(true);
            return true;
        }
        return false;
    }
});
cc.ParticleFlower.create = function () {
    return new cc.ParticleFlower();
};
cc.ParticleMeteor = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 150 : 100);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(-200, 200));
            this.setSpeed(15);
            this.setSpeedVar(5);
            this.setRadialAccel(0);
            this.setRadialAccelVar(0);
            this.setTangentialAccel(0);
            this.setTangentialAccelVar(0);
            this.setAngle(90);
            this.setAngleVar(360);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setPosVar(cc.p(0,0));
            this.setLife(2);
            this.setLifeVar(1);
            this.setStartSize(60.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(51, 102, 179));
            this.setStartColorVar(cc.color(0, 0, 51, 26));
            this.setEndColor(cc.color(0, 0, 0, 255));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            this.setBlendAdditive(true);
            return true;
        }
        return false;
    }
});
cc.ParticleMeteor.create = function () {
    return new cc.ParticleMeteor();
};
cc.ParticleSpiral = cc.ParticleSystem.extend({
    ctor:function() {
        cc.ParticleSystem.prototype.ctor.call(this,(cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 500 : 100);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setSpeed(150);
            this.setSpeedVar(0);
            this.setRadialAccel(-380);
            this.setRadialAccelVar(0);
            this.setTangentialAccel(45);
            this.setTangentialAccelVar(0);
            this.setAngle(90);
            this.setAngleVar(0);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setPosVar(cc.p(0,0));
            this.setLife(12);
            this.setLifeVar(0);
            this.setStartSize(20.0);
            this.setStartSizeVar(0.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(128,128,128,255));
            this.setStartColorVar(cc.color(128,128,128,0));
            this.setEndColor(cc.color(128,128,128,255));
            this.setEndColorVar(cc.color(128,128,128,0));
            this.setBlendAdditive(false);
            return true;
        }
        return false;
    }
});
cc.ParticleSpiral.create = function () {
    return new cc.ParticleSpiral();
};
cc.ParticleExplosion = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 700 : 300);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(0.1);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setSpeed(70);
            this.setSpeedVar(40);
            this.setRadialAccel(0);
            this.setRadialAccelVar(0);
            this.setTangentialAccel(0);
            this.setTangentialAccelVar(0);
            this.setAngle(90);
            this.setAngleVar(360);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height / 2);
            this.setPosVar(cc.p(0,0));
            this.setLife(5.0);
            this.setLifeVar(2);
            this.setStartSize(15.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getDuration());
            this.setStartColor(cc.color(179, 26, 51, 255));
            this.setStartColorVar(cc.color(128, 128, 128, 0));
            this.setEndColor(cc.color(128, 128, 128, 0));
            this.setEndColorVar(cc.color(128, 128, 128, 0));
            this.setBlendAdditive(false);
            return true;
        }
        return false;
    }
});
cc.ParticleExplosion.create = function () {
    return new cc.ParticleExplosion();
};
cc.ParticleSmoke = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 200 : 100);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, 0));
            this.setRadialAccel(0);
            this.setRadialAccelVar(0);
            this.setSpeed(25);
            this.setSpeedVar(10);
            this.setAngle(90);
            this.setAngleVar(5);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, 0);
            this.setPosVar(cc.p(20, 0));
            this.setLife(4);
            this.setLifeVar(1);
            this.setStartSize(60.0);
            this.setStartSizeVar(10.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(this.getTotalParticles() / this.getLife());
            this.setStartColor(cc.color(204, 204, 204, 255));
            this.setStartColorVar(cc.color(5, 5, 5, 0));
            this.setEndColor(cc.color(0, 0, 0, 255));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            this.setBlendAdditive(false);
            return true;
        }
        return false;
    }
});
cc.ParticleSmoke.create = function () {
    return new cc.ParticleSmoke();
};
cc.ParticleSnow = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 700 : 250);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(0, -1));
            this.setSpeed(5);
            this.setSpeedVar(1);
            this.setRadialAccel(0);
            this.setRadialAccelVar(1);
            this.setTangentialAccel(0);
            this.setTangentialAccelVar(1);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height + 10);
            this.setPosVar(cc.p(winSize.width / 2, 0));
            this.setAngle(-90);
            this.setAngleVar(5);
            this.setLife(45);
            this.setLifeVar(15);
            this.setStartSize(10.0);
            this.setStartSizeVar(5.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(10);
            this.setStartColor(cc.color(255, 255, 255, 255));
            this.setStartColorVar(cc.color(0, 0, 0, 0));
            this.setEndColor(cc.color(255, 255, 255, 0));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            this.setBlendAdditive(false);
            return true;
        }
        return false;
    }
});
cc.ParticleSnow.create = function () {
    return new cc.ParticleSnow();
};
cc.ParticleRain = cc.ParticleSystem.extend({
    ctor:function () {
        cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 1000 : 300);
    },
    initWithTotalParticles:function (numberOfParticles) {
        if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
            this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
            this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
            this.setGravity(cc.p(10, -10));
            this.setRadialAccel(0);
            this.setRadialAccelVar(1);
            this.setTangentialAccel(0);
            this.setTangentialAccelVar(1);
            this.setSpeed(130);
            this.setSpeedVar(30);
            this.setAngle(-90);
            this.setAngleVar(5);
            var winSize = cc.director.getWinSize();
            this.setPosition(winSize.width / 2, winSize.height);
            this.setPosVar(cc.p(winSize.width / 2, 0));
            this.setLife(4.5);
            this.setLifeVar(0);
            this.setStartSize(4.0);
            this.setStartSizeVar(2.0);
            this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
            this.setEmissionRate(20);
            this.setStartColor(cc.color(179, 204, 255, 255));
            this.setStartColorVar(cc.color(0, 0, 0, 0));
            this.setEndColor(cc.color(179, 204, 255, 128));
            this.setEndColorVar(cc.color(0, 0, 0, 0));
            this.setBlendAdditive(false);
            return true;
        }
        return false;
    }
});
cc.ParticleRain.create = function () {
    return new cc.ParticleRain();
};
cc.PARTICLE_DEFAULT_CAPACITY = 500;
cc.ParticleBatchNode = cc.Node.extend({
    textureAtlas:null,
    _blendFunc:null,
    _className:"ParticleBatchNode",
    ctor:function (fileImage, capacity) {
        cc.Node.prototype.ctor.call(this);
        this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST};
        if (cc.isString(fileImage)) {
            this.init(fileImage, capacity);
        } else if (fileImage instanceof cc.Texture2D) {
            this.initWithTexture(fileImage, capacity);
        }
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.ParticleBatchNode.CanvasRenderCmd(this);
        else
            return new cc.ParticleBatchNode.WebGLRenderCmd(this);
    },
    initWithTexture:function (texture, capacity) {
        this.textureAtlas = new cc.TextureAtlas();
        this.textureAtlas.initWithTexture(texture, capacity);
        this._children.length = 0;
        this._renderCmd._initWithTexture();
        return true;
    },
    initWithFile:function (fileImage, capacity) {
        var tex = cc.textureCache.addImage(fileImage);
        return this.initWithTexture(tex, capacity);
    },
    init:function (fileImage, capacity) {
        var tex = cc.textureCache.addImage(fileImage);
        return this.initWithTexture(tex, capacity);
    },
    addChild:function (child, zOrder, tag) {
        if(!child)
            throw new Error("cc.ParticleBatchNode.addChild() : child should be non-null");
        if(!(child instanceof cc.ParticleSystem))
            throw new Error("cc.ParticleBatchNode.addChild() : only supports cc.ParticleSystem as children");
        zOrder = (zOrder == null) ? child.zIndex : zOrder;
        tag = (tag == null) ? child.tag : tag;
        if(child.getTexture() !== this.textureAtlas.texture)
            throw new Error("cc.ParticleSystem.addChild() : the child is not using the same texture id");
        var childBlendFunc = child.getBlendFunc();
        if (this._children.length === 0)
            this.setBlendFunc(childBlendFunc);
        else{
            if((childBlendFunc.src !== this._blendFunc.src) || (childBlendFunc.dst !== this._blendFunc.dst)){
                cc.log("cc.ParticleSystem.addChild() : Can't add a ParticleSystem that uses a different blending function");
                return;
            }
        }
        var pos = this._addChildHelper(child, zOrder, tag);
        var atlasIndex = 0;
        if (pos !== 0) {
            var p = this._children[pos - 1];
            atlasIndex = p.getAtlasIndex() + p.getTotalParticles();
        } else
            atlasIndex = 0;
        this.insertChild(child, atlasIndex);
        child.setBatchNode(this);
    },
    insertChild:function (pSystem, index) {
        var totalParticles = pSystem.getTotalParticles();
        var locTextureAtlas = this.textureAtlas;
        var totalQuads = locTextureAtlas.totalQuads;
        pSystem.setAtlasIndex(index);
        if (totalQuads + totalParticles > locTextureAtlas.getCapacity()) {
            this._increaseAtlasCapacityTo(totalQuads + totalParticles);
            locTextureAtlas.fillWithEmptyQuadsFromIndex(locTextureAtlas.getCapacity() - totalParticles, totalParticles);
        }
        if (pSystem.getAtlasIndex() + totalParticles !== totalQuads)
            locTextureAtlas.moveQuadsFromIndex(index, index + totalParticles);
        locTextureAtlas.increaseTotalQuadsWith(totalParticles);
        this._updateAllAtlasIndexes();
    },
    removeChild:function (child, cleanup) {
        if (child == null)
            return;
        if(!(child instanceof cc.ParticleSystem))
            throw new Error("cc.ParticleBatchNode.removeChild(): only supports cc.ParticleSystem as children");
        if(this._children.indexOf(child) === -1){
            cc.log("cc.ParticleBatchNode.removeChild(): doesn't contain the sprite. Can't remove it");
            return;
        }
        cc.Node.prototype.removeChild.call(this, child, cleanup);
        var locTextureAtlas = this.textureAtlas;
        locTextureAtlas.removeQuadsAtIndex(child.getAtlasIndex(), child.getTotalParticles());
        locTextureAtlas.fillWithEmptyQuadsFromIndex(locTextureAtlas.totalQuads, child.getTotalParticles());
        child.setBatchNode(null);
        this._updateAllAtlasIndexes();
    },
    reorderChild:function (child, zOrder) {
        if(!child)
            throw new Error("cc.ParticleBatchNode.reorderChild(): child should be non-null");
        if(!(child instanceof cc.ParticleSystem))
            throw new Error("cc.ParticleBatchNode.reorderChild(): only supports cc.QuadParticleSystems as children");
        if(this._children.indexOf(child) === -1){
            cc.log("cc.ParticleBatchNode.reorderChild(): Child doesn't belong to batch");
            return;
        }
        if (zOrder === child.zIndex)
            return;
        if (this._children.length > 1) {
            var getIndexes = this._getCurrentIndex(child, zOrder);
            if (getIndexes.oldIndex !== getIndexes.newIndex) {
                this._children.splice(getIndexes.oldIndex, 1)
                this._children.splice(getIndexes.newIndex, 0, child);
                var oldAtlasIndex = child.getAtlasIndex();
                this._updateAllAtlasIndexes();
                var newAtlasIndex = 0;
                var locChildren = this._children;
                for (var i = 0; i < locChildren.length; i++) {
                    var pNode = locChildren[i];
                    if (pNode === child) {
                        newAtlasIndex = child.getAtlasIndex();
                        break;
                    }
                }
                this.textureAtlas.moveQuadsFromIndex(oldAtlasIndex, child.getTotalParticles(), newAtlasIndex);
                child.updateWithNoTime();
            }
        }
        child._setLocalZOrder(zOrder);
    },
    removeChildAtIndex:function (index, doCleanup) {
        this.removeChild(this._children[i], doCleanup);
    },
    removeAllChildren:function (doCleanup) {
        var locChildren = this._children;
        for (var i = 0; i < locChildren.length; i++) {
            locChildren[i].setBatchNode(null);
        }
        cc.Node.prototype.removeAllChildren.call(this, doCleanup);
        this.textureAtlas.removeAllQuads();
    },
    disableParticle:function (particleIndex) {
        var quad = this.textureAtlas.quads[particleIndex];
        quad.br.vertices.x = quad.br.vertices.y = quad.tr.vertices.x = quad.tr.vertices.y =
            quad.tl.vertices.x = quad.tl.vertices.y = quad.bl.vertices.x = quad.bl.vertices.y = 0.0;
        this.textureAtlas._setDirty(true);
    },
    getTexture:function () {
        return this.textureAtlas.texture;
    },
    setTexture:function (texture) {
        this.textureAtlas.texture = texture;
        var locBlendFunc = this._blendFunc;
        if (texture && !texture.hasPremultipliedAlpha() && ( locBlendFunc.src === cc.BLEND_SRC && locBlendFunc.dst === cc.BLEND_DST )) {
            locBlendFunc.src = cc.SRC_ALPHA;
            locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
        }
    },
    setBlendFunc:function (src, dst) {
        if (dst === undefined){
            this._blendFunc.src = src.src;
            this._blendFunc.dst = src.dst;
        } else{
            this._blendFunc.src = src;
            this._blendFunc.src = dst;
        }
    },
    getBlendFunc:function () {
        return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
    },
    _updateAllAtlasIndexes:function () {
        var index = 0;
        var locChildren = this._children;
        for (var i = 0; i < locChildren.length; i++) {
            var child = locChildren[i];
            child.setAtlasIndex(index);
            index += child.getTotalParticles();
        }
    },
    _increaseAtlasCapacityTo:function (quantity) {
        cc.log("cocos2d: cc.ParticleBatchNode: resizing TextureAtlas capacity from [" + this.textureAtlas.getCapacity()
            + "] to [" + quantity + "].");
        if (!this.textureAtlas.resizeCapacity(quantity)) {
            cc.log("cc.ParticleBatchNode._increaseAtlasCapacityTo() : WARNING: Not enough memory to resize the atlas");
        }
    },
    _searchNewPositionInChildrenForZ:function (z) {
        var locChildren = this._children;
        var count = locChildren.length;
        for (var i = 0; i < count; i++) {
            if (locChildren[i].zIndex > z)
                return i;
        }
        return count;
    },
    _getCurrentIndex:function (child, z) {
        var foundCurrentIdx = false;
        var foundNewIdx = false;
        var newIndex = 0;
        var oldIndex = 0;
        var minusOne = 0, locChildren = this._children;
        var count = locChildren.length;
        for (var i = 0; i < count; i++) {
            var pNode = locChildren[i];
            if (pNode.zIndex > z && !foundNewIdx) {
                newIndex = i;
                foundNewIdx = true;
                if (foundCurrentIdx && foundNewIdx)
                    break;
            }
            if (child === pNode) {
                oldIndex = i;
                foundCurrentIdx = true;
                if (!foundNewIdx)
                    minusOne = -1;
                if (foundCurrentIdx && foundNewIdx)
                    break;
            }
        }
        if (!foundNewIdx)
            newIndex = count;
        newIndex += minusOne;
        return {newIndex:newIndex, oldIndex:oldIndex};
    },
    _addChildHelper:function (child, z, aTag) {
        if(!child)
            throw new Error("cc.ParticleBatchNode._addChildHelper(): child should be non-null");
        if(child.parent){
            cc.log("cc.ParticleBatchNode._addChildHelper(): child already added. It can't be added again");
            return null;
        }
        if (!this._children)
            this._children = [];
        var pos = this._searchNewPositionInChildrenForZ(z);
        this._children.splice(pos, 0, child);
        child.tag = aTag;
        child._setLocalZOrder(z);
        child.parent = this;
        if (this._running) {
            child.onEnter();
            child.onEnterTransitionDidFinish();
        }
        return pos;
    },
    _updateBlendFunc:function () {
        if (!this.textureAtlas.texture.hasPremultipliedAlpha()) {
            this._blendFunc.src = cc.SRC_ALPHA;
            this._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
        }
    },
    getTextureAtlas:function () {
        return this.textureAtlas;
    },
    setTextureAtlas:function (textureAtlas) {
        this.textureAtlas = textureAtlas;
    }
});
var _p = cc.ParticleBatchNode.prototype;
_p.texture;
cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
cc.ParticleBatchNode.create = function (fileImage, capacity) {
    return new cc.ParticleBatchNode(fileImage, capacity);
};
(function(){
    cc.ParticleBatchNode.CanvasRenderCmd = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = false;
    };
    var proto = cc.ParticleBatchNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.ParticleBatchNode.CanvasRenderCmd;
    proto._initWithTexture = function(){};
})();
(function(){
    cc.ParticleBatchNode.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
    };
    var proto = cc.ParticleBatchNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.ParticleBatchNode.WebGLRenderCmd;
    proto.rendering = function (ctx) {
        var _t = this._node;
        if (_t.textureAtlas.totalQuads === 0)
            return;
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        cc.glBlendFuncForParticle(_t._blendFunc.src, _t._blendFunc.dst);
        _t.textureAtlas.drawQuads();
    };
    proto._initWithTexture = function(){
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        parentCmd = parentCmd || this.getParentRenderCmd();
        if (parentCmd)
            this._curLevel = parentCmd._curLevel + 1;
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this);
        this._dirtyFlag = 0;
    };
})();
(function(){
    cc.ParticleSystem.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
        this._buffersVBO = [0, 0];
        this._quads = [];
        this._indices = [];
        this._quadsArrayBuffer = null;
    };
    var proto = cc.ParticleSystem.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.ParticleSystem.WebGLRenderCmd;
    proto.getDrawMode = function(){};
    proto.setDrawMode = function(drawMode){};
    proto.getShapeType = function(){};
    proto.setShapeType = function(shapeType){};
    proto.setBatchNode = function(batchNode){
        var node = this._node;
        if (node._batchNode !== batchNode) {
            var oldBatch = node._batchNode;
            node._batchNode = batchNode;
            if (batchNode) {
                var locParticles = node._particles;
                for (var i = 0; i < node._totalParticles; i++)
                    locParticles[i].atlasIndex = i;
            }
            if (!batchNode) {
                this._allocMemory();
                this.initIndices(node._totalParticles);
                node.setTexture(oldBatch.getTexture());
                this._setupVBO();
            } else if (!oldBatch) {
                node._batchNode.textureAtlas._copyQuadsToTextureAtlas(this._quads, node.atlasIndex);
                cc._renderContext.deleteBuffer(this._buffersVBO[1]);
            }
        }
    };
    proto.initIndices = function (totalParticles) {
        var locIndices = this._indices;
        for (var i = 0, len = totalParticles; i < len; ++i) {
            var i6 = i * 6;
            var i4 = i * 4;
            locIndices[i6 + 0] = i4 + 0;
            locIndices[i6 + 1] = i4 + 1;
            locIndices[i6 + 2] = i4 + 2;
            locIndices[i6 + 5] = i4 + 1;
            locIndices[i6 + 4] = i4 + 2;
            locIndices[i6 + 3] = i4 + 3;
        }
    };
    proto.isDifferentTexture = function(texture1, texture2){
         return (texture1 === texture2);
    };
    proto.updateParticlePosition = function(particle, position){
        this.updateQuadWithParticle(particle, position);
    };
    proto.updateQuadWithParticle = function (particle, newPosition) {
        var quad = null, node = this._node;
        if (node._batchNode) {
            var batchQuads = node._batchNode.textureAtlas.quads;
            quad = batchQuads[node.atlasIndex + particle.atlasIndex];
            node._batchNode.textureAtlas.dirty = true;
        } else
            quad = this._quads[node._particleIdx];
        var r, g, b, a;
        if (node._opacityModifyRGB) {
            r = 0 | (particle.color.r * particle.color.a/255);
            g = 0 | (particle.color.g * particle.color.a/255);
            b = 0 | (particle.color.b * particle.color.a/255);
        } else {
            r = 0 | (particle.color.r );
            g = 0 | (particle.color.g );
            b = 0 | (particle.color.b );
        }
        a = 0 | (particle.color.a );
        var blColors = quad.bl.colors, brColors = quad.br.colors, tlColors = quad.tl.colors, trColors = quad.tr.colors;
        blColors.r = brColors.r = tlColors.r = trColors.r = r;
        blColors.g = brColors.g = tlColors.g = trColors.g = g;
        blColors.b = brColors.b = tlColors.b = trColors.b = b;
        blColors.a = brColors.a = tlColors.a = trColors.a = a;
        var size_2 = particle.size / 2;
        if (particle.rotation) {
            var x1 = -size_2, y1 = -size_2;
            var x2 = size_2, y2 = size_2;
            var x = newPosition.x, y = newPosition.y;
            var rad = -cc.degreesToRadians(particle.rotation);
            var cr = Math.cos(rad), sr = Math.sin(rad);
            var ax = x1 * cr - y1 * sr + x;
            var ay = x1 * sr + y1 * cr + y;
            var bx = x2 * cr - y1 * sr + x;
            var by = x2 * sr + y1 * cr + y;
            var cx = x2 * cr - y2 * sr + x;
            var cy = x2 * sr + y2 * cr + y;
            var dx = x1 * cr - y2 * sr + x;
            var dy = x1 * sr + y2 * cr + y;
            quad.bl.vertices.x = ax;
            quad.bl.vertices.y = ay;
            quad.br.vertices.x = bx;
            quad.br.vertices.y = by;
            quad.tl.vertices.x = dx;
            quad.tl.vertices.y = dy;
            quad.tr.vertices.x = cx;
            quad.tr.vertices.y = cy;
        } else {
            quad.bl.vertices.x = newPosition.x - size_2;
            quad.bl.vertices.y = newPosition.y - size_2;
            quad.br.vertices.x = newPosition.x + size_2;
            quad.br.vertices.y = newPosition.y - size_2;
            quad.tl.vertices.x = newPosition.x - size_2;
            quad.tl.vertices.y = newPosition.y + size_2;
            quad.tr.vertices.x = newPosition.x + size_2;
            quad.tr.vertices.y = newPosition.y + size_2;
        }
    };
    proto.rendering = function (ctx) {
        var node = this._node;
        if (!node._texture)
            return;
        var gl = ctx || cc._renderContext;
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        cc.glBindTexture2D(node._texture);
        cc.glBlendFuncForParticle(node._blendFunc.src, node._blendFunc.dst);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
        gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
        gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
        gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
        gl.drawElements(gl.TRIANGLES, node._particleIdx * 6, gl.UNSIGNED_SHORT, 0);
    };
    proto.initTexCoordsWithRect = function(pointRect){
        var node = this._node;
        var texture = node.texture;
        var scaleFactor = cc.contentScaleFactor();
        var rect = cc.rect(
                pointRect.x * scaleFactor,
                pointRect.y * scaleFactor,
                pointRect.width * scaleFactor,
                pointRect.height * scaleFactor);
        var wide = pointRect.width;
        var high = pointRect.height;
        if (texture) {
            wide = texture.pixelsWidth;
            high = texture.pixelsHeight;
        }
        var left, bottom, right, top;
        if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
            left = (rect.x * 2 + 1) / (wide * 2);
            bottom = (rect.y * 2 + 1) / (high * 2);
            right = left + (rect.width * 2 - 2) / (wide * 2);
            top = bottom + (rect.height * 2 - 2) / (high * 2);
        } else {
            left = rect.x / wide;
            bottom = rect.y / high;
            right = left + rect.width / wide;
            top = bottom + rect.height / high;
        }
        var temp = top;
        top = bottom;
        bottom = temp;
        var quads;
        var start = 0, end = 0;
        if (node._batchNode) {
            quads = node._batchNode.textureAtlas.quads;
            start = node.atlasIndex;
            end = node.atlasIndex + node._totalParticles;
        } else {
            quads = this._quads;
            start = 0;
            end = node._totalParticles;
        }
        for (var i = start; i < end; i++) {
            if (!quads[i])
                quads[i] = cc.V3F_C4B_T2F_QuadZero();
            var selQuad = quads[i];
            selQuad.bl.texCoords.u = left;
            selQuad.bl.texCoords.v = bottom;
            selQuad.br.texCoords.u = right;
            selQuad.br.texCoords.v = bottom;
            selQuad.tl.texCoords.u = left;
            selQuad.tl.texCoords.v = top;
            selQuad.tr.texCoords.u = right;
            selQuad.tr.texCoords.v = top;
        }
    };
    proto.setTotalParticles = function(tp){
        var node = this._node;
        if (tp > node._allocatedParticles) {
            var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
            this._indices = new Uint16Array(tp * 6);
            var locQuadsArrayBuffer = new ArrayBuffer(tp * quadSize);
            var locParticles = node._particles;
            locParticles.length = 0;
            var locQuads = this._quads;
            locQuads.length = 0;
            for (var j = 0; j < tp; j++) {
                locParticles[j] = new cc.Particle();
                locQuads[j] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, j * quadSize);
            }
            node._allocatedParticles = tp;
            node._totalParticles = tp;
            if (node._batchNode) {
                for (var i = 0; i < tp; i++)
                    locParticles[i].atlasIndex = i;
            }
            this._quadsArrayBuffer = locQuadsArrayBuffer;
            this.initIndices(tp);
            this._setupVBO();
            if(node._texture){
                this.initTexCoordsWithRect(cc.rect(0, 0, node._texture.width, node._texture.height));
            }
        } else
            node._totalParticles = tp;
        node.resetSystem();
    };
    proto.addParticle = function(){
        var node = this._node,
            particles = node._particles;
        return particles[node.particleCount];
    };
    proto._setupVBO = function(){
        var node = this;
        var gl = cc._renderContext;
        this._buffersVBO[0] = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
        gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
        this._buffersVBO[1] = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
    };
    proto._allocMemory = function(){
        var node  = this._node;
        if(node._batchNode){
            cc.log("cc.ParticleSystem._allocMemory(): Memory should not be allocated when not using batchNode");
            return false;
        }
        var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
        var totalParticles = node._totalParticles;
        var locQuads = this._quads;
        locQuads.length = 0;
        this._indices = new Uint16Array(totalParticles * 6);
        var locQuadsArrayBuffer = new ArrayBuffer(quadSize * totalParticles);
        for (var i = 0; i < totalParticles; i++)
            locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, i * quadSize);
        if (!locQuads || !this._indices) {
            cc.log("cocos2d: Particle system: not enough memory");
            return false;
        }
        this._quadsArrayBuffer = locQuadsArrayBuffer;
        return true;
    };
    proto.postStep = function(){
        var gl = cc._renderContext;
        gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
        gl.bufferSubData(gl.ARRAY_BUFFER, 0, this._quadsArrayBuffer);
    };
    proto._setBlendAdditive = function(){
        var locBlendFunc = this._node._blendFunc;
        if (this._texture && !this._texture.hasPremultipliedAlpha()) {
            locBlendFunc.src = cc.SRC_ALPHA;
            locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
        } else {
            locBlendFunc.src = cc.BLEND_SRC;
            locBlendFunc.dst = cc.BLEND_DST;
        }
    };
    proto._initWithTotalParticles = function(totalParticles){
        if (!this._allocMemory())
            return false;
        this.initIndices(totalParticles);
        this._setupVBO();
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
    };
    proto._updateDeltaColor = function (selParticle, dt) {
        selParticle.color.r += selParticle.deltaColor.r * dt;
        selParticle.color.g += selParticle.deltaColor.g * dt;
        selParticle.color.b += selParticle.deltaColor.b * dt;
        selParticle.color.a += selParticle.deltaColor.a * dt;
        selParticle.isChangeColor = true;
    };
})();
cc.IMEKeyboardNotificationInfo = function (begin, end, duration) {
    this.begin = begin || cc.rect(0, 0, 0, 0);
    this.end = end || cc.rect(0, 0, 0, 0);
    this.duration = duration || 0;
};
cc.IMEDelegate = cc.Class.extend({
    ctor:function () {
        cc.imeDispatcher.addDelegate(this);
    },
    removeDelegate:function () {
        cc.imeDispatcher.removeDelegate(this);
    },
    attachWithIME:function () {
        return cc.imeDispatcher.attachDelegateWithIME(this);
    },
    detachWithIME:function () {
        return cc.imeDispatcher.detachDelegateWithIME(this);
    },
    canAttachWithIME:function () {
        return false;
    },
    didAttachWithIME:function () {
    },
    canDetachWithIME:function () {
        return false;
    },
    didDetachWithIME:function () {
    },
    insertText:function (text, len) {
    },
    deleteBackward:function () {
    },
    getContentText:function () {
        return "";
    },
    keyboardWillShow:function (info) {
    },
    keyboardDidShow:function (info) {
    },
    keyboardWillHide:function (info) {
    },
    keyboardDidHide:function (info) {
    }
});
cc.IMEDispatcher = cc.Class.extend({
    _domInputControl:null,
    impl:null,
    _currentInputString:"",
    _lastClickPosition:null,
    ctor:function () {
        this.impl = new cc.IMEDispatcher.Impl();
        this._lastClickPosition = cc.p(0, 0);
    },
    init:function () {
        if (cc.sys.isMobile)
            return;
        this._domInputControl = cc.$("#imeDispatcherInput");
        if (!this._domInputControl) {
            this._domInputControl = cc.$new("input");
            this._domInputControl.setAttribute("type", "text");
            this._domInputControl.setAttribute("id", "imeDispatcherInput");
            this._domInputControl.resize(0.0, 0.0);
            this._domInputControl.translates(0, 0);
            this._domInputControl.style.opacity = "0";
            this._domInputControl.style.fontSize = "1px";
            this._domInputControl.setAttribute('tabindex', 2);
            this._domInputControl.style.position = "absolute";
            this._domInputControl.style.top = 0;
            this._domInputControl.style.left = 0;
            document.body.appendChild(this._domInputControl);
        }
        var selfPointer = this;
        this._domInputControl.addEventListener("input", function () {
            selfPointer._processDomInputString(selfPointer._domInputControl.value);
        }, false);
        this._domInputControl.addEventListener("keydown", function (e) {
            if (e.keyCode === cc.KEY.tab) {
                e.stopPropagation();
                e.preventDefault();
            } else if (e.keyCode === cc.KEY.enter) {
                selfPointer.dispatchInsertText("\n", 1);
                e.stopPropagation();
                e.preventDefault();
            }
        }, false);
        if (/msie/i.test(navigator.userAgent)) {
            this._domInputControl.addEventListener("keyup", function (e) {
                if (e.keyCode === cc.KEY.backspace) {
                    selfPointer._processDomInputString(selfPointer._domInputControl.value);
                }
            }, false);
        }
        window.addEventListener('mousedown', function (event) {
            var tx = event.pageX || 0;
            var ty = event.pageY || 0;
            selfPointer._lastClickPosition.x = tx;
            selfPointer._lastClickPosition.y = ty;
        }, false);
    },
    _processDomInputString:function (text) {
        var i, startPos;
        var len = this._currentInputString.length < text.length ? this._currentInputString.length : text.length;
        for (startPos = 0; startPos < len; startPos++) {
            if (text[startPos] !== this._currentInputString[startPos])
                break;
        }
        var delTimes = this._currentInputString.length - startPos;
        var insTimes = text.length - startPos;
        for (i = 0; i < delTimes; i++)
            this.dispatchDeleteBackward();
        for (i = 0; i < insTimes; i++)
            this.dispatchInsertText(text[startPos + i], 1);
        this._currentInputString = text;
    },
    dispatchInsertText:function (text, len) {
        if (!this.impl || !text || len <= 0)
            return;
        if (!this.impl._delegateWithIme)
            return;
        this.impl._delegateWithIme.insertText(text, len);
    },
    dispatchDeleteBackward:function () {
        if (!this.impl) {
            return;
        }
        if (!this.impl._delegateWithIme)
            return;
        this.impl._delegateWithIme.deleteBackward();
    },
    getContentText:function () {
        if (this.impl && this.impl._delegateWithIme) {
            var pszContentText = this.impl._delegateWithIme.getContentText();
            return (pszContentText) ? pszContentText : "";
        }
        return "";
    },
    dispatchKeyboardWillShow:function (info) {
        if (this.impl) {
            for (var i = 0; i < this.impl._delegateList.length; i++) {
                var delegate = this.impl._delegateList[i];
                if (delegate) {
                    delegate.keyboardWillShow(info);
                }
            }
        }
    },
    dispatchKeyboardDidShow:function (info) {
        if (this.impl) {
            for (var i = 0; i < this.impl._delegateList.length; i++) {
                var delegate = this.impl._delegateList[i];
                if (delegate)
                    delegate.keyboardDidShow(info);
            }
        }
    },
    dispatchKeyboardWillHide:function (info) {
        if (this.impl) {
            for (var i = 0; i < this.impl._delegateList.length; i++) {
                var delegate = this.impl._delegateList[i];
                if (delegate) {
                    delegate.keyboardWillHide(info);
                }
            }
        }
    },
    dispatchKeyboardDidHide:function (info) {
        if (this.impl) {
            for (var i = 0; i < this.impl._delegateList.length; i++) {
                var delegate = this.impl._delegateList[i];
                if (delegate) {
                    delegate.keyboardDidHide(info);
                }
            }
        }
    },
    addDelegate:function (delegate) {
        if (!delegate || !this.impl)
            return;
        if (this.impl._delegateList.indexOf(delegate) > -1) {
            return;
        }
        this.impl._delegateList.splice(0, 0, delegate);
    },
    attachDelegateWithIME:function (delegate) {
        if (!this.impl || !delegate)
            return false;
        if (this.impl._delegateList.indexOf(delegate) === -1)
            return false;
        if (this.impl._delegateWithIme) {
            if (!this.impl._delegateWithIme.canDetachWithIME()
                || !delegate.canAttachWithIME())
                return false;
            var pOldDelegate = this.impl._delegateWithIme;
            this.impl._delegateWithIme = null;
            pOldDelegate.didDetachWithIME();
            this._focusDomInput(delegate);
            return true;
        }
        if (!delegate.canAttachWithIME())
            return false;
        this._focusDomInput(delegate);
        return true;
    },
    _focusDomInput:function (delegate) {
        if(cc.sys.isMobile){
            this.impl._delegateWithIme = delegate;
            delegate.didAttachWithIME();
            this._currentInputString = delegate.string || "";
            var tipMessage = delegate.getTipMessage ? delegate.getTipMessage() : "please enter your word:";
            var userInput;
            var win = window.Window;
            if(win && win.prototype.prompt && win.prototype.prompt != prompt){
                userInput = win.prototype.prompt.call(window, tipMessage, this._currentInputString);
            }else{
                userInput = prompt(tipMessage, this._currentInputString);
            }
            if(userInput != null)
                this._processDomInputString(userInput);
            this.dispatchInsertText("\n", 1);
        }else{
            this.impl._delegateWithIme = delegate;
            this._currentInputString = delegate.string || "";
            delegate.didAttachWithIME();
            this._domInputControl.focus();
            this._domInputControl.value = this._currentInputString;
            this._domInputControlTranslate();
        }
    },
    _domInputControlTranslate:function () {
        if (/msie/i.test(navigator.userAgent)) {
            this._domInputControl.style.left = this._lastClickPosition.x + "px";
            this._domInputControl.style.top = this._lastClickPosition.y + "px";
        } else {
            this._domInputControl.translates(this._lastClickPosition.x, this._lastClickPosition.y);
        }
    },
    detachDelegateWithIME:function (delegate) {
        if (!this.impl || !delegate)
            return false;
        if (this.impl._delegateWithIme !== delegate)
            return false;
        if (!delegate.canDetachWithIME())
            return false;
        this.impl._delegateWithIme = null;
        delegate.didDetachWithIME();
        cc._canvas.focus();
        return true;
    },
    removeDelegate:function (delegate) {
        if (!this.impl || !delegate)
            return;
        if (this.impl._delegateList.indexOf(delegate) === -1)
            return;
        if (this.impl._delegateWithIme) {
            if (delegate === this.impl._delegateWithIme) {
                this.impl._delegateWithIme = null;
            }
        }
        cc.arrayRemoveObject(this.impl._delegateList, delegate);
    },
    processKeycode:function (keyCode) {
        if (keyCode < 32) {
            if (keyCode === cc.KEY.backspace) {
                this.dispatchDeleteBackward();
            } else if (keyCode === cc.KEY.enter) {
                this.dispatchInsertText("\n", 1);
            } else if (keyCode === cc.KEY.tab) {
            } else if (keyCode === cc.KEY.escape) {
            }
        } else if (keyCode < 255) {
            this.dispatchInsertText(String.fromCharCode(keyCode), 1);
        } else {
        }
    }
});
cc.IMEDispatcher.Impl = cc.Class.extend({
    _delegateWithIme:null,
    _delegateList:null,
    ctor:function () {
        this._delegateList = [];
    },
    findDelegate:function (delegate) {
        for (var i = 0; i < this._delegateList.length; i++) {
            if (this._delegateList[i] === delegate)
                return i;
        }
        return null;
    }
});
cc.imeDispatcher = new cc.IMEDispatcher();
document.body ?
    cc.imeDispatcher.init() :
    window.addEventListener('load', function () {
        cc.imeDispatcher.init();
    }, false);
cc.TextFieldDelegate = cc.Class.extend({
    onTextFieldAttachWithIME:function (sender) {
        return false;
    },
    onTextFieldDetachWithIME:function (sender) {
        return false;
    },
    onTextFieldInsertText:function (sender, text, len) {
        return false
    },
    onTextFieldDeleteBackward:function (sender, delText, len) {
        return false;
    },
    onDraw:function (sender) {
        return false;
    }
});
cc.TextFieldTTF = cc.LabelTTF.extend({
    delegate:null,
    colorSpaceHolder:null,
    _colorText: null,
    _lens:null,
    _inputText:"",
    _placeHolder:"",
    _charCount:0,
    _className:"TextFieldTTF",
    ctor:function (placeholder, dimensions, alignment, fontName, fontSize) {
        this.colorSpaceHolder = cc.color(127, 127, 127);
        this._colorText = cc.color(255,255,255, 255);
        cc.LabelTTF.prototype.ctor.call(this);
        if(fontSize !== undefined){
            this.initWithPlaceHolder("", dimensions, alignment, fontName, fontSize);
            if(placeholder)
                this.setPlaceHolder(placeholder);
        }else if(fontName === undefined && alignment !== undefined){
            this.initWithString("", arguments[1], arguments[2]);
            if(placeholder)
                this.setPlaceHolder(placeholder);
        }
    },
    onEnter: function(){
        cc.LabelTTF.prototype.onEnter.call(this);
        cc.imeDispatcher.addDelegate(this);
    },
    onExit: function(){
        cc.LabelTTF.prototype.onExit.call(this);
        cc.imeDispatcher.removeDelegate(this);
    },
    getDelegate:function () {
        return this.delegate;
    },
    setDelegate:function (value) {
        this.delegate = value;
    },
    getCharCount:function () {
        return this._charCount;
    },
    getColorSpaceHolder:function () {
        return cc.color(this.colorSpaceHolder);
    },
    setColorSpaceHolder:function (value) {
        this.colorSpaceHolder.r = value.r;
        this.colorSpaceHolder.g = value.g;
        this.colorSpaceHolder.b = value.b;
        this.colorSpaceHolder.a = cc.isUndefined(value.a) ? 255 : value.a;
        if(!this._inputText.length)
            this.setColor(this.colorSpaceHolder);
    },
    setTextColor:function(textColor){
        this._colorText.r = textColor.r;
        this._colorText.g = textColor.g;
        this._colorText.b = textColor.b;
        this._colorText.a = cc.isUndefined(textColor.a) ? 255 : textColor.a;
        if(this._inputText.length)
            this.setColor(this._colorText);
    },
    initWithPlaceHolder:function (placeholder, dimensions, alignment, fontName, fontSize) {
        switch (arguments.length) {
            case 5:
                if (placeholder)
                    this.setPlaceHolder(placeholder);
                return this.initWithString(this._placeHolder,fontName, fontSize, dimensions, alignment);
                break;
            case 3:
                if (placeholder)
                    this.setPlaceHolder(placeholder);
                return this.initWithString(this._placeHolder, arguments[1], arguments[2]);
                break;
            default:
                throw new Error("Argument must be non-nil ");
                break;
        }
    },
    setString:function (text) {
        text = String(text);
        this._inputText = text || "";
        if (!this._inputText.length){
            cc.LabelTTF.prototype.setString.call(this, this._placeHolder);
            this.setColor(this.colorSpaceHolder);
        } else {
            cc.LabelTTF.prototype.setString.call(this,this._inputText);
            this.setColor(this._colorText);
        }
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            this._renderCmd._updateTexture();
        this._charCount = this._inputText.length;
    },
    getString:function () {
        return this._inputText;
    },
    setPlaceHolder:function (text) {
        this._placeHolder = text || "";
        if (!this._inputText.length) {
            cc.LabelTTF.prototype.setString.call(this,this._placeHolder);
            this.setColor(this.colorSpaceHolder);
        }
    },
    getPlaceHolder:function () {
        return this._placeHolder;
    },
    draw:function (ctx) {
        var context = ctx || cc._renderContext;
        if (this.delegate && this.delegate.onDraw(this))
            return;
        cc.LabelTTF.prototype.draw.call(this, context);
    },
    visit: function(ctx){
        this._super(ctx);
    },
    attachWithIME:function () {
        return cc.imeDispatcher.attachDelegateWithIME(this);
    },
    detachWithIME:function () {
        return cc.imeDispatcher.detachDelegateWithIME(this);
    },
    canAttachWithIME:function () {
        return (this.delegate) ? (!this.delegate.onTextFieldAttachWithIME(this)) : true;
    },
    didAttachWithIME:function () {
    },
    canDetachWithIME:function () {
        return (this.delegate) ? (!this.delegate.onTextFieldDetachWithIME(this)) : true;
    },
    didDetachWithIME:function () {
    },
    deleteBackward:function () {
        var strLen = this._inputText.length;
        if (strLen === 0)
            return;
        var deleteLen = 1;
        if (this.delegate && this.delegate.onTextFieldDeleteBackward(this, this._inputText[strLen - deleteLen], deleteLen)) {
            return;
        }
        if (strLen <= deleteLen) {
            this._inputText = "";
            this._charCount = 0;
            cc.LabelTTF.prototype.setString.call(this,this._placeHolder);
            this.setColor(this.colorSpaceHolder);
            return;
        }
        this.string = this._inputText.substring(0, strLen - deleteLen);
    },
    removeDelegate:function () {
        cc.imeDispatcher.removeDelegate(this);
    },
    _tipMessage: "please enter your word:",
    setTipMessage: function (tipMessage) {
        if (tipMessage == null)
            return;
        this._tipMessage = tipMessage;
    },
    getTipMessage: function () {
        return this._tipMessage;
    },
    insertText:function (text, len) {
        var sInsert = text;
        var pos = sInsert.indexOf('\n');
        if (pos > -1) {
            sInsert = sInsert.substring(0, pos);
        }
        if (sInsert.length > 0) {
            if (this.delegate && this.delegate.onTextFieldInsertText(this, sInsert, sInsert.length)) {
                return;
            }
            var sText = this._inputText + sInsert;
            this._charCount = sText.length;
            this.string = sText;
        }
        if (pos === -1)
            return;
        if (this.delegate && this.delegate.onTextFieldInsertText(this, "\n", 1))
            return;
        this.detachWithIME();
    },
    getContentText:function () {
        return this._inputText;
    },
    keyboardWillShow:function (info) {
    },
    keyboardDidShow:function (info) {
    },
    keyboardWillHide:function (info) {
    },
    keyboardDidHide:function (info) {
    }
});
var _p = cc.TextFieldTTF.prototype;
_p.charCount;
cc.defineGetterSetter(_p, "charCount", _p.getCharCount);
_p.placeHolder;
cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
cc.TextFieldTTF.create = function (placeholder, dimensions, alignment, fontName, fontSize) {
    return new cc.TextFieldTTF(placeholder, dimensions, alignment, fontName, fontSize);
};
cc.TGA_OK = 0;
cc.TGA_ERROR_FILE_OPEN = 1;
cc.TGA_ERROR_READING_FILE = 2;
cc.TGA_ERROR_INDEXED_COLOR = 3;
cc.TGA_ERROR_MEMORY = 4;
cc.TGA_ERROR_COMPRESSED_FILE = 5;
cc.ImageTGA = function (status, type, pixelDepth, width, height, imageData, flipped) {
    this.status = status || 0;
    this.type = type || 0;
    this.pixelDepth = pixelDepth || 0;
    this.width = width || 0;
    this.height = height || 0;
    this.imageData = imageData || [];
    this.flipped = flipped || 0;
};
cc.tgaLoadHeader = function (buffer, bufSize, psInfo) {
    var step = 2;
    if (step + 1 > bufSize)
        return false;
    var binaryReader = new cc.BinaryStreamReader(buffer);
    binaryReader.setOffset(step);
    psInfo.type = binaryReader.readByte();
    step += 10;
    if (step + 4 + 1 > bufSize)
        return false;
    binaryReader.setOffset(step);
    psInfo.width = binaryReader.readUnsignedShort();
    psInfo.height = binaryReader.readUnsignedInteger();
    psInfo.pixelDepth = binaryReader.readByte();
    step += 5;
    if (step + 1 > bufSize)
        return false;
    var garbage = binaryReader.readByte();
    psInfo.flipped = 0;
    if (garbage & 0x20)
        psInfo.flipped = 1;
    return true;
};
cc.tgaLoadImageData = function (buffer, bufSize, psInfo) {
    var mode, total, i, aux;
    var step = 18;
    mode = 0 | (psInfo.pixelDepth / 2);
    total = psInfo.height * psInfo.width * mode;
    if (step + total > bufSize)
        return false;
    psInfo.imageData = cc.__getSubArray(buffer, step, step + total);
    if (mode >= 3) {
        for (i = 0; i < total; i += mode) {
            aux = psInfo.imageData[i];
            psInfo.imageData[i] = psInfo.imageData[i + 2];
            psInfo.imageData[i + 2] = aux;
        }
    }
    return true;
};
cc.tgaRGBtogreyscale = function (psInfo) {
    var i, j;
    if (psInfo.pixelDepth === 8)
        return;
    var mode = psInfo.pixelDepth / 8;
    var newImageData = new Uint8Array(psInfo.height * psInfo.width);
    if (newImageData === null)
        return;
    for (i = 0, j = 0; j < psInfo.width * psInfo.height; i += mode, j++)
        newImageData[j] = (0.30 * psInfo.imageData[i] + 0.59 * psInfo.imageData[i + 1] + 0.11 * psInfo.imageData[i + 2]);
    psInfo.pixelDepth = 8;
    psInfo.type = 3;
    psInfo.imageData = newImageData;
};
cc.tgaDestroy = function (psInfo) {
    if (!psInfo)
        return;
    psInfo.imageData = null;
    psInfo = null;
};
cc.tgaLoadRLEImageData = function (buffer, bufSize, psInfo) {
    var mode, total, i, index = 0 , skip = 0, flag = 0;
    var aux = [], runlength = 0;
    var step = 18;
    mode = psInfo.pixelDepth / 8;
    total = psInfo.height * psInfo.width;
    for (i = 0; i < total; i++) {
        if (runlength !== 0) {
            runlength--;
            skip = (flag !== 0);
        } else {
            if (step + 1 > bufSize)
                break;
            runlength = buffer[step];
            step += 1;
            flag = runlength & 0x80;
            if (flag)
                runlength -= 128;
            skip = 0;
        }
        if (!skip) {
            if (step + mode > bufSize)
                break;
            aux = cc.__getSubArray(buffer, step, step + mode);
            step += mode;
            if (mode >= 3) {
                var tmp = aux[0];
                aux[0] = aux[2];
                aux[2] = tmp;
            }
        }
        for (var j = 0; j < mode; j++)
            psInfo.imageData[index + j] = aux[j];
        index += mode;
    }
    return true;
};
cc.tgaFlipImage = function (psInfo) {
    var mode = psInfo.pixelDepth / 8;
    var rowbytes = psInfo.width * mode;
    for (var y = 0; y < (psInfo.height / 2); y++) {
        var row = cc.__getSubArray(psInfo.imageData, y * rowbytes, y * rowbytes + rowbytes);
        cc.__setDataToArray(cc.__getSubArray(psInfo.imageData, (psInfo.height - (y + 1)) * rowbytes, rowbytes), psInfo.imageData, y * rowbytes);
        cc.__setDataToArray(row, psInfo.imageData, (psInfo.height - (y + 1)) * rowbytes);
    }
    psInfo.flipped = 0;
};
cc.__getSubArray = function (array, start, end) {
    if (array instanceof  Array)
        return array.slice(start, end);
    else
        return array.subarray(start, end);
};
cc.__setDataToArray = function (sourceData, destArray, startIndex) {
    for (var i = 0; i < sourceData.length; i++)
        destArray[startIndex + i] = sourceData[i];
};
cc.BinaryStreamReader = cc.Class.extend({
    _binaryData:null,
    _offset:0,
    ctor:function (binaryData) {
        this._binaryData = binaryData;
    },
    setBinaryData:function (binaryData) {
        this._binaryData = binaryData;
        this._offset = 0;
    },
    getBinaryData:function () {
        return this._binaryData;
    },
    _checkSize:function (neededBits) {
        if (!(this._offset + Math.ceil(neededBits / 8) < this._data.length))
            throw new Error("Index out of bound");
    },
    _decodeFloat:function (precisionBits, exponentBits) {
        var length = precisionBits + exponentBits + 1;
        var size = length >> 3;
        this._checkSize(length);
        var bias = Math.pow(2, exponentBits - 1) - 1;
        var signal = this._readBits(precisionBits + exponentBits, 1, size);
        var exponent = this._readBits(precisionBits, exponentBits, size);
        var significand = 0;
        var divisor = 2;
        var curByte = 0;
        do {
            var byteValue = this._readByte(++curByte, size);
            var startBit = precisionBits % 8 || 8;
            var mask = 1 << startBit;
            while (mask >>= 1) {
                if (byteValue & mask)
                    significand += 1 / divisor;
                divisor *= 2;
            }
        } while (precisionBits -= startBit);
        this._offset += size;
        return exponent === (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
            : (1 + signal * -2) * (exponent || significand ? !exponent ? Math.pow(2, -bias + 1) * significand
            : Math.pow(2, exponent - bias) * (1 + significand) : 0);
    },
    _readByte:function (i, size) {
        return this._data[this._offset + size - i - 1];
    },
    _decodeInt:function (bits, signed) {
        var x = this._readBits(0, bits, bits / 8), max = Math.pow(2, bits);
        var result = signed && x >= max / 2 ? x - max : x;
        this._offset += bits / 8;
        return result;
    },
    _shl:function (a, b) {
        for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) === 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1){};
        return a;
    },
    _readBits:function (start, length, size) {
        var offsetLeft = (start + length) % 8;
        var offsetRight = start % 8;
        var curByte = size - (start >> 3) - 1;
        var lastByte = size + (-(start + length) >> 3);
        var diff = curByte - lastByte;
        var sum = (this._readByte(curByte, size) >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1);
        if (diff && offsetLeft)
            sum += (this._readByte(lastByte++, size) & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight;
        while (diff)
            sum += this._shl(this._readByte(lastByte++, size), (diff-- << 3) - offsetRight);
        return sum;
    },
    readInteger:function () {
        return this._decodeInt(32, true);
    },
    readUnsignedInteger:function () {
        return this._decodeInt(32, false);
    },
    readSingle:function () {
        return this._decodeFloat(23, 8);
    },
    readShort:function () {
        return this._decodeInt(16, true);
    },
    readUnsignedShort:function () {
        return this._decodeInt(16, false);
    },
    readByte:function () {
        var readByte = this._data[this._offset];
        this._offset += 1;
        return readByte;
    },
    readData:function (start, end) {
        if (this._binaryData instanceof Array) {
            return this._binaryData.slice(start, end);
        } else {
            return this._binaryData.subarray(start, end);
        }
    },
    setOffset:function (offset) {
        this._offset = offset;
    },
    getOffset:function () {
        return this._offset;
    }
});
cc.TMX_ORIENTATION_ORTHO = 0;
cc.TMX_ORIENTATION_HEX = 1;
cc.TMX_ORIENTATION_ISO = 2;
cc.TMXTiledMap = cc.Node.extend({
    properties: null,
    mapOrientation: null,
    objectGroups: null,
    _mapSize: null,
    _tileSize: null,
    _tileProperties: null,
    _className: "TMXTiledMap",
    ctor:function(tmxFile,resourcePath){
        cc.Node.prototype.ctor.call(this);
        this._mapSize = cc.size(0, 0);
        this._tileSize = cc.size(0, 0);
        if(resourcePath !== undefined){
            this.initWithXML(tmxFile,resourcePath);
        }else if(tmxFile !== undefined){
            this.initWithTMXFile(tmxFile);
        }
    },
    getMapSize:function () {
        return cc.size(this._mapSize.width, this._mapSize.height);
    },
    setMapSize:function (Var) {
        this._mapSize.width = Var.width;
        this._mapSize.height = Var.height;
    },
    _getMapWidth: function () {
        return this._mapSize.width;
    },
    _setMapWidth: function (width) {
        this._mapSize.width = width;
    },
    _getMapHeight: function () {
        return this._mapSize.height;
    },
    _setMapHeight: function (height) {
        this._mapSize.height = height;
    },
    getTileSize:function () {
        return cc.size(this._tileSize.width, this._tileSize.height);
    },
    setTileSize:function (Var) {
        this._tileSize.width = Var.width;
        this._tileSize.height = Var.height;
    },
    _getTileWidth: function () {
        return this._tileSize.width;
    },
    _setTileWidth: function (width) {
        this._tileSize.width = width;
    },
    _getTileHeight: function () {
        return this._tileSize.height;
    },
    _setTileHeight: function (height) {
        this._tileSize.height = height;
    },
    getMapOrientation:function () {
        return this.mapOrientation;
    },
    setMapOrientation:function (Var) {
        this.mapOrientation = Var;
    },
    getObjectGroups:function () {
        return this.objectGroups;
    },
    setObjectGroups:function (Var) {
        this.objectGroups = Var;
    },
    getProperties:function () {
        return this.properties;
    },
    setProperties:function (Var) {
        this.properties = Var;
    },
    initWithTMXFile:function (tmxFile) {
        if(!tmxFile || tmxFile.length === 0)
            throw new Error("cc.TMXTiledMap.initWithTMXFile(): tmxFile should be non-null or non-empty string.");
        this.width = 0;
        this.height = 0;
        var mapInfo = new cc.TMXMapInfo(tmxFile);
        if (!mapInfo)
            return false;
        var locTilesets = mapInfo.getTilesets();
        if(!locTilesets || locTilesets.length === 0)
            cc.log("cc.TMXTiledMap.initWithTMXFile(): Map not found. Please check the filename.");
        this._buildWithMapInfo(mapInfo);
        return true;
    },
    initWithXML:function(tmxString, resourcePath){
        this.width = 0;
        this.height = 0;
        var mapInfo = new cc.TMXMapInfo(tmxString, resourcePath);
        var locTilesets = mapInfo.getTilesets();
        if(!locTilesets || locTilesets.length === 0)
            cc.log("cc.TMXTiledMap.initWithXML(): Map not found. Please check the filename.");
        this._buildWithMapInfo(mapInfo);
        return true;
    },
    _buildWithMapInfo:function (mapInfo) {
        this._mapSize = mapInfo.getMapSize();
        this._tileSize = mapInfo.getTileSize();
        this.mapOrientation = mapInfo.orientation;
        this.objectGroups = mapInfo.getObjectGroups();
        this.properties = mapInfo.properties;
        this._tileProperties = mapInfo.getTileProperties();
        var idx = 0;
        var layers = mapInfo.getLayers();
        if (layers) {
            var layerInfo = null;
            for (var i = 0, len = layers.length; i < len; i++) {
                layerInfo = layers[i];
                if (layerInfo && layerInfo.visible) {
                    var child = this._parseLayer(layerInfo, mapInfo);
                    this.addChild(child, idx, idx);
                    this.width = Math.max(this.width, child.width);
                    this.height = Math.max(this.height, child.height);
                    idx++;
                }
            }
        }
    },
    allLayers: function () {
        var retArr = [], locChildren = this._children;
        for(var i = 0, len = locChildren.length;i< len;i++){
            var layer = locChildren[i];
            if(layer && layer instanceof cc.TMXLayer)
                retArr.push(layer);
        }
        return retArr;
    },
    getLayer:function (layerName) {
        if(!layerName || layerName.length === 0)
            throw new Error("cc.TMXTiledMap.getLayer(): layerName should be non-null or non-empty string.");
        var locChildren = this._children;
        for (var i = 0; i < locChildren.length; i++) {
            var layer = locChildren[i];
            if (layer && layer.layerName === layerName)
                return layer;
        }
        return null;
    },
    getObjectGroup:function (groupName) {
        if(!groupName || groupName.length === 0)
            throw new Error("cc.TMXTiledMap.getObjectGroup(): groupName should be non-null or non-empty string.");
        if (this.objectGroups) {
            for (var i = 0; i < this.objectGroups.length; i++) {
                var objectGroup = this.objectGroups[i];
                if (objectGroup && objectGroup.groupName === groupName) {
                    return objectGroup;
                }
            }
        }
        return null;
    },
    getProperty:function (propertyName) {
        return this.properties[propertyName.toString()];
    },
    propertiesForGID:function (GID) {
        cc.log("propertiesForGID is deprecated. Please use getPropertiesForGID instead.");
        return this.getPropertiesForGID[GID];
    },
    getPropertiesForGID: function(GID) {
        return this._tileProperties[GID];
    },
    _parseLayer:function (layerInfo, mapInfo) {
        var tileset = this._tilesetForLayer(layerInfo, mapInfo);
        var layer = new cc.TMXLayer(tileset, layerInfo, mapInfo);
        layerInfo.ownTiles = false;
        return layer;
    },
    _tilesetForLayer:function (layerInfo, mapInfo) {
        var size = layerInfo._layerSize;
        var tilesets = mapInfo.getTilesets();
        if (tilesets) {
            for (var i = tilesets.length - 1; i >= 0; i--) {
                var tileset = tilesets[i];
                if (tileset) {
                    for (var y = 0; y < size.height; y++) {
                        for (var x = 0; x < size.width; x++) {
                            var pos = x + size.width * y;
                            var gid = layerInfo._tiles[pos];
                            if (gid !== 0) {
                                if (((gid & cc.TMX_TILE_FLIPPED_MASK)>>>0) >= tileset.firstGid) {
                                    return tileset;
                                }
                            }
                        }
                    }
                }
            }
        }
        cc.log("cocos2d: Warning: TMX Layer " + layerInfo.name + " has no tiles");
        return null;
    }
});
var _p = cc.TMXTiledMap.prototype;
_p.mapWidth;
cc.defineGetterSetter(_p, "mapWidth", _p._getMapWidth, _p._setMapWidth);
_p.mapHeight;
cc.defineGetterSetter(_p, "mapHeight", _p._getMapHeight, _p._setMapHeight);
_p.tileWidth;
cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth);
_p.tileHeight;
cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight);
cc.TMXTiledMap.create = function (tmxFile,resourcePath) {
    return new cc.TMXTiledMap(tmxFile,resourcePath);
};
cc.TMX_PROPERTY_NONE = 0;
cc.TMX_PROPERTY_MAP = 1;
cc.TMX_PROPERTY_LAYER = 2;
cc.TMX_PROPERTY_OBJECTGROUP = 3;
cc.TMX_PROPERTY_OBJECT = 4;
cc.TMX_PROPERTY_TILE = 5;
cc.TMX_TILE_HORIZONTAL_FLAG = 0x80000000;
cc.TMX_TILE_VERTICAL_FLAG = 0x40000000;
cc.TMX_TILE_DIAGONAL_FLAG = 0x20000000;
cc.TMX_TILE_FLIPPED_ALL = (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_DIAGONAL_FLAG) >>> 0;
cc.TMX_TILE_FLIPPED_MASK = (~(cc.TMX_TILE_FLIPPED_ALL)) >>> 0;
cc.TMXLayerInfo = cc.Class.extend({
    properties:null,
    name:"",
    _layerSize:null,
    _tiles:null,
    visible:null,
    _opacity:null,
    ownTiles:true,
    _minGID:100000,
    _maxGID:0,
    offset:null,
    ctor:function () {
        this.properties = [];
        this.name = "";
        this._layerSize = null;
        this._tiles = null;
        this.visible = true;
        this._opacity = 0;
        this.ownTiles = true;
        this._minGID = 100000;
        this._maxGID = 0;
        this.offset = cc.p(0,0);
    },
    getProperties:function () {
        return this.properties;
    },
    setProperties:function (value) {
        this.properties = value;
    }
});
cc.TMXTilesetInfo = cc.Class.extend({
    name:"",
    firstGid:0,
    _tileSize:null,
    spacing:0,
    margin:0,
    sourceImage:"",
    imageSize:null,
    ctor:function () {
        this._tileSize = cc.size(0, 0);
        this.imageSize = cc.size(0, 0);
    },
    rectForGID:function (gid, result) {
        var rect = result || cc.rect(0, 0, 0, 0);
        rect.width = this._tileSize.width;
        rect.height = this._tileSize.height;
        gid &= cc.TMX_TILE_FLIPPED_MASK;
        gid = gid - parseInt(this.firstGid, 10);
        var max_x = parseInt((this.imageSize.width - this.margin * 2 + this.spacing) / (this._tileSize.width + this.spacing), 10);
        rect.x = parseInt((gid % max_x) * (this._tileSize.width + this.spacing) + this.margin, 10);
        rect.y = parseInt(parseInt(gid / max_x, 10) * (this._tileSize.height + this.spacing) + this.margin, 10);
        return rect;
    }
});
cc.TMXMapInfo = cc.SAXParser.extend({
    properties:null,
    orientation:null,
    parentElement:null,
    parentGID:null,
    layerAttrs:0,
    storingCharacters:false,
    tmxFileName:null,
    currentString:null,
    _objectGroups:null,
    _mapSize:null,
    _tileSize:null,
    _layers:null,
    _tilesets:null,
    _tileProperties:null,
    _resources:"",
    _currentFirstGID:0,
    ctor:function (tmxFile, resourcePath) {
        cc.SAXParser.prototype.ctor.apply(this);
        this._mapSize = cc.size(0, 0);
        this._tileSize = cc.size(0, 0);
        this._layers = [];
        this._tilesets = [];
        this._objectGroups = [];
        this.properties = [];
        this._tileProperties = {};
        this._currentFirstGID = 0;
        if (resourcePath !== undefined) {
            this.initWithXML(tmxFile,resourcePath);
        } else if(tmxFile !== undefined){
            this.initWithTMXFile(tmxFile);
        }
    },
    getOrientation:function () {
        return this.orientation;
    },
    setOrientation:function (value) {
        this.orientation = value;
    },
    getMapSize:function () {
        return cc.size(this._mapSize.width,this._mapSize.height);
    },
    setMapSize:function (value) {
        this._mapSize.width = value.width;
        this._mapSize.height = value.height;
    },
    _getMapWidth: function () {
        return this._mapSize.width;
    },
    _setMapWidth: function (width) {
        this._mapSize.width = width;
    },
    _getMapHeight: function () {
        return this._mapSize.height;
    },
    _setMapHeight: function (height) {
        this._mapSize.height = height;
    },
    getTileSize:function () {
        return cc.size(this._tileSize.width, this._tileSize.height);
    },
    setTileSize:function (value) {
        this._tileSize.width = value.width;
        this._tileSize.height = value.height;
    },
    _getTileWidth: function () {
        return this._tileSize.width;
    },
    _setTileWidth: function (width) {
        this._tileSize.width = width;
    },
    _getTileHeight: function () {
        return this._tileSize.height;
    },
    _setTileHeight: function (height) {
        this._tileSize.height = height;
    },
    getLayers:function () {
        return this._layers;
    },
    setLayers:function (value) {
        this._layers.push(value);
    },
    getTilesets:function () {
        return this._tilesets;
    },
    setTilesets:function (value) {
        this._tilesets.push(value);
    },
    getObjectGroups:function () {
        return this._objectGroups;
    },
    setObjectGroups:function (value) {
        this._objectGroups.push(value);
    },
    getParentElement:function () {
        return this.parentElement;
    },
    setParentElement:function (value) {
        this.parentElement = value;
    },
    getParentGID:function () {
        return this.parentGID;
    },
    setParentGID:function (value) {
        this.parentGID = value;
    },
    getLayerAttribs:function () {
        return this.layerAttrs;
    },
    setLayerAttribs:function (value) {
        this.layerAttrs = value;
    },
    getStoringCharacters:function () {
        return this.storingCharacters;
    },
    setStoringCharacters:function (value) {
        this.storingCharacters = value;
    },
    getProperties:function () {
        return this.properties;
    },
    setProperties:function (value) {
        this.properties = value;
    },
    initWithTMXFile:function (tmxFile) {
        this._internalInit(tmxFile, null);
        return this.parseXMLFile(tmxFile);
    },
    initWithXML:function (tmxString, resourcePath) {
        this._internalInit(null, resourcePath);
        return this.parseXMLString(tmxString);
    },
    parseXMLFile:function (tmxFile, isXmlString) {
        isXmlString = isXmlString || false;
        var xmlStr = isXmlString ? tmxFile : cc.loader.getRes(tmxFile);
        if(!xmlStr) throw new Error("Please load the resource first : " + tmxFile);
        var mapXML = this._parseXML(xmlStr);
        var i, j;
        var map = mapXML.documentElement;
        var version = map.getAttribute('version');
        var orientationStr = map.getAttribute('orientation');
        if (map.nodeName === "map") {
            if (version !== "1.0" && version !== null)
                cc.log("cocos2d: TMXFormat: Unsupported TMX version:" + version);
            if (orientationStr === "orthogonal")
                this.orientation = cc.TMX_ORIENTATION_ORTHO;
            else if (orientationStr === "isometric")
                this.orientation = cc.TMX_ORIENTATION_ISO;
            else if (orientationStr === "hexagonal")
                this.orientation = cc.TMX_ORIENTATION_HEX;
            else if (orientationStr !== null)
                cc.log("cocos2d: TMXFomat: Unsupported orientation:" + orientationStr);
            var mapSize = cc.size(0, 0);
            mapSize.width = parseFloat(map.getAttribute('width'));
            mapSize.height = parseFloat(map.getAttribute('height'));
            this.setMapSize(mapSize);
            mapSize = cc.size(0, 0);
            mapSize.width = parseFloat(map.getAttribute('tilewidth'));
            mapSize.height = parseFloat(map.getAttribute('tileheight'));
            this.setTileSize(mapSize);
            var propertyArr = map.querySelectorAll("map > properties >  property");
            if (propertyArr) {
                var aPropertyDict = {};
                for (i = 0; i < propertyArr.length; i++) {
                    aPropertyDict[propertyArr[i].getAttribute('name')] = propertyArr[i].getAttribute('value');
                }
                this.properties = aPropertyDict;
            }
        }
        var tilesets = map.getElementsByTagName('tileset');
        if (map.nodeName !== "map") {
            tilesets = [];
            tilesets.push(map);
        }
        for (i = 0; i < tilesets.length; i++) {
            var selTileset = tilesets[i];
            var tsxName = selTileset.getAttribute('source');
            if (tsxName) {
                var tsxPath = isXmlString ? cc.path.join(this._resources, tsxName) : cc.path.changeBasename(tmxFile, tsxName);
                this.parseXMLFile(tsxPath);
            } else {
                var tileset = new cc.TMXTilesetInfo();
                tileset.name = selTileset.getAttribute('name') || "";
                tileset.firstGid = parseInt(selTileset.getAttribute('firstgid')) || 0;
                tileset.spacing = parseInt(selTileset.getAttribute('spacing')) || 0;
                tileset.margin = parseInt(selTileset.getAttribute('margin')) || 0;
                var tilesetSize = cc.size(0, 0);
                tilesetSize.width = parseFloat(selTileset.getAttribute('tilewidth'));
                tilesetSize.height = parseFloat(selTileset.getAttribute('tileheight'));
                tileset._tileSize = tilesetSize;
                var image = selTileset.getElementsByTagName('image')[0];
                var imagename = image.getAttribute('source');
                var num = -1;
                if(this.tmxFileName)
                    num  = this.tmxFileName.lastIndexOf("/");
                if (num !== -1) {
                    var dir = this.tmxFileName.substr(0, num + 1);
                    tileset.sourceImage = dir + imagename;
                } else {
                    tileset.sourceImage = this._resources + (this._resources ? "/" : "") + imagename;
                }
                this.setTilesets(tileset);
                var tiles = selTileset.getElementsByTagName('tile');
                if (tiles) {
                    for (var tIdx = 0; tIdx < tiles.length; tIdx++) {
                        var t = tiles[tIdx];
                        this.parentGID = parseInt(tileset.firstGid) + parseInt(t.getAttribute('id') || 0);
                        var tp = t.querySelectorAll("properties > property");
                        if (tp) {
                            var dict = {};
                            for (j = 0; j < tp.length; j++) {
                                var name = tp[j].getAttribute('name');
                                dict[name] = tp[j].getAttribute('value');
                            }
                            this._tileProperties[this.parentGID] = dict;
                        }
                    }
                }
            }
        }
        var layers = map.getElementsByTagName('layer');
        if (layers) {
            for (i = 0; i < layers.length; i++) {
                var selLayer = layers[i];
                var data = selLayer.getElementsByTagName('data')[0];
                var layer = new cc.TMXLayerInfo();
                layer.name = selLayer.getAttribute('name');
                var layerSize = cc.size(0, 0);
                layerSize.width = parseFloat(selLayer.getAttribute('width'));
                layerSize.height = parseFloat(selLayer.getAttribute('height'));
                layer._layerSize = layerSize;
                var visible = selLayer.getAttribute('visible');
                layer.visible = !(visible == "0");
                var opacity = selLayer.getAttribute('opacity') || 1;
                if (opacity)
                    layer._opacity = parseInt(255 * parseFloat(opacity));
                else
                    layer._opacity = 255;
                layer.offset = cc.p(parseFloat(selLayer.getAttribute('x')) || 0, parseFloat(selLayer.getAttribute('y')) || 0);
                var nodeValue = '';
                for (j = 0; j < data.childNodes.length; j++) {
                    nodeValue += data.childNodes[j].nodeValue
                }
                nodeValue = nodeValue.trim();
                var compression = data.getAttribute('compression');
                var encoding = data.getAttribute('encoding');
                if(compression && compression !== "gzip" && compression !== "zlib"){
                    cc.log("cc.TMXMapInfo.parseXMLFile(): unsupported compression method");
                    return null;
                }
                var tiles;
                switch (compression) {
                    case 'gzip':
                        tiles = cc.unzipBase64AsArray(nodeValue, 4);
                        break;
                    case 'zlib':
                        var inflator = new Zlib.Inflate(cc.Codec.Base64.decodeAsArray(nodeValue, 1));
                        tiles = cc.uint8ArrayToUint32Array(inflator.decompress());
                        break;
                    case null:
                    case '':
                        if (encoding === "base64")
                            tiles = cc.Codec.Base64.decodeAsArray(nodeValue, 4);
                        else if (encoding === "csv") {
                            tiles = [];
                            var csvTiles = nodeValue.split(',');
                            for (var csvIdx = 0; csvIdx < csvTiles.length; csvIdx++)
                                tiles.push(parseInt(csvTiles[csvIdx]));
                        } else {
                            var selDataTiles = data.getElementsByTagName("tile");
                            tiles = [];
                            for (var xmlIdx = 0; xmlIdx < selDataTiles.length; xmlIdx++)
                                tiles.push(parseInt(selDataTiles[xmlIdx].getAttribute("gid")));
                        }
                        break;
                    default:
                        if(this.layerAttrs === cc.TMXLayerInfo.ATTRIB_NONE)
                            cc.log("cc.TMXMapInfo.parseXMLFile(): Only base64 and/or gzip/zlib maps are supported");
                        break;
                }
                if (tiles) {
                    layer._tiles = new Uint32Array(tiles);
                }
                var layerProps = selLayer.querySelectorAll("properties > property");
                if (layerProps) {
                    var layerProp = {};
                    for (j = 0; j < layerProps.length; j++) {
                        layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value');
                    }
                    layer.properties = layerProp;
                }
                this.setLayers(layer);
            }
        }
        var objectGroups = map.getElementsByTagName('objectgroup');
        if (objectGroups) {
            for (i = 0; i < objectGroups.length; i++) {
                var selGroup = objectGroups[i];
                var objectGroup = new cc.TMXObjectGroup();
                objectGroup.groupName = selGroup.getAttribute('name');
                objectGroup.setPositionOffset(cc.p(parseFloat(selGroup.getAttribute('x')) * this.getTileSize().width || 0,
                    parseFloat(selGroup.getAttribute('y')) * this.getTileSize().height || 0));
                var groupProps = selGroup.querySelectorAll("objectgroup > properties > property");
                if (groupProps) {
                    for (j = 0; j < groupProps.length; j++) {
                        var groupProp = {};
                        groupProp[groupProps[j].getAttribute('name')] = groupProps[j].getAttribute('value');
                        objectGroup.properties = groupProp;
                    }
                }
                var objects = selGroup.querySelectorAll('object');
                var getContentScaleFactor = cc.director.getContentScaleFactor();
                if (objects) {
                    for (j = 0; j < objects.length; j++) {
                        var selObj = objects[j];
                        var objectProp = {};
                        objectProp["name"] = selObj.getAttribute('name') || "";
                        objectProp["type"] = selObj.getAttribute('type') || "";
                        objectProp["width"] = parseInt(selObj.getAttribute('width')) || 0;
                        objectProp["height"] = parseInt(selObj.getAttribute('height')) || 0;
                        objectProp["x"] = (((selObj.getAttribute('x') || 0) | 0) + objectGroup.getPositionOffset().x) / getContentScaleFactor;
                        var y = ((selObj.getAttribute('y') || 0) | 0) + objectGroup.getPositionOffset().y / getContentScaleFactor;
                        objectProp["y"] = (parseInt(this.getMapSize().height * this.getTileSize().height) - y - objectProp["height"]) / cc.director.getContentScaleFactor();
                        objectProp["rotation"] = parseInt(selObj.getAttribute('rotation')) || 0;
                        var docObjProps = selObj.querySelectorAll("properties > property");
                        if (docObjProps) {
                            for (var k = 0; k < docObjProps.length; k++)
                                objectProp[docObjProps[k].getAttribute('name')] = docObjProps[k].getAttribute('value');
                        }
                        var polygonProps = selObj.querySelectorAll("polygon");
                        if(polygonProps && polygonProps.length > 0) {
                            var selPgPointStr = polygonProps[0].getAttribute('points');
                            if(selPgPointStr)
                                objectProp["points"] = this._parsePointsString(selPgPointStr);
                        }
                        var polylineProps = selObj.querySelectorAll("polyline");
                        if(polylineProps && polylineProps.length > 0) {
                            var selPlPointStr = polylineProps[0].getAttribute('points');
                            if(selPlPointStr)
                                objectProp["polylinePoints"] = this._parsePointsString(selPlPointStr);
                        }
                        objectGroup.setObjects(objectProp);
                    }
                }
                this.setObjectGroups(objectGroup);
            }
        }
        return map;
    },
    _parsePointsString:function(pointsString){
         if(!pointsString)
            return null;
        var points = [];
        var pointsStr = pointsString.split(' ');
        for(var i = 0; i < pointsStr.length; i++){
            var selPointStr = pointsStr[i].split(',');
            points.push({'x':selPointStr[0], 'y':selPointStr[1]});
        }
        return points;
    },
    parseXMLString:function (xmlString) {
        return this.parseXMLFile(xmlString, true);
    },
    getTileProperties:function () {
        return this._tileProperties;
    },
    setTileProperties:function (tileProperties) {
        this._tileProperties.push(tileProperties);
    },
    getCurrentString:function () {
        return this.currentString;
    },
    setCurrentString:function (currentString) {
        this.currentString = currentString;
    },
    getTMXFileName:function () {
        return this.tmxFileName;
    },
    setTMXFileName:function (fileName) {
        this.tmxFileName = fileName;
    },
    _internalInit:function (tmxFileName, resourcePath) {
        this._tilesets.length = 0;
        this._layers.length = 0;
        this.tmxFileName = tmxFileName;
        if (resourcePath)
            this._resources = resourcePath;
        this._objectGroups.length = 0;
        this.properties.length = 0;
        this._tileProperties.length = 0;
        this.currentString = "";
        this.storingCharacters = false;
        this.layerAttrs = cc.TMXLayerInfo.ATTRIB_NONE;
        this.parentElement = cc.TMX_PROPERTY_NONE;
        this._currentFirstGID = 0;
    }
});
var _p = cc.TMXMapInfo.prototype;
_p.mapWidth;
cc.defineGetterSetter(_p, "mapWidth", _p._getMapWidth, _p._setMapWidth);
_p.mapHeight;
cc.defineGetterSetter(_p, "mapHeight", _p._getMapHeight, _p._setMapHeight);
_p.tileWidth;
cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth);
_p.tileHeight;
cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight);
cc.TMXMapInfo.create = function (tmxFile, resourcePath) {
    return new cc.TMXMapInfo(tmxFile, resourcePath);
};
cc.loader.register(["tmx", "tsx"], cc._txtLoader);
cc.TMXLayerInfo.ATTRIB_NONE = 1 << 0;
cc.TMXLayerInfo.ATTRIB_BASE64 = 1 << 1;
cc.TMXLayerInfo.ATTRIB_GZIP = 1 << 2;
cc.TMXLayerInfo.ATTRIB_ZLIB = 1 << 3;
cc.TMXObjectGroup = cc.Class.extend({
    properties: null,
    groupName: "",
    _positionOffset: null,
    _objects: null,
    ctor:function () {
        this.groupName = "";
        this._positionOffset = cc.p(0,0);
        this.properties = [];
        this._objects = [];
    },
    getPositionOffset:function () {
        return cc.p(this._positionOffset);
    },
    setPositionOffset:function (offset) {
        this._positionOffset.x = offset.x;
        this._positionOffset.y = offset.y;
    },
    getProperties:function () {
        return this.properties;
    },
    setProperties:function (Var) {
        this.properties.push(Var);
    },
    getGroupName:function () {
        return this.groupName.toString();
    },
    setGroupName:function (groupName) {
        this.groupName = groupName;
    },
    propertyNamed:function (propertyName) {
        return this.properties[propertyName];
    },
    objectNamed:function (objectName) {
        return this.getObject(objectName);
    },
    getObject: function(objectName){
        if (this._objects && this._objects.length > 0) {
            var locObjects = this._objects;
            for (var i = 0, len = locObjects.length; i < len; i++) {
                var name = locObjects[i]["name"];
                if (name && name === objectName)
                    return locObjects[i];
            }
        }
        return null;
    },
    getObjects:function () {
        return this._objects;
    },
    setObjects:function (objects) {
        this._objects.push(objects);
    }
});
cc.TMXLayer = cc.SpriteBatchNode.extend({
    tiles: null,
    tileset: null,
    layerOrientation: null,
    properties: null,
    layerName: "",
    _textures: null,
    _texGrids: null,
    _spriteTiles: null,
    _layerSize: null,
    _mapTileSize: null,
    _opacity: 255,
    _minGID: null,
    _maxGID: null,
    _vertexZvalue: null,
    _useAutomaticVertexZ: null,
    _reusedTile: null,
    _atlasIndexArray: null,
    _contentScaleFactor: null,
    _className:"TMXLayer",
    ctor:function (tilesetInfo, layerInfo, mapInfo) {
        cc.SpriteBatchNode.prototype.ctor.call(this);
        this._descendants = [];
        this._layerSize = cc.size(0, 0);
        this._mapTileSize = cc.size(0, 0);
        this._spriteTiles = {};
        if(mapInfo !== undefined)
            this.initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.TMXLayer.CanvasRenderCmd(this);
        else
            return new cc.TMXLayer.WebGLRenderCmd(this);
    },
    _fillTextureGrids: function (tileset, texId) {
        var tex = this._textures[texId];
        if (!tex.isLoaded()) {
            tex.addEventListener("load", function () {
                this._fillTextureGrids(tileset, texId);
            }, this);
            return;
        }
        if (!tileset.imageSize.width || !tileset.imageSize.height) {
            tileset.imageSize.width = tex.width;
            tileset.imageSize.height = tex.height;
        }
        var tw = tileset._tileSize.width,
            th = tileset._tileSize.height,
            imageW = tex._contentSize.width,
            imageH = tex._contentSize.height,
            spacing = tileset.spacing,
            margin = tileset.margin,
            cols = Math.floor((imageW - margin*2 + spacing) / (tw + spacing)),
            rows = Math.floor((imageH - margin*2 + spacing) / (th + spacing)),
            count = rows * cols,
            gid = tileset.firstGid,
            maxGid = tileset.firstGid + count,
            grids = this._texGrids,
            grid = null,
            override = grids[gid] ? true : false,
            t, l, r, b;
        for (; gid < maxGid; ++gid) {
            if (override && !grids[gid]) {
                override = false;
            }
            if (!override && grids[gid]) {
                break;
            }
            grid = {
                texId: texId,
                x: 0, y: 0, width: tw, height: th,
                t: 0, l: 0, r: 0, b: 0
            };
            tileset.rectForGID(gid, grid);
            grid.t = grid.y / imageH;
            grid.l = grid.x / imageW;
            grid.r = (grid.x + grid.width) / imageW;
            grid.b = (grid.y + grid.height) / imageH;
            grids[gid] = grid;
        }
    },
    initWithTilesetInfo:function (tilesetInfo, layerInfo, mapInfo) {
        var size = layerInfo._layerSize;
        var totalNumberOfTiles = parseInt(size.width * size.height);
        this.layerName = layerInfo.name;
        this.tiles = layerInfo._tiles;
        this.properties = layerInfo.properties;
        this._layerSize = size;
        this._minGID = layerInfo._minGID;
        this._maxGID = layerInfo._maxGID;
        this._opacity = layerInfo._opacity;
        this.tileset = tilesetInfo;
        this.layerOrientation = mapInfo.orientation;
        this._mapTileSize = mapInfo.getTileSize();
        var tilesets = mapInfo._tilesets;
        if (tilesets) {
            this._textures = [];
            this._texGrids = [];
            var i, len = tilesets.length, tileset, tex;
            for (i = 0; i < len; ++i) {
                tileset = tilesets[i];
                tex = cc.textureCache.addImage(tileset.sourceImage);
                this._textures.push(tex);
                this._fillTextureGrids(tileset, i);
                if (tileset === tilesetInfo) {
                    this._texture = tex;
                }
            }
        }
        var offset = this._calculateLayerOffset(layerInfo.offset);
        this.setPosition(cc.pointPixelsToPoints(offset));
        this._parseInternalProperties();
        this.setContentSize(cc.sizePixelsToPoints(cc.size(this._layerSize.width * this._mapTileSize.width,
            this._layerSize.height * this._mapTileSize.height)));
        this._useAutomaticVertexZ = false;
        this._vertexZvalue = 0;
        return true;
    },
    getLayerSize:function () {
        return cc.size(this._layerSize.width, this._layerSize.height);
    },
    setLayerSize:function (Var) {
        this._layerSize.width = Var.width;
        this._layerSize.height = Var.height;
    },
    _getLayerWidth: function () {
        return this._layerSize.width;
    },
    _setLayerWidth: function (width) {
        this._layerSize.width = width;
    },
    _getLayerHeight: function () {
        return this._layerSize.height;
    },
    _setLayerHeight: function (height) {
        this._layerSize.height = height;
    },
    getMapTileSize:function () {
        return cc.size(this._mapTileSize.width,this._mapTileSize.height);
    },
    setMapTileSize:function (Var) {
        this._mapTileSize.width = Var.width;
        this._mapTileSize.height = Var.height;
    },
    _getTileWidth: function () {
        return this._mapTileSize.width;
    },
    _setTileWidth: function (width) {
        this._mapTileSize.width = width;
    },
    _getTileHeight: function () {
        return this._mapTileSize.height;
    },
    _setTileHeight: function (height) {
        this._mapTileSize.height = height;
    },
    getTiles:function () {
        return this.tiles;
    },
    setTiles:function (Var) {
        this.tiles = Var;
    },
    getTileset:function () {
        return this.tileset;
    },
    setTileset:function (Var) {
        this.tileset = Var;
    },
    getLayerOrientation:function () {
        return this.layerOrientation;
    },
    setLayerOrientation:function (Var) {
        this.layerOrientation = Var;
    },
    getProperties:function () {
        return this.properties;
    },
    setProperties:function (Var) {
        this.properties = Var;
    },
    getProperty:function (propertyName) {
        return this.properties[propertyName];
    },
    getLayerName:function () {
        return this.layerName;
    },
    setLayerName:function (layerName) {
        this.layerName = layerName;
    },
    releaseMap:function () {
        this._spriteTiles = {};
    },
    getTileAt: function (pos, y) {
        if (pos === undefined) {
            throw new Error("cc.TMXLayer.getTileAt(): pos should be non-null");
        }
        var x = pos;
        if (y === undefined) {
            x = pos.x;
            y = pos.y;
        }
        if (x >= this._layerSize.width || y >= this._layerSize.height || x < 0 || y < 0) {
            throw new Error("cc.TMXLayer.getTileAt(): invalid position");
        }
        if (!this.tiles) {
            cc.log("cc.TMXLayer.getTileAt(): TMXLayer: the tiles map has been released");
            return null;
        }
        var tile = null, gid = this.getTileGIDAt(x, y);
        if (gid === 0) {
            return tile;
        }
        var z = 0 | (x + y * this._layerSize.width);
        tile = this._spriteTiles[z];
        if (!tile) {
            var rect = this._texGrids[gid];
            var tex = this._textures[rect.texId];
            rect = cc.rectPixelsToPoints(rect);
            tile = new cc.Sprite(tex, rect);
            tile.setPosition(this.getPositionAt(x, y));
            var vertexZ = this._vertexZForPos(x, y);
            tile.setVertexZ(vertexZ);
            tile.setAnchorPoint(0, 0);
            tile.setOpacity(this._opacity);
            this.addChild(tile, vertexZ, z);
        }
        return tile;
    },
    getTileGIDAt:function (pos, y) {
        if (pos === undefined) {
            throw new Error("cc.TMXLayer.getTileGIDAt(): pos should be non-null");
        }
        var x = pos;
        if (y === undefined) {
            x = pos.x;
            y = pos.y;
        }
        if (x >= this._layerSize.width || y >= this._layerSize.height || x < 0 || y < 0) {
            throw new Error("cc.TMXLayer.getTileGIDAt(): invalid position");
        }
        if (!this.tiles) {
            cc.log("cc.TMXLayer.getTileGIDAt(): TMXLayer: the tiles map has been released");
            return null;
        }
        var idx = 0 | (x + y * this._layerSize.width);
        var tile = this.tiles[idx];
        return (tile & cc.TMX_TILE_FLIPPED_MASK) >>> 0;
    },
    setTileGID: function(gid, posOrX, flagsOrY, flags) {
        if (posOrX === undefined) {
            throw new Error("cc.TMXLayer.setTileGID(): pos should be non-null");
        }
        var pos;
        if (flags !== undefined) {
            pos = cc.p(posOrX, flagsOrY);
        } else {
            pos = posOrX;
            flags = flagsOrY;
        }
        if (pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) {
            throw new Error("cc.TMXLayer.setTileGID(): invalid position");
        }
        if (!this.tiles) {
            cc.log("cc.TMXLayer.setTileGID(): TMXLayer: the tiles map has been released");
            return;
        }
        if (gid !== 0 && gid < this.tileset.firstGid) {
            cc.log( "cc.TMXLayer.setTileGID(): invalid gid:" + gid);
            return;
        }
        flags = flags || 0;
        var currentFlags = this.getTileFlagsAt(pos);
        var currentGID = this.getTileGIDAt(pos);
        if (currentGID !== gid || currentFlags !== flags) {
            var gidAndFlags = (gid | flags) >>> 0;
            if (gid === 0)
                this.removeTileAt(pos);
            else if (currentGID === 0)
                this._updateTileForGID(gidAndFlags, pos);
            else {
                var z = pos.x + pos.y * this._layerSize.width;
                var sprite = this.getChildByTag(z);
                if (sprite) {
                    var rect = this._texGrids[gid];
                    var tex = this._textures[rect.texId];
                    rect = cc.rectPixelsToPoints(rect);
                    sprite.setTexture(tex);
                    sprite.setTextureRect(rect, false);
                    if (flags != null)
                        this._setupTileSprite(sprite, pos, gidAndFlags);
                    this.tiles[z] = gidAndFlags;
                } else {
                    this._updateTileForGID(gidAndFlags, pos);
                }
            }
        }
    },
    addChild: function (child, localZOrder, tag) {
        cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
        if (tag !== undefined) {
            this._spriteTiles[tag] = child;
            child._vertexZ = this._vertexZ + cc.renderer.assignedZStep * tag / this.tiles.length;
        }
    },
    removeChild: function (child, cleanup) {
        if (this._spriteTiles[child.tag]) {
            this._spriteTiles[child.tag] = null;
        }
        cc.Node.prototype.removeChild.call(this, child, cleanup);
    },
    getTileFlagsAt:function (pos, y) {
        if(!pos)
            throw new Error("cc.TMXLayer.getTileFlagsAt(): pos should be non-null");
        if(y !== undefined)
            pos = cc.p(pos, y);
        if(pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0)
            throw new Error("cc.TMXLayer.getTileFlagsAt(): invalid position");
        if(!this.tiles){
            cc.log("cc.TMXLayer.getTileFlagsAt(): TMXLayer: the tiles map has been released");
            return null;
        }
        var idx = 0 | (pos.x + pos.y * this._layerSize.width);
        var tile = this.tiles[idx];
        return (tile & cc.TMX_TILE_FLIPPED_ALL) >>> 0;
    },
    removeTileAt:function (pos, y) {
        if (!pos) {
            throw new Error("cc.TMXLayer.removeTileAt(): pos should be non-null");
        }
        if (y !== undefined) {
            pos = cc.p(pos, y);
        }
        if (pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) {
            throw new Error("cc.TMXLayer.removeTileAt(): invalid position");
        }
        if (!this.tiles) {
            cc.log("cc.TMXLayer.removeTileAt(): TMXLayer: the tiles map has been released");
            return;
        }
        var gid = this.getTileGIDAt(pos);
        if (gid !== 0) {
            var z = 0 | (pos.x + pos.y * this._layerSize.width);
            this.tiles[z] = 0;
            var sprite = this._spriteTiles[z];
            if (sprite) {
                this.removeChild(sprite, true);
            }
        }
    },
    getPositionAt:function (pos, y) {
        if (y !== undefined)
            pos = cc.p(pos, y);
        var ret = cc.p(0,0);
        switch (this.layerOrientation) {
            case cc.TMX_ORIENTATION_ORTHO:
                ret = this._positionForOrthoAt(pos);
                break;
            case cc.TMX_ORIENTATION_ISO:
                ret = this._positionForIsoAt(pos);
                break;
            case cc.TMX_ORIENTATION_HEX:
                ret = this._positionForHexAt(pos);
                break;
        }
        return cc.pointPixelsToPoints(ret);
    },
    _positionForIsoAt:function (pos) {
        return cc.p(this._mapTileSize.width / 2 * ( this._layerSize.width + pos.x - pos.y - 1),
            this._mapTileSize.height / 2 * (( this._layerSize.height * 2 - pos.x - pos.y) - 2));
    },
    _positionForOrthoAt:function (pos) {
        return cc.p(pos.x * this._mapTileSize.width,
            (this._layerSize.height - pos.y - 1) * this._mapTileSize.height);
    },
    _positionForHexAt:function (pos) {
        var diffY = (pos.x % 2 === 1) ? (-this._mapTileSize.height / 2) : 0;
        return cc.p(pos.x * this._mapTileSize.width * 3 / 4,
            (this._layerSize.height - pos.y - 1) * this._mapTileSize.height + diffY);
    },
    _calculateLayerOffset:function (pos) {
        var ret = cc.p(0,0);
        switch (this.layerOrientation) {
            case cc.TMX_ORIENTATION_ORTHO:
                ret = cc.p(pos.x * this._mapTileSize.width, -pos.y * this._mapTileSize.height);
                break;
            case cc.TMX_ORIENTATION_ISO:
                ret = cc.p((this._mapTileSize.width / 2) * (pos.x - pos.y),
                    (this._mapTileSize.height / 2 ) * (-pos.x - pos.y));
                break;
            case cc.TMX_ORIENTATION_HEX:
                if(pos.x !== 0 || pos.y !== 0)
                    cc.log("offset for hexagonal map not implemented yet");
                break;
        }
        return ret;
    },
    _updateTileForGID:function (gid, pos) {
        if (!this._texGrids[gid]) {
            return;
        }
        var idx = 0 | (pos.x + pos.y * this._layerSize.width);
        if (idx < this.tiles.length) {
            this.tiles[idx] = gid;
        }
    },
    _parseInternalProperties:function () {
        var vertexz = this.getProperty("cc_vertexz");
        if (vertexz) {
            if (vertexz === "automatic") {
                this._useAutomaticVertexZ = true;
                var alphaFuncVal = this.getProperty("cc_alpha_func");
                var alphaFuncValue = 0;
                if (alphaFuncVal)
                    alphaFuncValue = parseFloat(alphaFuncVal);
                if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
                    this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
                    this.shaderProgram.use();
                    this.shaderProgram.setUniformLocationWith1f(cc.UNIFORM_ALPHA_TEST_VALUE_S, alphaFuncValue);
                }
            } else
                this._vertexZvalue = parseInt(vertexz, 10);
        }
    },
    _setupTileSprite:function (sprite, pos, gid) {
        var z = pos.x + pos.y * this._layerSize.width;
        var posInPixel = this.getPositionAt(pos);
        sprite.setPosition(posInPixel);
        sprite.setVertexZ(this._vertexZForPos(pos));
        sprite.setAnchorPoint(0, 0);
        sprite.setOpacity(this._opacity);
        sprite.setFlippedX(false);
        sprite.setFlippedY(false);
        sprite.setRotation(0.0);
        if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) {
            sprite.setAnchorPoint(0.5, 0.5);
            sprite.setPosition(posInPixel.x + sprite.width/2, posInPixel.y + sprite.height/2);
            var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0;
            if (flag === cc.TMX_TILE_HORIZONTAL_FLAG)
                sprite.setRotation(90);
            else if (flag === cc.TMX_TILE_VERTICAL_FLAG)
                sprite.setRotation(270);
            else if (flag === (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) {
                sprite.setRotation(90);
                sprite.setFlippedX(true);
            } else {
                sprite.setRotation(270);
                sprite.setFlippedX(true);
            }
        } else {
            if ((gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) {
                sprite.setFlippedX(true);
            }
            if ((gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0) {
                sprite.setFlippedY(true);
            }
        }
    },
    _vertexZForPos:function (x, y) {
        if (y === undefined) {
            y = x.y;
            x = x.x;
        }
        var ret = 0;
        var maxVal = 0;
        if (this._useAutomaticVertexZ) {
            switch (this.layerOrientation) {
                case cc.TMX_ORIENTATION_ISO:
                    maxVal = this._layerSize.width + this._layerSize.height;
                    ret = -(maxVal - (x + y));
                    break;
                case cc.TMX_ORIENTATION_ORTHO:
                    ret = -(this._layerSize.height - y);
                    break;
                case cc.TMX_ORIENTATION_HEX:
                    cc.log("TMX Hexa zOrder not supported");
                    break;
                default:
                    cc.log("TMX invalid value");
                    break;
            }
        } else {
            ret = this._vertexZvalue;
        }
        return ret;
    }
});
var _p = cc.TMXLayer.prototype;
_p.layerWidth;
cc.defineGetterSetter(_p, "layerWidth", _p._getLayerWidth, _p._setLayerWidth);
_p.layerHeight;
cc.defineGetterSetter(_p, "layerHeight", _p._getLayerHeight, _p._setLayerHeight);
_p.tileWidth;
cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth);
_p.tileHeight;
cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight);
cc.TMXLayer.create = function (tilesetInfo, layerInfo, mapInfo) {
    return new cc.TMXLayer(tilesetInfo, layerInfo, mapInfo);
};
(function(){
    cc.TMXLayer.CanvasRenderCmd = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = true;
    };
    var proto = cc.TMXLayer.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.TMXLayer.CanvasRenderCmd;
    proto.visit = function (parentCmd) {
        var node = this._node, renderer = cc.renderer;
        parentCmd = parentCmd || this.getParentRenderCmd();
        if (parentCmd) {
            this._curLevel = parentCmd._curLevel + 1;
        }
        if (!node._visible)
            return;
        if (isNaN(node._customZ)) {
            node._vertexZ = renderer.assignedZ;
            renderer.assignedZ += renderer.assignedZStep;
        }
        this._syncStatus(parentCmd);
        var children = node._children, child,
            spTiles = node._spriteTiles,
            i, len = children.length;
        if (len > 0) {
            node.sortAllChildren();
            for (i = 0; i < len; i++) {
                child = children[i];
                if (child._localZOrder < 0) {
                    child._renderCmd.visit(this);
                }
                else {
                    break;
                }
            }
            renderer.pushRenderCommand(this);
            for (; i < len; i++) {
                child = children[i];
                if (child._localZOrder === 0 && spTiles[child.tag]) {
                    if (isNaN(child._customZ)) {
                        child._vertexZ = renderer.assignedZ;
                        renderer.assignedZ += renderer.assignedZStep;
                    }
                    child._renderCmd.updateStatus();
                    continue;
                }
                child._renderCmd.visit(this);
            }
        } else {
            renderer.pushRenderCommand(this);
        }
        this._dirtyFlag = 0;
    };
    proto.rendering = function (ctx, scaleX, scaleY) {
        var node = this._node, hasRotation = (node._rotationX || node._rotationY),
            layerOrientation = node.layerOrientation,
            tiles = node.tiles,
            alpha = node._opacity / 255;
        if (!tiles || alpha <= 0) {
            return;
        }
        var maptw = node._mapTileSize.width,
            mapth = node._mapTileSize.height,
            tilew = node.tileset._tileSize.width / cc.director._contentScaleFactor,
            tileh = node.tileset._tileSize.height / cc.director._contentScaleFactor,
            extw = tilew - maptw,
            exth = tileh - mapth,
            winw = cc.winSize.width,
            winh = cc.winSize.height,
            rows = node._layerSize.height,
            cols = node._layerSize.width,
            grids = node._texGrids,
            spTiles = node._spriteTiles,
            wt = this._worldTransform,
            ox = -node._contentSize.width * node._anchorPoint.x,
            oy = -node._contentSize.height * node._anchorPoint.y,
            a = wt.a, b = wt.b, c = wt.c, d = wt.d,
            mapx = ox * a + oy * c + wt.tx,
            mapy = ox * b + oy * d + wt.ty;
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        var startCol = 0, startRow = 0,
            maxCol = cols, maxRow = rows;
        if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ORTHO) {
            startCol = Math.floor(-(mapx - extw * a) / (maptw * a));
            startRow = Math.floor((mapy - exth * d + mapth * rows * d - winh) / (mapth * d));
            maxCol = Math.ceil((winw - mapx + extw * a) / (maptw * a));
            maxRow = rows - Math.floor(-(mapy + exth * d) / (mapth * d));
            if (startCol < 0) startCol = 0;
            if (startRow < 0) startRow = 0;
            if (maxCol > cols) maxCol = cols;
            if (maxRow > rows) maxRow = rows;
        }
        var i, row, col, colOffset = startRow * cols, z,
            gid, grid, tex, cmd,
            mask = cc.TMX_TILE_FLIPPED_MASK,
            top, left, bottom, right, dw = tilew, dh = tileh ,
            w = tilew * a, h = tileh * d, gt, gl, gb, gr,
            flippedX = false, flippedY = false;
        z = colOffset + startCol;
        for (i in spTiles) {
            if (i < z && spTiles[i]) {
                cmd = spTiles[i]._renderCmd;
                if (spTiles[i]._localZOrder === 0 && !!cmd.rendering) {
                    cmd.rendering(ctx, scaleX, scaleY);
                }
            }
            else if (i >= z) {
                break;
            }
        }
        wrapper.setTransform(wt, scaleX, scaleY);
        wrapper.setGlobalAlpha(alpha);
        for (row = startRow; row < maxRow; ++row) {
            for (col = startCol; col < maxCol; ++col) {
                z = colOffset + col;
                if (spTiles[z]) {
                    cmd = spTiles[z]._renderCmd;
                    if (spTiles[z]._localZOrder === 0 && !!cmd.rendering) {
                        cmd.rendering(ctx, scaleX, scaleY);
                        wrapper.setTransform(wt, scaleX, scaleY);
                        wrapper.setGlobalAlpha(alpha);
                    }
                    continue;
                }
                gid = node.tiles[z];
                grid = grids[(gid & mask) >>> 0];
                if (!grid) {
                    continue;
                }
                tex = node._textures[grid.texId];
                if (!tex || !tex._htmlElementObj) {
                    continue;
                }
                switch (layerOrientation) {
                case cc.TMX_ORIENTATION_ORTHO:
                    left = col * maptw;
                    bottom = -(rows - row - 1) * mapth;
                    break;
                case cc.TMX_ORIENTATION_ISO:
                    left = maptw / 2 * ( cols + col - row - 1);
                    bottom = -mapth / 2 * ( rows * 2 - col - row - 2);
                    break;
                case cc.TMX_ORIENTATION_HEX:
                    left = col * maptw * 3 / 4;
                    bottom = -(rows - row - 1) * mapth + ((col % 2 === 1) ? (-mapth / 2) : 0);
                    break;
                }
                right = left + tilew;
                top = bottom - tileh;
                if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ISO) {
                    gb = -mapy + bottom*d;
                    if (gb < -winh-h) {
                        col += Math.floor((-winh - gb)*2/h) - 1;
                        continue;
                    }
                    gr = mapx + right*a;
                    if (gr < -w) {
                        col += Math.floor((-gr)*2/w) - 1;
                        continue;
                    }
                    gl = mapx + left*a;
                    gt = -mapy + top*d;
                    if (gl > winw || gt > 0) {
                        col = maxCol;
                        continue;
                    }
                }
                if (gid > cc.TMX_TILE_DIAGONAL_FLAG) {
                    flippedX = (gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0;
                    flippedY = (gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0;
                }
                if (flippedX) {
                    left = -right;
                    context.scale(-1, 1);
                }
                if (flippedY) {
                    top = -bottom;
                    context.scale(1, -1);
                }
                context.drawImage(tex._htmlElementObj,
                    grid.x, grid.y, grid.width, grid.height,
                    left, top, dw, dh);
                if (flippedX) {
                    context.scale(-1, 1);
                }
                if (flippedY) {
                    context.scale(1, -1);
                }
                cc.g_NumberOfDraws++;
            }
            colOffset += cols;
        }
        for (i in spTiles) {
            if (i > z && spTiles[i]) {
                cmd = spTiles[i]._renderCmd;
                if (spTiles[i]._localZOrder === 0 && !!cmd.rendering) {
                    cmd.rendering(ctx, scaleX, scaleY);
                }
            }
        }
    };
})();
(function(){
    cc.TMXLayer.WebGLRenderCmd = function(renderableObject){
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._vertices = [
            {x:0, y:0},
            {x:0, y:0},
            {x:0, y:0},
            {x:0, y:0}
        ];
        this._color = new Uint32Array(1);
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
        var radian = Math.PI * 90 / 180;
        this._sin90 = Math.sin(radian);
        this._cos90 = Math.cos(radian);
        radian = radian * 3;
        this._sin270 = Math.sin(radian);
        this._cos270 = Math.cos(radian);
    };
    var proto = cc.TMXLayer.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.TMXLayer.WebGLRenderCmd;
    proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
        var node = this._node, hasRotation = (node._rotationX || node._rotationY),
            layerOrientation = node.layerOrientation,
            tiles = node.tiles;
        if (!tiles) {
            return 0;
        }
        var scalex = cc.view._scaleX,
            scaley = cc.view._scaleY,
            maptw = node._mapTileSize.width,
            mapth = node._mapTileSize.height,
            tilew = node.tileset._tileSize.width / cc.director._contentScaleFactor,
            tileh = node.tileset._tileSize.height / cc.director._contentScaleFactor,
            extw = tilew - maptw,
            exth = tileh - mapth,
            winw = cc.winSize.width,
            winh = cc.winSize.height,
            rows = node._layerSize.height,
            cols = node._layerSize.width,
            grids = node._texGrids,
            spTiles = node._spriteTiles,
            wt = this._worldTransform,
            a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty,
            ox = -node._contentSize.width * node._anchorPoint.x,
            oy = -node._contentSize.height * node._anchorPoint.y,
            mapx = ox * a + oy * c + tx,
            mapy = ox * b + oy * d + ty;
        var opacity = node._opacity,
            cr = this._displayedColor.r,
            cg = this._displayedColor.g,
            cb = this._displayedColor.b;
        if (node._opacityModifyRGB) {
            var ca = opacity / 255;
            cr *= ca;
            cg *= ca;
            cb *= ca;
        }
        this._color[0] = ((opacity<<24) | (cb<<16) | (cg<<8) | cr);
        var startCol = 0, startRow = 0,
            maxCol = cols, maxRow = rows;
        if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ORTHO) {
            startCol = Math.floor(-(mapx - extw * a) / (maptw * a));
            startRow = Math.floor((mapy - exth * d + mapth * rows * d - winh) / (mapth * d));
            maxCol = Math.ceil((winw - mapx + extw * a) / (maptw * a));
            maxRow = rows - Math.floor(-(mapy + exth * d) / (mapth * d));
            if (startCol < 0) startCol = 0;
            if (startRow < 0) startRow = 0;
            if (maxCol > cols) maxCol = cols;
            if (maxRow > rows) maxRow = rows;
        }
        var row, col,
            offset = vertexDataOffset,
            colOffset = startRow * cols, z, gid, grid,
            mask = cc.TMX_TILE_FLIPPED_MASK,
            i, top, left, bottom, right,
            w = tilew * a, h = tileh * d, gt, gl, gb, gr,
            wa = a, wb = b, wc = c, wd = d, wtx = tx, wty = ty,
            flagged = false, flippedX = false, flippedY = false,
            vertices = this._vertices;
        for (row = startRow; row < maxRow; ++row) {
            for (col = startCol; col < maxCol; ++col) {
                if (offset + 24 > f32buffer.length) {
                    cc.renderer._increaseBatchingSize((offset - vertexDataOffset) / 6);
                    cc.renderer._batchRendering();
                    vertexDataOffset = 0;
                    offset = 0;
                }
                z = colOffset + col;
                if (spTiles[z]) {
                    continue;
                }
                gid = node.tiles[z];
                grid = grids[(gid & mask) >>> 0];
                if (!grid) {
                    continue;
                }
                switch (layerOrientation) {
                case cc.TMX_ORIENTATION_ORTHO:
                    left = col * maptw;
                    bottom = (rows - row - 1) * mapth;
                    z = node._vertexZ + cc.renderer.assignedZStep * z / tiles.length;
                    break;
                case cc.TMX_ORIENTATION_ISO:
                    left = maptw / 2 * ( cols + col - row - 1);
                    bottom = mapth / 2 * ( rows * 2 - col - row - 2);
                    z = node._vertexZ + cc.renderer.assignedZStep * (node.height - bottom) / node.height;
                    break;
                case cc.TMX_ORIENTATION_HEX:
                    left = col * maptw * 3 / 4;
                    bottom = (rows - row - 1) * mapth + ((col % 2 === 1) ? (-mapth / 2) : 0);
                    z = node._vertexZ + cc.renderer.assignedZStep * (node.height - bottom) / node.height;
                    break;
                }
                right = left + tilew;
                top = bottom + tileh;
                if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ISO) {
                    gb = mapy + bottom*d;
                    if (gb > winh+h) {
                        col += Math.floor((gb-winh)*2/h) - 1;
                        continue;
                    }
                    gr = mapx + right*a;
                    if (gr < -w) {
                        col += Math.floor((-gr)*2/w) - 1;
                        continue;
                    }
                    gl = mapx + left*a;
                    gt = mapy + top*d;
                    if (gl > winw || gt < 0) {
                        col = maxCol;
                        continue;
                    }
                }
                if (gid > cc.TMX_TILE_DIAGONAL_FLAG) {
                    flagged = true;
                    flippedX = (gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0;
                    flippedY = (gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0;
                }
                vertices[0].x = left * wa + top * wc + wtx;
                vertices[0].y = left * wb + top * wd + wty;
                vertices[1].x = left * wa + bottom * wc + wtx;
                vertices[1].y = left * wb + bottom * wd + wty;
                vertices[2].x = right * wa + top * wc + wtx;
                vertices[2].y = right * wb + top * wd + wty;
                vertices[3].x = right * wa + bottom * wc + wtx;
                vertices[3].y = right * wb + bottom * wd + wty;
                for (i = 0; i < 4; ++i) {
                    f32buffer[offset] = vertices[i].x;
                    f32buffer[offset + 1] = vertices[i].y;
                    f32buffer[offset + 2] = z;
                    ui32buffer[offset + 3] = this._color[0];
                    switch (i) {
                    case 0:
                    f32buffer[offset + 4] = flippedX ? grid.r : grid.l;
                    f32buffer[offset + 5] = flippedY ? grid.b : grid.t;
                    break;
                    case 1:
                    f32buffer[offset + 4] = flippedX ? grid.r : grid.l;
                    f32buffer[offset + 5] = flippedY ? grid.t : grid.b;
                    break;
                    case 2:
                    f32buffer[offset + 4] = flippedX ? grid.l : grid.r;
                    f32buffer[offset + 5] = flippedY ? grid.b : grid.t;
                    break;
                    case 3:
                    f32buffer[offset + 4] = flippedX ? grid.l : grid.r;
                    f32buffer[offset + 5] = flippedY ? grid.t : grid.b;
                    break;
                    }
                    offset += 6;
                }
                if (flagged) {
                    wa = a;
                    wb = b;
                    wc = c;
                    wd = d;
                    wtx = tx;
                    wty = ty;
                    flippedX = false;
                    flippedY = false;
                    flagged = false;
                }
            }
            colOffset += cols;
        }
        return (offset - vertexDataOffset) / 6;
    };
})();
cc.PointObject = cc.Class.extend({
    _ratio:null,
    _offset:null,
    _child:null,
    ctor: function(ratio, offset){
        this.initWithCCPoint(ratio, offset);
    },
    getRatio:function () {
        return this._ratio;
    },
    setRatio:function (value) {
        this._ratio = value;
    },
    getOffset:function () {
        return this._offset;
    },
    setOffset:function (value) {
        this._offset = value;
    },
    getChild:function () {
        return this._child;
    },
    setChild:function (value) {
        this._child = value;
    },
    initWithCCPoint:function (ratio, offset) {
        this._ratio = ratio;
        this._offset = offset;
        this._child = null;
        return true;
    }
});
cc.PointObject.create = function (ratio, offset) {
    return new cc.PointObject(ratio, offset);
};
cc.ParallaxNode = cc.Node.extend({
    parallaxArray:null,
    _lastPosition:null,
    _className:"ParallaxNode",
    getParallaxArray:function () {
        return this.parallaxArray;
    },
    setParallaxArray:function (value) {
        this.parallaxArray = value;
    },
    ctor:function () {
        cc.Node.prototype.ctor.call(this);
        this.parallaxArray = [];
        this._lastPosition = cc.p(-100, -100);
    },
    addChild:function (child, z, ratio, offset) {
        if (arguments.length === 3) {
            cc.log("ParallaxNode: use addChild(child, z, ratio, offset) instead");
            return;
        }
        if(!child)
            throw new Error("cc.ParallaxNode.addChild(): child should be non-null");
        var obj = new cc.PointObject(ratio, offset);
        obj.setChild(child);
        this.parallaxArray.push(obj);
        child.setPosition(this._position.x * ratio.x + offset.x, this._position.y * ratio.y + offset.y);
        cc.Node.prototype.addChild.call(this, child, z, child.tag);
    },
    removeChild:function (child, cleanup) {
        var locParallaxArray = this.parallaxArray;
        for (var i = 0; i < locParallaxArray.length; i++) {
            var point = locParallaxArray[i];
            if (point.getChild() === child) {
                locParallaxArray.splice(i, 1);
                break;
            }
        }
        cc.Node.prototype.removeChild.call(this, child, cleanup);
    },
    removeAllChildren:function (cleanup) {
        this.parallaxArray.length = 0;
        cc.Node.prototype.removeAllChildren.call(this, cleanup);
    },
    _updateParallaxPosition: function(){
        var pos = this._absolutePosition();
        if (!cc.pointEqualToPoint(pos, this._lastPosition)) {
            var locParallaxArray = this.parallaxArray;
            for (var i = 0, len = locParallaxArray.length; i < len; i++) {
                var point = locParallaxArray[i];
                var child = point.getChild();
                child.setPosition(-pos.x + pos.x * point.getRatio().x + point.getOffset().x,
                        -pos.y + pos.y * point.getRatio().y + point.getOffset().y);
            }
            this._lastPosition = pos;
        }
    },
    _absolutePosition:function () {
        var ret = this._position;
        var cn = this;
        while (cn.parent !== null) {
            cn = cn.parent;
            ret = cc.pAdd(ret, cn.getPosition());
        }
        return ret;
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.ParallaxNode.CanvasRenderCmd(this);
        else
            return new cc.ParallaxNode.WebGLRenderCmd(this);
    }
});
cc.ParallaxNode.create = function () {
    return new cc.ParallaxNode();
};
(function(){
    cc.ParallaxNode.CanvasRenderCmd = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = false;
    };
    var proto = cc.ParallaxNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = cc.ParallaxNode.CanvasRenderCmd;
    proto.updateStatus = function(){
        this._node._updateParallaxPosition();
        cc.Node.CanvasRenderCmd.prototype.updateStatus.call(this);
    };
    proto._syncStatus = function(parentCmd){
        this._node._updateParallaxPosition();
        cc.Node.CanvasRenderCmd.prototype._syncStatus.call(this, parentCmd);
    };
})();
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if(cc._renderType !== cc.game.RENDER_TYPE_WEBGL)
        return;
    cc.ParallaxNode.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = false;
    };
    var proto = cc.ParallaxNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = cc.ParallaxNode.WebGLRenderCmd;
    proto.updateStatus = function(){
        this._node._updateParallaxPosition();
        cc.Node.WebGLRenderCmd.prototype.updateStatus.call(this);
    };
    proto._syncStatus = function(parentCmd){
        this._node._updateParallaxPosition();
        cc.Node.WebGLRenderCmd.prototype._syncStatus.call(this, parentCmd);
    };
});
cc.CONTROL_EVENT_TOTAL_NUMBER = 9;
cc.CONTROL_EVENT_TOUCH_DOWN = 1 << 0;
cc.CONTROL_EVENT_TOUCH_DRAG_INSIDE = 1 << 1;
cc.CONTROL_EVENT_TOUCH_DRAG_OUTSIDE = 1 << 2;
cc.CONTROL_EVENT_TOUCH_DRAG_ENTER = 1 << 3;
cc.CONTROL_EVENT_TOUCH_DRAG_EXIT = 1 << 4;
cc.CONTROL_EVENT_TOUCH_UP_INSIDE = 1 << 5;
cc.CONTROL_EVENT_TOUCH_UP_OUTSIDE = 1 << 6;
cc.CONTROL_EVENT_TOUCH_CANCEL = 1 << 7;
cc.CONTROL_EVENT_VALUECHANGED = 1 << 8;
cc.CONTROL_STATE_NORMAL = 1 << 0;
cc.CONTROL_STATE_HIGHLIGHTED = 1 << 1;
cc.CONTROL_STATE_DISABLED = 1 << 2;
cc.CONTROL_STATE_SELECTED = 1 << 3;
cc.CONTROL_STATE_INITIAL = 1 << 3;
cc.Control = cc.Layer.extend({
    _isOpacityModifyRGB: false,
    _hasVisibleParents: false,
    _touchListener: null,
    _className: "Control",
    isOpacityModifyRGB: function () {
        return this._isOpacityModifyRGB;
    },
    setOpacityModifyRGB: function (opacityModifyRGB) {
        this._isOpacityModifyRGB = opacityModifyRGB;
        var children = this.getChildren();
        for (var i = 0, len = children.length; i < len; i++) {
            var selNode = children[i];
            if (selNode)
                selNode.setOpacityModifyRGB(opacityModifyRGB);
        }
    },
    _state: cc.CONTROL_STATE_NORMAL,
    getState: function () {
        return this._state;
    },
    _enabled: false,
    _selected: false,
    _highlighted: false,
    _dispatchTable: null,
    setEnabled: function (enabled) {
        this._enabled = enabled;
        this._state = enabled ? cc.CONTROL_STATE_NORMAL : cc.CONTROL_STATE_DISABLED;
        this.needsLayout();
    },
    isEnabled: function () {
        return this._enabled;
    },
    setSelected: function (selected) {
        this._selected = selected;
        this.needsLayout();
    },
    isSelected: function () {
        return this._selected;
    },
    setHighlighted: function (highlighted) {
        this._highlighted = highlighted;
        this.needsLayout();
    },
    isHighlighted: function () {
        return this._highlighted;
    },
    hasVisibleParents: function () {
        var parent = this.getParent();
        for (var c = parent; c != null; c = c.getParent()) {
            if (!c.isVisible())
                return false;
        }
        return true;
    },
    ctor: function () {
        cc.Layer.prototype.ctor.call(this);
        this._dispatchTable = {};
        this._color = cc.color.WHITE;
    },
    init: function () {
        if (cc.Layer.prototype.init.call(this)) {
            this._state = cc.CONTROL_STATE_NORMAL;
            this._enabled = true;
            this._selected = false;
            this._highlighted = false;
            var listener = cc.EventListener.create({
                event: cc.EventListener.TOUCH_ONE_BY_ONE,
                swallowTouches: true
            });
            if (this.onTouchBegan)
                listener.onTouchBegan = this.onTouchBegan.bind(this);
            if (this.onTouchMoved)
                listener.onTouchMoved = this.onTouchMoved.bind(this);
            if (this.onTouchEnded)
                listener.onTouchEnded = this.onTouchEnded.bind(this);
            if (this.onTouchCancelled)
                listener.onTouchCancelled = this.onTouchCancelled.bind(this);
            this._touchListener = listener;
            return true;
        } else
            return false;
    },
    onEnter: function () {
        var locListener = this._touchListener;
        if (!locListener._isRegistered())
            cc.eventManager.addListener(locListener, this);
        cc.Node.prototype.onEnter.call(this);
    },
    sendActionsForControlEvents: function (controlEvents) {
        for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
            if ((controlEvents & (1 << i))) {
                var invocationList = this._dispatchListforControlEvent(1 << i);
                for (var j = 0, inLen = invocationList.length; j < inLen; j++) {
                    invocationList[j].invoke(this);
                }
            }
        }
    },
    addTargetWithActionForControlEvents: function (target, action, controlEvents) {
        for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
            if ((controlEvents & (1 << i)))
                this._addTargetWithActionForControlEvent(target, action, 1 << i);
        }
    },
    removeTargetWithActionForControlEvents: function (target, action, controlEvents) {
        for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
            if ((controlEvents & (1 << i)))
                this._removeTargetWithActionForControlEvent(target, action, 1 << i);
        }
    },
    getTouchLocation: function (touch) {
        var touchLocation = touch.getLocation();
        return this.convertToNodeSpace(touchLocation);
    },
    isTouchInside: function (touch) {
        var touchLocation = touch.getLocation();
        touchLocation = this.getParent().convertToNodeSpace(touchLocation);
        return cc.rectContainsPoint(this.getBoundingBox(), touchLocation);
    },
    _invocationWithTargetAndActionForControlEvent: function (target, action, controlEvent) {
        return null;
    },
    _dispatchListforControlEvent: function (controlEvent) {
        controlEvent = controlEvent.toString();
        if (!this._dispatchTable[controlEvent])
            this._dispatchTable[controlEvent] = [];
        return this._dispatchTable[controlEvent];
    },
    _addTargetWithActionForControlEvent: function (target, action, controlEvent) {
        var invocation = new cc.Invocation(target, action, controlEvent);
        var eventInvocationList = this._dispatchListforControlEvent(controlEvent);
        eventInvocationList.push(invocation);
    },
    _removeTargetWithActionForControlEvent: function (target, action, controlEvent) {
        var eventInvocationList = this._dispatchListforControlEvent(controlEvent);
        var bDeleteObjects = true;
        if (!target && !action) {
            eventInvocationList.length = 0;
        } else {
            for (var i = 0; i < eventInvocationList.length;) {
                var invocation = eventInvocationList[i];
                var shouldBeRemoved = true;
                if (target)
                    shouldBeRemoved = (target === invocation.getTarget());
                if (action)
                    shouldBeRemoved = (shouldBeRemoved && (action === invocation.getAction()));
                if (shouldBeRemoved)
                    cc.arrayRemoveObject(eventInvocationList, invocation);
                else
                    i++;
            }
        }
    },
    needsLayout: function () {
    }
});
var _p = cc.Control.prototype;
_p.state;
cc.defineGetterSetter(_p, "state", _p.getState);
_p.enabled;
cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
_p.selected;
cc.defineGetterSetter(_p, "selected", _p.isSelected, _p.setSelected);
_p.highlighted;
cc.defineGetterSetter(_p, "highlighted", _p.isHighlighted, _p.setHighlighted);
_p = null;
cc.Control.create = function () {
    var retControl = new cc.Control();
    if (retControl && retControl.init())
        return retControl;
    return null;
};
cc.CONTROL_ZOOM_ACTION_TAG = 0xCCCB0001;
cc.ControlButton = cc.Control.extend({
    _doesAdjustBackgroundImage: false,
    zoomOnTouchDown: false,
    _preferredSize: null,
    _labelAnchorPoint: null,
    _currentTitle: null,
    _currentTitleColor: null,
    _titleLabel: null,
    _backgroundSprite: null,
    _opacity: 0,
    _isPushed: false,
    _titleDispatchTable: null,
    _titleColorDispatchTable: null,
    _titleLabelDispatchTable: null,
    _backgroundSpriteDispatchTable: null,
    _parentInited: false,
    _marginV: 0,
    _marginH: 0,
    _className: "ControlButton",
    ctor: function (label, backgroundSprite, fontSize) {
        cc.Control.prototype.ctor.call(this);
        this._preferredSize = cc.size(0, 0);
        this._labelAnchorPoint = cc.p(0, 0);
        this._currentTitle = "";
        this._currentTitleColor = cc.color.WHITE;
        this._titleDispatchTable = {};
        this._titleColorDispatchTable = {};
        this._titleLabelDispatchTable = {};
        this._backgroundSpriteDispatchTable = {};
        if(fontSize != undefined)
            this.initWithTitleAndFontNameAndFontSize(label, backgroundSprite, fontSize);
        else if(backgroundSprite != undefined)
            this.initWithLabelAndBackgroundSprite(label, backgroundSprite);
        else if(label != undefined)
            this.initWithBackgroundSprite(label);
        else
            this.init();
    },
    init: function () {
        return this.initWithLabelAndBackgroundSprite(new cc.LabelTTF("", "Arial", 12), new cc.Scale9Sprite());
    },
    needsLayout: function () {
        if (!this._parentInited) {
            return;
        }
        if (this._titleLabel)
            this._titleLabel.setVisible(false);
        if (this._backgroundSprite)
            this._backgroundSprite.setVisible(false);
        this.setLabelAnchorPoint(this._labelAnchorPoint);
        var locState = this._state;
        this._currentTitle = this.getTitleForState(locState);
        this._currentTitleColor = this.getTitleColorForState(locState);
        this._titleLabel = this.getTitleLabelForState(locState);
        var label = this._titleLabel;
        if (label && label.setString)
            label.setString(this._currentTitle);
        if (label)
            label.setColor(this._currentTitleColor);
        var locContentSize = this.getContentSize();
        if (label)
            label.setPosition(locContentSize.width / 2, locContentSize.height / 2);
        this._backgroundSprite = this.getBackgroundSpriteForState(locState);
        var locBackgroundSprite = this._backgroundSprite;
        if (locBackgroundSprite)
            locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2);
        var titleLabelSize = cc.size(0, 0);
        if (label) {
            var boundingBox = label.getBoundingBox();
            titleLabelSize.width = boundingBox.width;
            titleLabelSize.height = boundingBox.height;
        }
        if (this._doesAdjustBackgroundImage) {
            if (locBackgroundSprite)
                locBackgroundSprite.setContentSize(titleLabelSize.width + this._marginH * 2, titleLabelSize.height + this._marginV * 2);
        } else {
            if (locBackgroundSprite) {
                var preferredSize = locBackgroundSprite.getPreferredSize();
                preferredSize = cc.size(preferredSize.width, preferredSize.height);
                if (preferredSize.width <= 0)
                    preferredSize.width = titleLabelSize.width;
                if (preferredSize.height <= 0)
                    preferredSize.height = titleLabelSize.height;
                locBackgroundSprite.setContentSize(preferredSize);
            }
        }
        var rectTitle = label ? label.getBoundingBox() : cc.rect(0, 0, 0, 0);
        var rectBackground = locBackgroundSprite ? locBackgroundSprite.getBoundingBox() : cc.rect(0, 0, 0, 0);
        var maxRect = cc.rectUnion(rectTitle, rectBackground);
        this.setContentSize(maxRect.width, maxRect.height);
        locContentSize = this.getContentSize();
        if (label) {
            label.setPosition(locContentSize.width / 2, locContentSize.height / 2);
            label.setVisible(true);
        }
        if (locBackgroundSprite) {
            locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2);
            locBackgroundSprite.setVisible(true);
        }
    },
    initWithLabelAndBackgroundSprite: function (label, backgroundSprite) {
        if (!label)
            throw new Error("cc.ControlButton.initWithLabelAndBackgroundSprite(): label should be non-null");
        if (!backgroundSprite)
            throw new Error("cc.ControlButton.initWithLabelAndBackgroundSprite(): backgroundSprite should be non-null");
        if (cc.Control.prototype.init.call(this, true)) {
            this._parentInited = true;
            this._titleDispatchTable = {};
            this._titleColorDispatchTable = {};
            this._titleLabelDispatchTable = {};
            this._backgroundSpriteDispatchTable = {};
            this._isPushed = false;
            this.zoomOnTouchDown = true;
            this._currentTitle = null;
            this.setAdjustBackgroundImage(true);
            this.setPreferredSize(cc.size(0, 0));
            this.zoomOnTouchDown = true;
            this.ignoreAnchorPointForPosition(false);
            this.setAnchorPoint(0.5, 0.5);
            this._titleLabel = label;
            this._backgroundSprite = backgroundSprite;
            this.setOpacity(255);
            this.setOpacityModifyRGB(true);
            var tempString = label.getString();
            this.setTitleForState(tempString, cc.CONTROL_STATE_NORMAL);
            this.setTitleColorForState(label.getColor(), cc.CONTROL_STATE_NORMAL);
            this.setTitleLabelForState(label, cc.CONTROL_STATE_NORMAL);
            this.setBackgroundSpriteForState(backgroundSprite, cc.CONTROL_STATE_NORMAL);
            this._state = cc.CONTROL_STATE_NORMAL;
            this._marginH = 24;
            this._marginV = 12;
            this._labelAnchorPoint = cc.p(0.5, 0.5);
            this.setPreferredSize(cc.size(0, 0));
            this.needsLayout();
            return true;
        }//couldn't init the CCControl
        else
            return false;
    },
    initWithTitleAndFontNameAndFontSize: function (title, fontName, fontSize) {
        var label = new cc.LabelTTF(title, fontName, fontSize);
        return this.initWithLabelAndBackgroundSprite(label, new cc.Scale9Sprite());
    },
    initWithBackgroundSprite: function (sprite) {
        var label = new cc.LabelTTF("", "Arial", 30);//
        return this.initWithLabelAndBackgroundSprite(label, sprite);
    },
    doesAdjustBackgroundImage: function () {
        return this._doesAdjustBackgroundImage;
    },
    setAdjustBackgroundImage: function (adjustBackgroundImage) {
        this._doesAdjustBackgroundImage = adjustBackgroundImage;
        this.needsLayout();
    },
    getZoomOnTouchDown: function () {
        return this.zoomOnTouchDown;
    },
    setZoomOnTouchDown: function (zoomOnTouchDown) {
        return this.zoomOnTouchDown = zoomOnTouchDown;
    },
    getPreferredSize: function () {
        return this._preferredSize;
    },
    setPreferredSize: function (size) {
        if (size.width === 0 && size.height === 0) {
            this._doesAdjustBackgroundImage = true;
        } else {
            this._doesAdjustBackgroundImage = false;
            var locTable = this._backgroundSpriteDispatchTable;
            for (var itemKey in locTable)
                locTable[itemKey].setPreferredSize(size);
        }
        this._preferredSize = size;
        this.needsLayout();
    },
    getLabelAnchorPoint: function () {
        return this._labelAnchorPoint;
    },
    setLabelAnchorPoint: function (labelAnchorPoint) {
        this._labelAnchorPoint = labelAnchorPoint;
        if (this._titleLabel)
            this._titleLabel.setAnchorPoint(labelAnchorPoint);
    },
    _getCurrentTitle: function () {
        return this._currentTitle;
    },
    _getCurrentTitleColor: function () {
        return this._currentTitleColor;
    },
    getOpacity: function () {
        return this._opacity;
    },
    setOpacity: function (opacity) {
        cc.Control.prototype.setOpacity.call(this, opacity);
        var locTable = this._backgroundSpriteDispatchTable;
        for (var itemKey in locTable)
            locTable[itemKey].setOpacity(opacity);
    },
    setColor: function (color) {
        cc.Control.prototype.setColor.call(this, color);
        var locTable = this._backgroundSpriteDispatchTable;
        for (var key in locTable)
            locTable[key].setColor(color);
    },
    getColor: function () {
        var locRealColor = this._realColor;
        return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
    },
    isPushed: function () {
        return this._isPushed;
    },
    _getVerticalMargin: function () {
        return this._marginV;
    },
    _getHorizontalOrigin: function () {
        return this._marginH;
    },
    setMargins: function (marginH, marginV) {
        this._marginV = marginV;
        this._marginH = marginH;
        this.needsLayout();
    },
    setEnabled: function (enabled) {
        cc.Control.prototype.setEnabled.call(this, enabled);
        this.needsLayout();
    },
    setSelected: function (enabled) {
        cc.Control.prototype.setSelected.call(this, enabled);
        this.needsLayout();
    },
    setHighlighted: function (enabled) {
        this._state = enabled ? cc.CONTROL_STATE_HIGHLIGHTED : cc.CONTROL_STATE_NORMAL;
        cc.Control.prototype.setHighlighted.call(this, enabled);
        var action = this.getActionByTag(cc.CONTROL_ZOOM_ACTION_TAG);
        if (action)
            this.stopAction(action);
        if (this.zoomOnTouchDown) {
            var scaleValue = (this.isHighlighted() && this.isEnabled() && !this.isSelected()) ? 1.1 : 1.0;
            var zoomAction = cc.scaleTo(0.05, scaleValue);
            zoomAction.setTag(cc.CONTROL_ZOOM_ACTION_TAG);
            this.runAction(zoomAction);
        }
    },
    onTouchBegan: function (touch, event) {
        if (!this.isTouchInside(touch) || !this.isEnabled() || !this.isVisible() || !this.hasVisibleParents())
            return false;
        this._isPushed = true;
        this.setHighlighted(true);
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DOWN);
        return true;
    },
    onTouchMoved: function (touch, event) {
        if (!this._enabled || !this._isPushed || this._selected) {
            if (this._highlighted)
                this.setHighlighted(false);
            return;
        }
        var isTouchMoveInside = this.isTouchInside(touch);
        if (isTouchMoveInside && !this._highlighted) {
            this.setHighlighted(true);
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_ENTER);
        } else if (isTouchMoveInside && this._highlighted) {
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_INSIDE);
        } else if (!isTouchMoveInside && this._highlighted) {
            this.setHighlighted(false);
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_EXIT);
        } else if (!isTouchMoveInside && !this._highlighted) {
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_OUTSIDE);
        }
    },
    onTouchEnded: function (touch, event) {
        this._isPushed = false;
        this.setHighlighted(false);
        if (this.isTouchInside(touch)) {
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_UP_INSIDE);
        } else {
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_UP_OUTSIDE);
        }
    },
    onTouchCancelled: function (touch, event) {
        this._isPushed = false;
        this.setHighlighted(false);
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_CANCEL);
    },
    getTitleForState: function (state) {
        var locTable = this._titleDispatchTable;
        if (locTable) {
            if (locTable[state])
                return locTable[state];
            return locTable[cc.CONTROL_STATE_NORMAL];
        }
        return "";
    },
    setTitleForState: function (title, state) {
        this._titleDispatchTable[state] = title || "";
        if (this.getState() === state)
            this.needsLayout();
    },
    getTitleColorForState: function (state) {
        var colorObject = this._titleColorDispatchTable[state];
        if (colorObject)
            return colorObject;
        colorObject = this._titleColorDispatchTable[cc.CONTROL_STATE_NORMAL];
        if (colorObject)
            return colorObject;
        return cc.color.WHITE;
    },
    setTitleColorForState: function (color, state) {
        this._titleColorDispatchTable[state] = color;
        if (this.getState() === state)
            this.needsLayout();
    },
    getTitleLabelForState: function (state) {
        var locTable = this._titleLabelDispatchTable;
        if (locTable[state])
            return locTable[state];
        return locTable[cc.CONTROL_STATE_NORMAL];
    },
    setTitleLabelForState: function (titleLabel, state) {
        var locTable = this._titleLabelDispatchTable;
        if (locTable[state]) {
            var previousLabel = locTable[state];
            if (previousLabel)
                this.removeChild(previousLabel, true);
        }
        locTable[state] = titleLabel;
        titleLabel.setVisible(false);
        titleLabel.setAnchorPoint(0.5, 0.5);
        this.addChild(titleLabel, 1);
        if (this.getState() === state)
            this.needsLayout();
    },
    setTitleTTFForState: function (fntFile, state) {
        var title = this.getTitleForState(state);
        if (!title)
            title = "";
        this.setTitleLabelForState(new cc.LabelTTF(title, fntFile, 12), state);
    },
    getTitleTTFForState: function (state) {
        var labelTTF = this.getTitleLabelForState(state);
        if ((labelTTF != null) && (labelTTF instanceof  cc.LabelTTF)) {
            return labelTTF.getFontName();
        } else {
            return "";
        }
    },
    setTitleTTFSizeForState: function (size, state) {
        var labelTTF = this.getTitleLabelForState(state);
        if ((labelTTF != null) && (labelTTF instanceof  cc.LabelTTF)) {
            labelTTF.setFontSize(size);
        }
    },
    getTitleTTFSizeForState: function (state) {
        var labelTTF = this.getTitleLabelForState(state);
        if ((labelTTF != null) && (labelTTF instanceof  cc.LabelTTF)) {
            return labelTTF.getFontSize();
        }
        return 0;
    },
    setTitleBMFontForState: function (fntFile, state) {
        var title = this.getTitleForState(state);
        if (!title)
            title = "";
        this.setTitleLabelForState(new cc.LabelBMFont(title, fntFile), state);
    },
    getTitleBMFontForState: function (state) {
        var labelBMFont = this.getTitleLabelForState(state);
        if ((labelBMFont != null) && (labelBMFont instanceof  cc.LabelBMFont)) {
            return labelBMFont.getFntFile();
        }
        return "";
    },
    getBackgroundSpriteForState: function (state) {
        var locTable = this._backgroundSpriteDispatchTable;
        if (locTable[state]) {
            return locTable[state];
        }
        return locTable[cc.CONTROL_STATE_NORMAL];
    },
    setBackgroundSpriteForState: function (sprite, state) {
        var locTable = this._backgroundSpriteDispatchTable;
        if (locTable[state]) {
            var previousSprite = locTable[state];
            if (previousSprite)
                this.removeChild(previousSprite, true);
        }
        locTable[state] = sprite;
        sprite.setVisible(false);
        sprite.setAnchorPoint(0.5, 0.5);
        this.addChild(sprite);
        var locPreferredSize = this._preferredSize;
        if (locPreferredSize.width !== 0 || locPreferredSize.height !== 0) {
            sprite.setPreferredSize(locPreferredSize);
        }
        if (this._state === state)
            this.needsLayout();
    },
    setBackgroundSpriteFrameForState: function (spriteFrame, state) {
        var sprite = cc.Scale9Sprite.createWithSpriteFrame(spriteFrame);
        this.setBackgroundSpriteForState(sprite, state);
    }
});
var _p = cc.ControlButton.prototype;
_p.adjustBackground;
cc.defineGetterSetter(_p, "adjustBackground", _p.getAdjustBackgroundImage, _p.setAdjustBackgroundImage);
_p.preferredSize;
cc.defineGetterSetter(_p, "preferredSize", _p.getPreferredSize, _p.setPreferredSize);
_p.labelAnchor;
cc.defineGetterSetter(_p, "labelAnchor", _p.getLabelAnchorPoint, _p.setLabelAnchorPoint);
_p = null;
cc.ControlButton.create = function (label, backgroundSprite, fontSize) {
    return new cc.ControlButton(label, backgroundSprite, fontSize);
};
cc.RGBA = function(r,g,b,a){
    this.r = r ;
    this.g = g ;
    this.b = b ;
    this.a = a ;
};
cc.HSV = function(h,s,v){
    this.h = h ;
    this.s = s ;
    this.v = v ;
};
cc.ControlUtils = {};
cc.ControlUtils.addSpriteToTargetWithPosAndAnchor = function(spriteName,target,pos,anchor){
    var sprite = new cc.Sprite("#" + spriteName);
    if (!sprite)
        return null;
    sprite.setPosition(pos);
    sprite.setAnchorPoint(anchor);
    target.addChild(sprite);
    return sprite;
};
cc.ControlUtils.HSVfromRGB = function(rgbaValue){
    var out = new cc.HSV();
    var min, max, delta;
    min = rgbaValue.r < rgbaValue.g ? rgbaValue.r : rgbaValue.g;
    min = min  < rgbaValue.b ? min  : rgbaValue.b;
    max = rgbaValue.r > rgbaValue.g ? rgbaValue.r : rgbaValue.g;
    max = max  > rgbaValue.b ? max  : rgbaValue.b;
    out.v = max;
    delta = max - min;
    if( max > 0.0 ){
        out.s = (delta / max);
    } else {
        out.s = 0.0;
        out.h = -1;
        return out;
    }
    if( rgbaValue.r >= max ){
        out.h = ( rgbaValue.g - rgbaValue.b ) / delta;
    } else {
        if( rgbaValue.g >= max )
            out.h = 2.0 + ( rgbaValue.b - rgbaValue.r ) / delta;
        else
            out.h = 4.0 + ( rgbaValue.r - rgbaValue.g ) / delta;
    }
    out.h *= 60.0;
    if( out.h < 0.0 )
        out.h += 360.0;
    return out;
};
cc.ControlUtils.RGBfromHSV = function(hsvValue){
    var hh, p, q, t, ff;
    var i;
    var out = new cc.RGBA();
    out.a = 1;
    if (hsvValue.s <= 0.0){
        if (!hsvValue.h){
            out.r = hsvValue.v;
            out.g = hsvValue.v;
            out.b = hsvValue.v;
            return out;
        }
        out.r = 0.0;
        out.g = 0.0;
        out.b = 0.0;
        return out;
    }
    hh = hsvValue.h;
    if(hh >= 360.0)
        hh = 0.0;
    hh /= 60.0;
    i = 0 | hh;
    ff = hh - i;
    p = hsvValue.v * (1.0 - hsvValue.s);
    q = hsvValue.v * (1.0 - (hsvValue.s * ff));
    t = hsvValue.v * (1.0 - (hsvValue.s * (1.0 - ff)));
    switch(i) {
        case 0:
            out.r = hsvValue.v;
            out.g = t;
            out.b = p;
            break;
        case 1:
            out.r = q;
            out.g = hsvValue.v;
            out.b = p;
            break;
        case 2:
            out.r = p;
            out.g = hsvValue.v;
            out.b = t;
            break;
        case 3:
            out.r = p;
            out.g = q;
            out.b = hsvValue.v;
            break;
        case 4:
            out.r = t;
            out.g = p;
            out.b = hsvValue.v;
            break;
        default:
            out.r = hsvValue.v;
            out.g = p;
            out.b = q;
            break;
    }
    return out;
};
cc.ControlUtils.CCRectUnion = function(rect1, rect2){
    return cc.rectUnion(rect1,rect2);
};
cc.Invocation = cc.Class.extend({
    _action:null,
    _target:null,
    _controlEvent:null,
    ctor:function(target,action,controlEvent){
        this._target=target;
        this._action=action;
        this._controlEvent=controlEvent;
    },
    getAction:function(){
       return this._action;
    },
    getTarget:function(){
       return this._target ;
    },
    getControlEvent:function(){
       return this._controlEvent;
    },
    invoke:function(sender){
        if (this._target && this._action) {
            if (cc.isString(this._action)) {
                this._target[this._action](sender, this._controlEvent);
            } else{
                this._action.call(this._target, sender, this._controlEvent);
            }
        }
    }
});
cc.Spacer = cc.Layer.extend({});
cc.Spacer.verticalSpacer = function (space) {
    var pRet = new cc.Spacer();
    pRet.init();
    pRet.setContentSize(0, space);
    return pRet;
};
cc.Spacer.horizontalSpacer = function (space) {
    var pRet = new cc.Spacer();
    pRet.init();
    pRet.setContentSize(space, 0);
    return pRet;
};
cc.MenuPassive = cc.Layer.extend({
    _color:null,
    _opacity:0,
    _className:"MenuPassive",
    ctor:function () {
    },
    getColor:function () {
        var locColor = this._color;
        return cc.color(locColor.r, locColor.g, locColor.b, locColor.a);
    },
    setColor:function (color) {
        var locColor = this._color;
        locColor.r = color.r;
        locColor.g = color.g;
        locColor.b = color.b;
        if (this._children && this._children.length > 0) {
            for (var i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    this._children[i].setColor(color);
                }
            }
        }
        if (color.a !== undefined && !color.a_undefined) {
            this.setOpacity(color.a);
        }
    },
    getOpacity:function () {
        return this._opacity;
    },
    setOpacity:function (opacity) {
        this._opacity = opacity;
        if (this._children && this._children.length > 0) {
            for (var i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    this._children[i].setOpacity(opacity);
                }
            }
        }
        this._color.a = opacity;
    },
    initWithItems:function (item, args) {
        if (this.init()) {
            var winSize = cc.director.getWinSize();
            this.ignoreAnchorPointForPosition(true);
            this.setAnchorPoint(0.5, 0.5);
            this.setContentSize(winSize);
            this.setPosition(winSize.width / 2, winSize.height / 2);
            var z = 0;
            if (item) {
                this.addChild(item, z);
                for (var i = 0; i < args.length; i++) {
                    if (args[i]) {
                        z++;
                        this.addChild(args[i], z);
                    }
                }
            }
            return true;
        }
        return false;
    },
    alignItemsVertically:function () {
        this.alignItemsVerticallyWithPadding(cc.DEFAULT_PADDING);
    },
    alignItemsVerticallyWithPadding:function (padding) {
        var height = -padding;
        var i;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    height += this._children[i].getContentSize().height * this._children[i].getScaleY() + padding;
                }
            }
        }
        var width = 0;
        var y = height / 2.0;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    width = Math.max(width, this._children[i].getContentSize().width);
                    this._children[i].setPosition(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2.0);
                    y -= this._children[i].getContentSize().height * this._children[i].getScaleY() + padding;
                }
            }
        }
        this.setContentSize(width, height);
    },
    alignItemsHorizontally:function () {
        this.alignItemsHorizontallyWithPadding(cc.DEFAULT_PADDING);
    },
    alignItemsHorizontallyWithPadding:function (padding) {
        var width = -padding;
        var i;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    width += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding;
                }
            }
        }
        var height = 0;
        var x = -width / 2.0;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    height = Math.max(height, this._children[i].getContentSize().height);
                    this._children[i].setPosition(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2.0, 0);
                    x += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding;
                }
            }
        }
        this.setContentSize(width, height);
    },
    alignItemsInColumns:function (columns) {
        var rows = [];
        var i;
        for (i = 1; i < arguments.length; i++) {
            rows.push(arguments[i]);
        }
        var height = -5;
        var row = 0;
        var rowHeight = 0;
        var columnsOccupied = 0;
        var rowColumns;
        var tmp;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    if(row >= rows.length){
                        cc.log("cc.MenuPassive.alignItemsInColumns(): invalid row index");
                        continue;
                    }
                    rowColumns = rows[row];
                    if(!rowColumns) {
                        cc.log("cc.MenuPassive.alignItemsInColumns(): can not have zero columns on a row");
                        continue;
                    }
                    tmp = this._children[i].getContentSize().height;
                    rowHeight = 0 | ((rowHeight >= tmp || (tmp == null)) ? rowHeight : tmp);
                    ++columnsOccupied;
                    if (columnsOccupied >= rowColumns) {
                        height += rowHeight + 5;
                        columnsOccupied = 0;
                        rowHeight = 0;
                        ++row;
                    }
                }
            }
        }
        var winSize = cc.director.getWinSize();
        row = 0;
        rowHeight = 0;
        rowColumns = 0;
        var w = 0.0;
        var x = 0.0;
        var y = (height / 2);
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    if (rowColumns === 0) {
                        rowColumns = rows[row];
                        w = winSize.width / (1 + rowColumns);
                        x = w;
                    }
                    tmp = this._children[i].getContentSize().height;
                    rowHeight = 0 | ((rowHeight >= tmp || (tmp == null)) ? rowHeight : tmp);
                    this._children[i].setPosition(x - winSize.width / 2,
                        y - this._children[i].getContentSize().height / 2);
                    x += w;
                    ++columnsOccupied;
                    if (columnsOccupied >= rowColumns) {
                        y -= rowHeight + 5;
                        columnsOccupied = 0;
                        rowColumns = 0;
                        rowHeight = 0;
                        ++row;
                    }
                }
            }
        }
    },
    alignItemsInRows:function (rows) {
        var columns = [];
        var i;
        for (i = 1; i < arguments.length; i++) {
            columns.push(arguments[i]);
        }
        var columnWidths = [];
        var columnHeights = [];
        var width = -10;
        var columnHeight = -5;
        var column = 0;
        var columnWidth = 0;
        var rowsOccupied = 0;
        var columnRows;
        var tmp;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    if(column >= columns.length){
                        cc.log("cc.MenuPassive.alignItemsInRows(): invalid row index");
                        continue;
                    }
                    columnRows = columns[column];
                    if(!columnRows) {
                        cc.log("cc.MenuPassive.alignItemsInColumns(): can't have zero rows on a column");
                        continue;
                    }
                    tmp = this._children[i].getContentSize().width;
                    columnWidth = 0 | ((columnWidth >= tmp || (tmp == null)) ? columnWidth : tmp);
                    columnHeight += 0 | (this._children[i].getContentSize().height + 5);
                    ++rowsOccupied;
                    if (rowsOccupied >= columnRows) {
                        columnWidths.push(columnWidth);
                        columnHeights.push(columnHeight);
                        width += columnWidth + 10;
                        rowsOccupied = 0;
                        columnWidth = 0;
                        columnHeight = -5;
                        ++column;
                    }
                }
            }
        }
        var winSize = cc.director.getWinSize();
        column = 0;
        columnWidth = 0;
        columnRows = null;
        var x = (-width / 2);
        var y = 0.0;
        if (this._children && this._children.length > 0) {
            for (i = 0; i < this._children.length; i++) {
                if (this._children[i]) {
                    if (columnRows == null) {
                        columnRows = columns[column];
                        y = columnHeights[column];
                    }
                    tmp = this._children[i].getContentSize().width;
                    columnWidth = 0 | ((columnWidth >= tmp || (tmp == null)) ? columnWidth : tmp);
                    this._children[i].setPosition(x + columnWidths[column] / 2, y - winSize.height / 2);
                    y -= this._children[i].getContentSize().height + 10;
                    ++rowsOccupied;
                    if (rowsOccupied >= columnRows) {
                        x += columnWidth + 5;
                        rowsOccupied = 0;
                        columnRows = 0;
                        columnWidth = 0;
                        ++column;
                    }
                }
            }
        }
    },
    setOpacityModifyRGB:function (bValue) {
    },
    isOpacityModifyRGB:function () {
        return false;
    }
});
cc.MenuPassive.create = function (item) {
    if (!item) {
        item = null;
    }
    var argArr = [];
    for (var i = 1; i < arguments.length; i++) {
        argArr.push(arguments[i]);
    }
    var pRet = new cc.MenuPassive();
    if (pRet && pRet.initWithItems(item, argArr)) {
        return pRet;
    }
    return null;
};
cc.MenuPassive.createWithItem = function (item) {
    return cc.MenuPassive.create(item, null);
};
cc.ControlSaturationBrightnessPicker = cc.Control.extend({
    _saturation:0,
    _brightness:0,
    _background:null,
    _overlay:null,
    _shadow:null,
    _slider:null,
    _startPos:null,
    _boxPos:0,
    _boxSize:0,
    _className:"ControlSaturationBrightnessPicker",
    ctor:function (target, pos) {
        cc.Control.prototype.ctor.call(this);
        pos && this.initWithTargetAndPos(target, pos);
    },
    getSaturation:function () {
        return this._saturation;
    },
    getBrightness:function () {
        return this._brightness;
    },
    getBackground:function () {
        return this._background;
    },
    getOverlay:function () {
        return this._brightness;
    },
    getShadow:function () {
        return this._shadow;
    },
    getSlider:function () {
        return this._slider;
    },
    getStartPos:function () {
        return this._startPos;
    },
    initWithTargetAndPos:function (target, pos) {
        if (cc.Control.prototype.init.call(this)) {
            this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPickerBackground.png", target, pos, cc.p(0.0, 0.0));
            this._overlay = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPickerOverlay.png", target, pos, cc.p(0.0, 0.0));
            this._shadow = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPickerShadow.png", target, pos, cc.p(0.0, 0.0));
            this._slider = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPicker.png", target, pos, cc.p(0.5, 0.5));
            this._startPos = pos;
            this._boxPos = 35;
            this._boxSize = this._background.getContentSize().width / 2;
            return true;
        } else
            return false;
    },
    setEnabled:function (enabled) {
        cc.Control.prototype.setEnabled.call(this, enabled);
        if (this._slider) {
            this._slider.setOpacity(enabled ? 255 : 128);
        }
    },
    updateWithHSV:function (hsv) {
        var hsvTemp = new cc.HSV();
        hsvTemp.s = 1;
        hsvTemp.h = hsv.h;
        hsvTemp.v = 1;
        var rgb = cc.ControlUtils.RGBfromHSV(hsvTemp);
        this._background.setColor(cc.color(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
    },
    updateDraggerWithHSV:function (hsv) {
        var pos = cc.p(this._startPos.x + this._boxPos + (this._boxSize * (1 - hsv.s)),
            this._startPos.y + this._boxPos + (this._boxSize * hsv.v));
        this._updateSliderPosition(pos);
    },
    _updateSliderPosition:function (sliderPosition) {
        var centerX = this._startPos.x + this._background.getBoundingBox().width * 0.5;
        var centerY = this._startPos.y + this._background.getBoundingBox().height * 0.5;
        var dx = sliderPosition.x - centerX;
        var dy = sliderPosition.y - centerY;
        var dist = Math.sqrt(dx * dx + dy * dy);
        var angle = Math.atan2(dy, dx);
        var limit = this._background.getBoundingBox().width * 0.5;
        if (dist > limit) {
            sliderPosition.x = centerX + limit * Math.cos(angle);
            sliderPosition.y = centerY + limit * Math.sin(angle);
        }
        this._slider.setPosition(sliderPosition);
        if (sliderPosition.x < this._startPos.x + this._boxPos)
            sliderPosition.x = this._startPos.x + this._boxPos;
        else if (sliderPosition.x > this._startPos.x + this._boxPos + this._boxSize - 1)
            sliderPosition.x = this._startPos.x + this._boxPos + this._boxSize - 1;
        if (sliderPosition.y < this._startPos.y + this._boxPos)
            sliderPosition.y = this._startPos.y + this._boxPos;
        else if (sliderPosition.y > this._startPos.y + this._boxPos + this._boxSize)
            sliderPosition.y = this._startPos.y + this._boxPos + this._boxSize;
        this._saturation = 1.0 - Math.abs((this._startPos.x + this._boxPos - sliderPosition.x) / this._boxSize);
        this._brightness = Math.abs((this._startPos.y + this._boxPos - sliderPosition.y) / this._boxSize);
    },
    _checkSliderPosition:function (location) {
        var centerX = this._startPos.x + this._background.getBoundingBox().width * 0.5;
        var centerY = this._startPos.y + this._background.getBoundingBox().height * 0.5;
        var dx = location.x - centerX;
        var dy = location.y - centerY;
        var dist = Math.sqrt(dx * dx + dy * dy);
        if (dist <= this._background.getBoundingBox().width * 0.5) {
            this._updateSliderPosition(location);
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
            return true;
        }
        return false;
    },
    onTouchBegan:function (touch, event) {
        if (!this.isEnabled() || !this.isVisible())        {
            return false;
        }
        var touchLocation = this.getTouchLocation(touch);
        return this._checkSliderPosition(touchLocation);
    },
    onTouchMoved:function (touch, event) {
        var touchLocation = this.getTouchLocation(touch);
        this._checkSliderPosition(touchLocation);
    }
});
var _p = cc.ControlSaturationBrightnessPicker.prototype;
_p.saturation;
cc.defineGetterSetter(_p, "saturation", _p.getSaturation);
_p.brightness;
cc.defineGetterSetter(_p, "brightness", _p.getBrightness);
_p.background;
cc.defineGetterSetter(_p, "background", _p.getBackground);
_p.overlay;
cc.defineGetterSetter(_p, "overlay", _p.getOverlay);
_p.shadow;
cc.defineGetterSetter(_p, "shadow", _p.getShadow);
_p.slider;
cc.defineGetterSetter(_p, "slider", _p.getSlider);
_p.startPos;
cc.defineGetterSetter(_p, "startPos", _p.getStartPos);
_p = null;
cc.ControlSaturationBrightnessPicker.create = function (target, pos) {
    return new cc.ControlSaturationBrightnessPicker(target, pos);
};
cc.ControlHuePicker = cc.Control.extend({
    _hue:0,
    _huePercentage:0,
    _background:null,
    _slider:null,
    _startPos:null,
    _className:"ControlHuePicker",
    ctor:function(target, pos) {
        cc.Control.prototype.ctor.call(this);
        pos && this.initWithTargetAndPos(target, pos);
    },
    getHue:function () {
        return this._hue;
    },
    setHue:function (hueValue) {
        this._hue = hueValue;
        this.setHuePercentage(this._hue / 360.0);
    },
    getHuePercentage:function () {
        return this._huePercentage;
    },
    setHuePercentage:function (hueValueInPercent) {
        this._huePercentage = hueValueInPercent;
        this._hue = this._huePercentage * 360.0;
        var backgroundBox = this._background.getBoundingBox();
        var centerX = this._startPos.x + backgroundBox.width * 0.5;
        var centerY = this._startPos.y + backgroundBox.height * 0.5;
        var limit = backgroundBox.width * 0.5 - 15.0;
        var angleDeg = this._huePercentage * 360.0 - 180.0;
        var angle = cc.degreesToRadians(angleDeg);
        var x = centerX + limit * Math.cos(angle);
        var y = centerY + limit * Math.sin(angle);
        this._slider.setPosition(x, y);
    },
    setEnabled:function (enabled) {
        cc.Control.prototype.setEnabled.call(this, enabled);
        if (this._slider) {
            this._slider.setOpacity(enabled ? 255 : 128);
        }
    },
    getBackground:function () {
        return this._background;
    },
    getSlider:function () {
        return this._slider;
    },
    getStartPos:function () {
        return this._startPos;
    },
    initWithTargetAndPos:function (target, pos) {
        if (cc.Control.prototype.init.call(this)) {
            this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("huePickerBackground.png", target, pos, cc.p(0.0, 0.0));
            this._slider = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPicker.png", target, pos, cc.p(0.5, 0.5));
            this._slider.setPosition(pos.x, pos.y + this._background.getBoundingBox().height * 0.5);
            this._startPos = pos;
            this._hue = 0.0;
            this._huePercentage = 0.0;
            return true;
        } else
            return false;
    },
    _updateSliderPosition:function (location) {
        var backgroundBox = this._background.getBoundingBox();
        var centerX = this._startPos.x + backgroundBox.width * 0.5;
        var centerY = this._startPos.y + backgroundBox.height * 0.5;
        var dx = location.x - centerX;
        var dy = location.y - centerY;
        var angle = Math.atan2(dy, dx);
        var angleDeg = cc.radiansToDegrees(angle) + 180.0;
        this.setHue(angleDeg);
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
    },
    _checkSliderPosition:function (location) {
        var distance = Math.sqrt(Math.pow(location.x + 10, 2) + Math.pow(location.y, 2));
        if (80 > distance && distance > 59)        {
            this._updateSliderPosition(location);
            return true;
        }
        return false;
    },
    onTouchBegan:function (touch, event) {
        if (!this.isEnabled() || !this.isVisible())        {
            return false;
        }
        var touchLocation = this.getTouchLocation(touch);
        return this._checkSliderPosition(touchLocation);
    },
    onTouchMoved:function (touch, event) {
        var touchLocation = this.getTouchLocation(touch);
        this._checkSliderPosition(touchLocation);
    }
});
var _p = cc.ControlHuePicker.prototype;
_p.hue;
cc.defineGetterSetter(_p, "hue", _p.getHue, _p.setHue);
_p.huePercent;
cc.defineGetterSetter(_p, "huePercent", _p.getHuePercentage, _p.setHuePercentage);
_p.background;
cc.defineGetterSetter(_p, "background", _p.getBackground);
_p.slider;
cc.defineGetterSetter(_p, "slider", _p.getSlider);
_p.startPos;
cc.defineGetterSetter(_p, "startPos", _p.getStartPos);
_p = null;
cc.ControlHuePicker.create = function (target, pos) {
    return new cc.ControlHuePicker(target, pos);
};
cc.ControlColourPicker = cc.Control.extend({
    _hsv:null,
    _colourPicker:null,
    _huePicker:null,
    _background:null,
    _className:"ControlColourPicker",
    ctor:function () {
        cc.Control.prototype.ctor.call(this);
        this.init();
    },
    hueSliderValueChanged:function (sender, controlEvent) {
        this._hsv.h = sender.getHue();
        var rgb = cc.ControlUtils.RGBfromHSV(this._hsv);
        cc.Control.prototype.setColor.call(this,cc.color(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
        this._updateControlPicker();
    },
    colourSliderValueChanged:function (sender, controlEvent) {
        this._hsv.s = sender.getSaturation();
        this._hsv.v = sender.getBrightness();
        var rgb = cc.ControlUtils.RGBfromHSV(this._hsv);
        cc.Control.prototype.setColor.call(this,cc.color(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
    },
    setColor:function (color) {
        cc.Control.prototype.setColor.call(this,color);
        var rgba = new cc.RGBA();
        rgba.r = color.r / 255.0;
        rgba.g = color.g / 255.0;
        rgba.b = color.b / 255.0;
        rgba.a = 1.0;
        this._hsv = cc.ControlUtils.HSVfromRGB(rgba);
        this._updateHueAndControlPicker();
    },
    getBackground:function () {
        return this._background;
    },
    init:function () {
        if (cc.Control.prototype.init.call(this)) {
            cc.spriteFrameCache.addSpriteFrames(res.CCControlColourPickerSpriteSheet_plist);
            var spriteSheet = new cc.SpriteBatchNode(res.CCControlColourPickerSpriteSheet_png);
            this.addChild(spriteSheet);
            this._hsv = new cc.HSV(0, 0, 0);
            this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("menuColourPanelBackground.png", spriteSheet, cc.p(0,0), cc.p(0.5, 0.5));
            var backgroundPointZero = cc.pSub(this._background.getPosition(),
                cc.p(this._background.getContentSize().width / 2, this._background.getContentSize().height / 2));
            var hueShift = 8;
            var colourShift = 28;
            this._huePicker = new cc.ControlHuePicker(spriteSheet, cc.p(backgroundPointZero.x + hueShift, backgroundPointZero.y + hueShift));
            this._colourPicker = new cc.ControlSaturationBrightnessPicker(spriteSheet, cc.p(backgroundPointZero.x + colourShift, backgroundPointZero.y + colourShift));
            this._huePicker.addTargetWithActionForControlEvents(this, this.hueSliderValueChanged, cc.CONTROL_EVENT_VALUECHANGED);
            this._colourPicker.addTargetWithActionForControlEvents(this, this.colourSliderValueChanged, cc.CONTROL_EVENT_VALUECHANGED);
            this._updateHueAndControlPicker();
            this.addChild(this._huePicker);
            this.addChild(this._colourPicker);
            this.setContentSize(this._background.getContentSize());
            return true;
        }
        else
            return false;
    },
    _updateControlPicker:function () {
        this._huePicker.setHue(this._hsv.h);
        this._colourPicker.updateWithHSV(this._hsv);
    },
    _updateHueAndControlPicker:function () {
        this._huePicker.setHue(this._hsv.h);
        this._colourPicker.updateWithHSV(this._hsv);
        this._colourPicker.updateDraggerWithHSV(this._hsv);
    },
    setEnabled:function (enabled) {
        cc.Control.prototype.setEnabled.call(this, enabled);
        if (this._huePicker !== null) {
            this._huePicker.setEnabled(enabled);
        }
        if (this._colourPicker) {
            this._colourPicker.setEnabled(enabled);
        }
    },
    onTouchBegan:function () {
        return false;
    }
});
var _p = cc.ControlColourPicker.prototype;
_p.background;
cc.defineGetterSetter(_p, "background", _p.getBackground);
_p = null;
cc.ControlColourPicker.create = function () {
    return new cc.ControlColourPicker();
};
var res = res || {};
res.CCControlColourPickerSpriteSheet_plist = res.CCControlColourPickerSpriteSheet_plist || "res/extensions/CCControlColourPickerSpriteSheet.plist";
res.CCControlColourPickerSpriteSheet_png = res.CCControlColourPickerSpriteSheet_png || "res/extensions/CCControlColourPickerSpriteSheet.png";
cc.SLIDER_MARGIN_H = 24;
cc.SLIDER_MARGIN_V = 8;
cc.ControlSlider = cc.Control.extend({
    _value:0,
    _minimumValue:0,
    _maximumValue:0,
    _minimumAllowedValue:0,
    _maximumAllowedValue:0,
    _thumbSprite:null,
    _progressSprite:null,
    _backgroundSprite:null,
    _className:"ControlSlider",
    ctor:function (bgFile, progressFile, thumbFile) {
        cc.Control.prototype.ctor.call(this);
        if (thumbFile != undefined) {
            var bgSprite = new cc.Sprite(bgFile);
            var progressSprite = new cc.Sprite(progressFile);
            var thumbSprite = new cc.Sprite(thumbFile);
            this.initWithSprites(bgSprite, progressSprite, thumbSprite);
        }
    },
    getValue:function () {
        return this._value;
    },
    setValue:function (value) {
        value = Math.max(value, this._minimumValue);
        value = Math.min(value, this._maximumValue);
        this._value = value;
        this.needsLayout();
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
    },
    getMinimumValue:function () {
        return this._minimumValue;
    },
    setMinimumValue:function (minimumValue) {
        this._minimumValue = minimumValue;
        this._minimumAllowedValue = minimumValue;
        if (this._minimumValue >= this._maximumValue)
            this._maximumValue = this._minimumValue + 1.0;
        this.setValue(this._value);
    },
    getMaximumValue:function () {
        return this._maximumValue;
    },
    setMaximumValue:function (maximumValue) {
        this._maximumValue = maximumValue;
        this._maximumAllowedValue = maximumValue;
        if (this._maximumValue <= this._minimumValue)
            this._minimumValue = this._maximumValue - 1.0;
        this.setValue(this._value);
    },
    isTouchInside:function (touch) {
        var touchLocation = touch.getLocation();
        touchLocation = this.getParent().convertToNodeSpace(touchLocation);
        var rect = this.getBoundingBox();
        rect.width += this._thumbSprite.getContentSize().width;
        rect.x -= this._thumbSprite.getContentSize().width / 2;
        return cc.rectContainsPoint(rect, touchLocation);
    },
    locationFromTouch:function (touch) {
        var touchLocation = touch.getLocation();
        touchLocation = this.convertToNodeSpace(touchLocation);
        if (touchLocation.x < 0) {
            touchLocation.x = 0;
        } else if (touchLocation.x > this._backgroundSprite.getContentSize().width) {
            touchLocation.x = this._backgroundSprite.getContentSize().width;
        }
        return touchLocation;
    },
    getMinimumAllowedValue:function () {
        return this._minimumAllowedValue;
    },
    setMinimumAllowedValue:function (val) {
        this._minimumAllowedValue = val;
    },
    getMaximumAllowedValue:function () {
        return this._maximumAllowedValue;
    },
    setMaximumAllowedValue:function (val) {
        this._maximumAllowedValue = val;
    },
    getThumbSprite:function () {
        return this._thumbSprite;
    },
    getProgressSprite:function () {
        return this._progressSprite;
    },
    getBackgroundSprite:function () {
        return this._backgroundSprite;
    },
    initWithSprites:function (backgroundSprite, progressSprite, thumbSprite) {
        if (cc.Control.prototype.init.call(this)) {
            this.ignoreAnchorPointForPosition(false);
            this._backgroundSprite = backgroundSprite;
            this._progressSprite = progressSprite;
            this._thumbSprite = thumbSprite;
            var maxRect = cc.ControlUtils.CCRectUnion(backgroundSprite.getBoundingBox(), thumbSprite.getBoundingBox());
            this.setContentSize(maxRect.width, maxRect.height);
            this._backgroundSprite.setAnchorPoint(0.5, 0.5);
            this._backgroundSprite.setPosition(maxRect.width / 2, maxRect.height / 2);
            this.addChild(this._backgroundSprite);
            this._progressSprite.setAnchorPoint(0.0, 0.5);
            this._progressSprite.setPosition(0, maxRect.height / 2);
            this.addChild(this._progressSprite);
            this._thumbSprite.setPosition(0, maxRect.height / 2);
            this.addChild(this._thumbSprite);
            this._minimumValue = 0.0;
            this._maximumValue = 1.0;
            this.setValue(this._minimumValue);
            return true;
        } else
            return false;
    },
    setEnabled:function (enabled) {
        cc.Control.prototype.setEnabled.call(this, enabled);
        if (this._thumbSprite) {
            this._thumbSprite.setOpacity(enabled ? 255 : 128);
        }
    },
    sliderBegan:function (location) {
        this.setSelected(true);
        this._thumbSprite.setColor(cc.color.GRAY);
        this.setValue(this.valueForLocation(location));
    },
    sliderMoved:function (location) {
        this.setValue(this.valueForLocation(location));
    },
    sliderEnded:function (location) {
        if (this.isSelected()) {
            this.setValue(this.valueForLocation(this._thumbSprite.getPosition()));
        }
        this._thumbSprite.setColor(cc.color.WHITE);
        this.setSelected(false);
    },
    getTouchLocationInControl:function (touch) {
        var touchLocation = touch.getLocation();
        touchLocation = this.convertToNodeSpace(touchLocation);
        if (touchLocation.x < 0) {
            touchLocation.x = 0;
        } else if (touchLocation.x > this._backgroundSprite.getContentSize().width + cc.SLIDER_MARGIN_H) {
            touchLocation.x = this._backgroundSprite.getContentSize().width + cc.SLIDER_MARGIN_H;
        }
        return touchLocation;
    },
    onTouchBegan:function (touch, event) {
        if (!this.isTouchInside(touch)|| !this.isEnabled() || !this.isVisible())
            return false;
        var location = this.locationFromTouch(touch);
        this.sliderBegan(location);
        return true;
    },
    onTouchMoved:function (touch, event) {
        var location = this.locationFromTouch(touch);
        this.sliderMoved(location);
    },
    onTouchEnded:function (touch, event) {
        this.sliderEnded(cc.p(0,0));
    },
    needsLayout:function(){
        var percent = (this._value - this._minimumValue) / (this._maximumValue - this._minimumValue);
        this._thumbSprite.setPositionX(percent * this._backgroundSprite.getContentSize().width);
        var textureRect = this._progressSprite.getTextureRect();
        textureRect = cc.rect(textureRect.x, textureRect.y, this._thumbSprite.getPositionX(), textureRect.height);
        this._progressSprite.setTextureRect(textureRect, this._progressSprite.isTextureRectRotated());
        this._thumbSprite._renderCmd.transform(this._renderCmd);
    },
    valueForLocation:function (location) {
        var percent = location.x / this._backgroundSprite.getContentSize().width;
        return Math.max(Math.min(this._minimumValue + percent * (this._maximumValue - this._minimumValue), this._maximumAllowedValue), this._minimumAllowedValue);
    }
});
var _p = cc.ControlSlider.prototype;
_p.value;
cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
_p.minValue;
cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
_p.maxValue;
cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
_p.minAllowedValue;
cc.defineGetterSetter(_p, "minAllowedValue", _p.getMinimumAllowedValue, _p.setMinimumAllowedValue);
_p.maxAllowedValue;
cc.defineGetterSetter(_p, "maxAllowedValue", _p.getMaximumAllowedValue, _p.setMaximumAllowedValue);
_p.thumbSprite;
cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite);
_p.progressSprite;
cc.defineGetterSetter(_p, "progressSprite", _p.getProgressSprite);
_p.backgroundSprite;
cc.defineGetterSetter(_p, "backgroundSprite", _p.getBackgroundSprite);
_p = null;
cc.ControlSlider.create = function (bgFile, progressFile, thumbFile) {
    return new cc.ControlSlider(bgFile, progressFile, thumbFile);
};
cc.ControlSwitch = cc.Control.extend({
    _switchSprite:null,
    _initialTouchXPosition:0,
    _moved:false,
    _on:false,
    _className:"ControlSwitch",
    ctor:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
        cc.Control.prototype.ctor.call(this);
        offLabel && this.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
    },
    initWithMaskSprite:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
        if(!maskSprite)
            throw new Error("cc.ControlSwitch.initWithMaskSprite(): maskSprite should be non-null.");
        if(!onSprite)
            throw new Error("cc.ControlSwitch.initWithMaskSprite(): onSprite should be non-null.");
        if(!offSprite)
            throw new Error("cc.ControlSwitch.initWithMaskSprite(): offSprite should be non-null.");
        if(!thumbSprite)
            throw new Error("cc.ControlSwitch.initWithMaskSprite(): thumbSprite should be non-null.");
        if (this.init()) {
            this._on = true;
            this._switchSprite = new cc.ControlSwitchSprite();
            this._switchSprite.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
            this._switchSprite.setPosition(this._switchSprite.getContentSize().width / 2, this._switchSprite.getContentSize().height / 2);
            this.addChild(this._switchSprite);
            this.ignoreAnchorPointForPosition(false);
            this.setAnchorPoint(0.5, 0.5);
            this.setContentSize(this._switchSprite.getContentSize());
            return true;
        }
        return false;
    },
    setOn:function (isOn, animated) {
        animated = animated || false;
        this._on = isOn;
        var xPosition = (this._on) ? this._switchSprite.getOnPosition() : this._switchSprite.getOffPosition();
        if(animated){
            this._switchSprite.runAction(new cc.ActionTween(0.2, "sliderXPosition", this._switchSprite.getSliderXPosition(),xPosition));
        }else{
            this._switchSprite.setSliderXPosition(xPosition);
        }
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
    },
    isOn:function () {
        return this._on;
    },
    hasMoved:function () {
        return this._moved;
    },
    setEnabled:function (enabled) {
        this._enabled = enabled;
        this._switchSprite.setOpacity((enabled) ? 255 : 128);
    },
    locationFromTouch:function (touch) {
        var touchLocation = touch.getLocation();
        touchLocation = this.convertToNodeSpace(touchLocation);
        return touchLocation;
    },
    onTouchBegan:function (touch, event) {
        if (!this.isTouchInside(touch)  || !this.isEnabled()|| !this.isVisible()) {
            return false;
        }
        this._moved = false;
        var location = this.locationFromTouch(touch);
        this._initialTouchXPosition = location.x - this._switchSprite.getSliderXPosition();
        this._switchSprite.getThumbSprite().setColor(cc.color.GRAY);
        this._switchSprite.needsLayout();
        return true;
    },
    onTouchMoved:function (touch, event) {
        var location = this.locationFromTouch(touch);
        location = cc.p(location.x - this._initialTouchXPosition, 0);
        this._moved = true;
        this._switchSprite.setSliderXPosition(location.x);
    },
    onTouchEnded:function (touch, event) {
        var location = this.locationFromTouch(touch);
        this._switchSprite.getThumbSprite().setColor(cc.color.WHITE);
        if (this.hasMoved()) {
            this.setOn(!(location.x < this._switchSprite.getContentSize().width / 2), true);
        } else {
            this.setOn(!this._on, true);
        }
    },
    onTouchCancelled:function (touch, event) {
        var location = this.locationFromTouch(touch);
        this._switchSprite.getThumbSprite().setColor(cc.color.WHITE);
        if (this.hasMoved()) {
            this.setOn(!(location.x < this._switchSprite.getContentSize().width / 2), true);
        } else {
            this.setOn(!this._on, true);
        }
    }
});
cc.ControlSwitch.create = function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
    return new cc.ControlSwitch(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
};
cc.ControlSwitchSprite = cc.Sprite.extend({
    _sliderXPosition:0,
    _onPosition:0,
    _offPosition:0,
    _textureLocation:0,
    _maskLocation:0,
    _maskSize:null,
    _onSprite:null,
    _offSprite:null,
    _thumbSprite:null,
    _onLabel:null,
    _offLabel:null,
    _clipper:null,
    _stencil:null,
    _backRT:null,
    ctor:function () {
        cc.Sprite.prototype.ctor.call(this);
        this._sliderXPosition = 0;
        this._onPosition = 0;
        this._offPosition = 0;
        this._maskLocation = 0;
        this._maskSize = cc.size(0, 0);
        this._onSprite = null;
        this._offSprite = null;
        this._thumbSprite = null;
        this._onLabel = null;
        this._offLabel = null;
    },
    initWithMaskSprite:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
        if (cc.Sprite.prototype.init.call(this)) {
            this.setSpriteFrame(maskSprite.displayFrame());
            this._onPosition = 0;
            this._offPosition = -onSprite.getContentSize().width + thumbSprite.getContentSize().width / 2;
            this._sliderXPosition = this._onPosition;
            this.setOnSprite(onSprite);
            this.setOffSprite(offSprite);
            this.setThumbSprite(thumbSprite);
            this.setOnLabel(onLabel);
            this.setOffLabel(offLabel);
            this._stencil = maskSprite;
            var maskSize = this._maskSize = this._stencil.getContentSize();
            this._stencil.setPosition(0, 0);
            this._clipper = new cc.ClippingNode();
            this._clipper.setAnchorPoint(0.5, 0.5);
            this._clipper.setPosition(maskSize.width / 2, maskSize.height / 2);
            this._clipper.setStencil(this._stencil);
            this.addChild(this._clipper);
            this._clipper.addChild(onSprite);
            this._clipper.addChild(offSprite);
            this._clipper.addChild(onLabel);
            this._clipper.addChild(offLabel);
            this.addChild(this._thumbSprite);
            this.needsLayout();
            return true;
        }
        return false;
    },
    needsLayout:function () {
        var maskSize = this._maskSize;
        this._onSprite.setPosition(
            this._onSprite.getContentSize().width / 2 + this._sliderXPosition - maskSize.width / 2,
            this._onSprite.getContentSize().height / 2 - maskSize.height / 2
        );
        this._offSprite.setPosition(
            this._onSprite.getContentSize().width + this._offSprite.getContentSize().width / 2 + this._sliderXPosition - maskSize.width / 2,
            this._offSprite.getContentSize().height / 2 - maskSize.height / 2
        );
        if (this._onLabel) {
            this._onLabel.setPosition(
                this._onSprite.getPositionX() - this._thumbSprite.getContentSize().width / 6,
                this._onSprite.getContentSize().height / 2 - maskSize.height / 2
            );
        }
        if (this._offLabel) {
            this._offLabel.setPosition(
                this._offSprite.getPositionX() + this._thumbSprite.getContentSize().width / 6,
                this._offSprite.getContentSize().height / 2 - maskSize.height / 2
            );
        }
        this._thumbSprite.setPosition(
            this._onSprite.getContentSize().width + this._sliderXPosition,
            this._maskSize.height / 2
        );
    },
    setSliderXPosition:function (sliderXPosition) {
        if (sliderXPosition <= this._offPosition) {
            sliderXPosition = this._offPosition;
        } else if (sliderXPosition >= this._onPosition) {
            sliderXPosition = this._onPosition;
        }
        this._sliderXPosition = sliderXPosition;
        this.needsLayout();
    },
    getSliderXPosition:function () {
        return this._sliderXPosition;
    },
    _getOnSideWidth:function () {
        return this._onSprite.getContentSize().width;
    },
    _getOffSideWidth:function () {
        return this._offSprite.getContentSize().height;
    },
    updateTweenAction:function (value, key) {
        if (key === "sliderXPosition")
            this.setSliderXPosition(value);
    },
    setOnPosition:function (onPosition) {
        this._onPosition = onPosition;
    },
    getOnPosition:function () {
        return this._onPosition;
    },
    setOffPosition:function (offPosition) {
        this._offPosition = offPosition;
    },
    getOffPosition:function () {
        return this._offPosition;
    },
    setMaskTexture:function (maskTexture) {
        this._stencil.setTexture(maskTexture);
    },
    getMaskTexture:function () {
        return this._stencil.getTexture();
    },
    setTextureLocation:function (textureLocation) {
        this._textureLocation = textureLocation;
    },
    getTextureLocation:function () {
        return this._textureLocation;
    },
    setMaskLocation:function (maskLocation) {
        this._maskLocation = maskLocation;
    },
    getMaskLocation:function () {
        return this._maskLocation;
    },
    setOnSprite:function (onSprite) {
        this._onSprite = onSprite;
    },
    getOnSprite:function () {
        return this._onSprite;
    },
    setOffSprite:function (offSprite) {
        this._offSprite = offSprite;
    },
    getOffSprite:function () {
        return this._offSprite;
    },
    setThumbSprite:function (thumbSprite) {
        this._thumbSprite = thumbSprite;
    },
    getThumbSprite:function () {
        return this._thumbSprite;
    },
    setOnLabel:function (onLabel) {
        this._onLabel = onLabel;
    },
    getOnLabel:function () {
        return this._onLabel;
    },
    setOffLabel:function (offLabel) {
        this._offLabel = offLabel;
    },
    getOffLabel:function () {
        return this._offLabel;
    }
});
var _p = cc.ControlSwitchSprite.prototype;
_p.sliderX;
cc.defineGetterSetter(_p, "sliderX", _p.getSliderXPosition, _p.setSliderXPosition);
_p.onPos;
cc.defineGetterSetter(_p, "onPos", _p.getOnPosition, _p.setOnPosition);
_p.offPos;
cc.defineGetterSetter(_p, "offPos", _p.getOffPosition, _p.setOffPosition);
_p.maskTexture;
cc.defineGetterSetter(_p, "maskTexture", _p.getMaskTexture, _p.setMaskTexture);
_p.maskPos;
cc.defineGetterSetter(_p, "maskPos", _p.getMaskLocation, _p.setMaskLocation);
_p.onSprite;
cc.defineGetterSetter(_p, "onSprite", _p.getOnSprite, _p.setOnSprite);
_p.offSprite;
cc.defineGetterSetter(_p, "offSprite", _p.getOffSprite, _p.setOffSprite);
_p.thumbSprite;
cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite, _p.setThumbSprite);
_p.onLabel;
cc.defineGetterSetter(_p, "onLabel", _p.getOnLabel, _p.setOnLabel);
_p.offLabel;
cc.defineGetterSetter(_p, "offLabel", _p.getOffLabel, _p.setOffLabel);
_p.onSideWidth;
cc.defineGetterSetter(_p, "onSideWidth", _p._getOnSideWidth);
_p.offSideWidth;
cc.defineGetterSetter(_p, "offSideWidth", _p._getOffSideWidth);
_p = null;
cc.CONTROL_STEPPER_PARTMINUS = 0;
cc.CONTROL_STEPPER_PARTPLUS = 1;
cc.CONTROL_STEPPER_PARTNONE = 2;
cc.CONTROL_STEPPER_LABELCOLOR_ENABLED = cc.color(55, 55, 55);
cc.CONTROL_STEPPER_LABELCOLOR_DISABLED = cc.color(147, 147, 147);
cc.CONTROL_STEPPER_LABELFONT = "CourierNewPSMT";
cc.AUTOREPEAT_DELTATIME = 0.15;
cc.AUTOREPEAT_INCREASETIME_INCREMENT = 12;
cc.ControlStepper = cc.Control.extend({
    _minusSprite:null,
    _plusSprite:null,
    _minusLabel:null,
    _plusLabel:null,
    _value:0,
    _continuous:false,
    _autorepeat:false,
    _wraps:false,
    _minimumValue:0,
    _maximumValue:0,
    _stepValue:0,
    _touchInsideFlag:false,
    _touchedPart:cc.CONTROL_STEPPER_PARTNONE,
    _autorepeatCount:0,
    _className:"ControlStepper",
    ctor:function (minusSprite, plusSprite) {
        cc.Control.prototype.ctor.call(this);
        this._minusSprite = null;
        this._plusSprite = null;
        this._minusLabel = null;
        this._plusLabel = null;
        this._value = 0;
        this._continuous = false;
        this._autorepeat = false;
        this._wraps = false;
        this._minimumValue = 0;
        this._maximumValue = 0;
        this._stepValue = 0;
        this._touchInsideFlag = false;
        this._touchedPart = cc.CONTROL_STEPPER_PARTNONE;
        this._autorepeatCount = 0;
        plusSprite && this.initWithMinusSpriteAndPlusSprite(minusSprite, plusSprite);
    },
    initWithMinusSpriteAndPlusSprite:function (minusSprite, plusSprite) {
        if(!minusSprite)
            throw new Error("cc.ControlStepper.initWithMinusSpriteAndPlusSprite(): Minus sprite should be non-null.");
        if(!plusSprite)
            throw new Error("cc.ControlStepper.initWithMinusSpriteAndPlusSprite(): Plus sprite should be non-null.");
        if (this.init()) {
            this._autorepeat = true;
            this._continuous = true;
            this._minimumValue = 0;
            this._maximumValue = 100;
            this._value = 0;
            this._stepValue = 1;
            this._wraps = false;
            this.ignoreAnchorPointForPosition(false);
            this.setMinusSprite(minusSprite);
            this._minusSprite.setPosition(minusSprite.getContentSize().width / 2, minusSprite.getContentSize().height / 2);
            this.addChild(this._minusSprite);
            this.setMinusLabel(new cc.LabelTTF("-", cc.CONTROL_STEPPER_LABELFONT, 40, cc.size(40, 40), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER));
            this._minusLabel.setColor(cc.CONTROL_STEPPER_LABELCOLOR_DISABLED);
            this._minusLabel.setPosition(this._minusSprite.getContentSize().width / 2, this._minusSprite.getContentSize().height / 2);
            this._minusSprite.addChild(this._minusLabel);
            this.setPlusSprite(plusSprite);
            this._plusSprite.setPosition(minusSprite.getContentSize().width + plusSprite.getContentSize().width / 2,
                minusSprite.getContentSize().height / 2);
            this.addChild(this._plusSprite);
            this.setPlusLabel(new cc.LabelTTF("+", cc.CONTROL_STEPPER_LABELFONT, 40, cc.size(40, 40), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER));
            this._plusLabel.setColor(cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
            this._plusLabel.setPosition(this._plusSprite.getContentSize().width / 2, this._plusSprite.getContentSize().height / 2);
            this._plusSprite.addChild(this._plusLabel);
            var maxRect = cc.ControlUtils.CCRectUnion(this._minusSprite.getBoundingBox(), this._plusSprite.getBoundingBox());
            this.setContentSize(this._minusSprite.getContentSize().width + this._plusSprite.getContentSize().height, maxRect.height);
            return true;
        }
        return false;
    },
    setWraps: function (wraps) {
        this._wraps = wraps;
        if (this._wraps) {
            this._minusLabel.setColor(cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
            this._plusLabel.setColor(cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
        }
        this.setValue(this._value);
    },
    getWraps: function () {
        return this._wraps;
    },
    setMinimumValue:function (minimumValue) {
        if (minimumValue >= this._maximumValue)
            throw new Error("cc.ControlStepper.setMinimumValue(): minimumValue should be numerically less than maximumValue.");
        this._minimumValue = minimumValue;
        this.setValue(this._value);
    },
    getMinimumValue: function () {
        return this._minimumValue;
    },
    setMaximumValue:function (maximumValue) {
        if (maximumValue <= this._minimumValue)
            throw new Error("cc.ControlStepper.setMaximumValue(): maximumValue should be numerically less than maximumValue.");
        this._maximumValue = maximumValue;
        this.setValue(this._value);
    },
    getMaximumValue: function () {
        return this._maximumValue;
    },
    setValue:function (value) {
        this.setValueWithSendingEvent(value, true);
    },
    getValue:function () {
        return this._value;
    },
    setStepValue:function (stepValue) {
        if (stepValue <= 0)
            throw new Error("cc.ControlStepper.setMaximumValue(): stepValue should be numerically greater than 0.");
        this._stepValue = stepValue;
    },
    getStepValue:function () {
        return this._stepValue;
    },
    isContinuous:function () {
        return this._continuous;
    },
    setValueWithSendingEvent:function (value, send) {
        if (value < this._minimumValue) {
            value = this._wraps ? this._maximumValue : this._minimumValue;
        } else if (value > this._maximumValue) {
            value = this._wraps ? this._minimumValue : this._maximumValue;
        }
        this._value = value;
        if (!this._wraps) {
            this._minusLabel.setColor((value === this._minimumValue) ? cc.CONTROL_STEPPER_LABELCOLOR_DISABLED : cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
            this._plusLabel.setColor((value === this._maximumValue) ? cc.CONTROL_STEPPER_LABELCOLOR_DISABLED : cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
        }
        if (send) {
            this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
        }
    },
    startAutorepeat:function () {
        this._autorepeatCount = -1;
        this.schedule(this.update, cc.AUTOREPEAT_DELTATIME, cc.REPEAT_FOREVER, cc.AUTOREPEAT_DELTATIME * 3);
    },
    stopAutorepeat:function () {
        this.unschedule(this.update);
    },
    update:function (dt) {
        this._autorepeatCount++;
        if ((this._autorepeatCount < cc.AUTOREPEAT_INCREASETIME_INCREMENT) && (this._autorepeatCount % 3) !== 0)
            return;
        if (this._touchedPart === cc.CONTROL_STEPPER_PARTMINUS) {
            this.setValueWithSendingEvent(this._value - this._stepValue, this._continuous);
        } else if (this._touchedPart === cc.CONTROL_STEPPER_PARTPLUS) {
            this.setValueWithSendingEvent(this._value + this._stepValue, this._continuous);
        }
    },
    updateLayoutUsingTouchLocation:function (location) {
        if (location.x < this._minusSprite.getContentSize().width
            && this._value > this._minimumValue) {
            this._touchedPart = cc.CONTROL_STEPPER_PARTMINUS;
            this._minusSprite.setColor(cc.color.GRAY);
            this._plusSprite.setColor(cc.color.WHITE);
        } else if (location.x >= this._minusSprite.getContentSize().width
            && this._value < this._maximumValue) {
            this._touchedPart = cc.CONTROL_STEPPER_PARTPLUS;
            this._minusSprite.setColor(cc.color.WHITE);
            this._plusSprite.setColor(cc.color.GRAY);
        } else {
            this._touchedPart = cc.CONTROL_STEPPER_PARTNONE;
            this._minusSprite.setColor(cc.color.WHITE);
            this._plusSprite.setColor(cc.color.WHITE);
        }
    },
    onTouchBegan:function (touch, event) {
        if (!this.isTouchInside(touch) || !this.isEnabled() || !this.isVisible()) {
            return false;
        }
        var location = this.getTouchLocation(touch);
        this.updateLayoutUsingTouchLocation(location);
        this._touchInsideFlag = true;
        if (this._autorepeat) {
            this.startAutorepeat();
        }
        return true;
    },
    onTouchMoved:function (touch, event) {
        if (this.isTouchInside(touch)) {
            var location = this.getTouchLocation(touch);
            this.updateLayoutUsingTouchLocation(location);
            if (!this._touchInsideFlag) {
                this._touchInsideFlag = true;
                if (this._autorepeat) {
                    this.startAutorepeat();
                }
            }
        } else {
            this._touchInsideFlag = false;
            this._touchedPart = cc.CONTROL_STEPPER_PARTNONE;
            this._minusSprite.setColor(cc.color.WHITE);
            this._plusSprite.setColor(cc.color.WHITE);
            if (this._autorepeat) {
                this.stopAutorepeat();
            }
        }
    },
    onTouchEnded:function (touch, event) {
        this._minusSprite.setColor(cc.color.WHITE);
        this._plusSprite.setColor(cc.color.WHITE);
        if (this._autorepeat) {
            this.stopAutorepeat();
        }
        if (this.isTouchInside(touch)) {
            var location = this.getTouchLocation(touch);
            this.setValue(this._value + ((location.x < this._minusSprite.getContentSize().width) ? (0.0 - this._stepValue) : this._stepValue));
        }
    },
    setMinusSprite:function (sprite) {
        this._minusSprite = sprite;
    },
    getMinusSprite:function () {
        return this._minusSprite;
    },
    setPlusSprite:function (sprite) {
        this._plusSprite = sprite;
    },
    getPlusSprite:function () {
        return this._plusSprite;
    },
    setMinusLabel:function (sprite) {
        this._minusLabel = sprite;
    },
    getMinusLabel:function () {
        return this._minusLabel;
    },
    setPlusLabel:function (sprite) {
        this._plusLabel = sprite;
    },
    getPlusLabel:function () {
        return this._plusLabel;
    }
});
var _p = cc.ControlStepper.prototype;
_p.wraps;
cc.defineGetterSetter(_p, "wraps", _p.getWraps, _p.setWraps);
_p.value;
cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
_p.minValue;
cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
_p.maxValue;
cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
_p.stepValue;
cc.defineGetterSetter(_p, "stepValue", _p.getStepValue, _p.setStepValue);
_p.continuous;
cc.defineGetterSetter(_p, "continuous", _p.isContinuous);
_p.minusSprite;
cc.defineGetterSetter(_p, "minusSprite", _p.getMinusSprite, _p.setMinusSprite);
_p.plusSprite;
cc.defineGetterSetter(_p, "plusSprite", _p.getPlusSprite, _p.setPlusSprite);
_p.minusLabel;
cc.defineGetterSetter(_p, "minusLabel", _p.getMinusLabel, _p.setMinusLabel);
_p.plusLabel;
cc.defineGetterSetter(_p, "plusLabel", _p.getPlusLabel, _p.setPlusLabel);
_p = null;
cc.ControlStepper.create = function (minusSprite, plusSprite) {
    return new cc.ControlStepper(minusSprite, plusSprite);
};
cc.ControlPotentiometer = cc.Control.extend({
    _thumbSprite:null,
    _progressTimer:null,
    _previousLocation:null,
    _value:0,
    _minimumValue:0,
    _maximumValue:1,
    _className:"ControlPotentiometer",
    ctor:function (backgroundFile, progressFile, thumbFile) {
        cc.Control.prototype.ctor.call(this);
        if (thumbFile != undefined) {
            var backgroundSprite = new cc.Sprite(backgroundFile);
            var thumbSprite = new cc.Sprite(thumbFile);
            var progressTimer = new cc.ProgressTimer(new cc.Sprite(progressFile));
            this.initWithTrackSprite_ProgressTimer_ThumbSprite(backgroundSprite, progressTimer, thumbSprite);
        }
    },
    initWithTrackSprite_ProgressTimer_ThumbSprite:function (trackSprite, progressTimer, thumbSprite) {
        if (this.init()) {
            this.setProgressTimer(progressTimer);
            this.setThumbSprite(thumbSprite);
            this._thumbSprite.setPosition(progressTimer.getPosition());
            this.addChild(thumbSprite, 2);
            this.addChild(progressTimer, 1);
            this.addChild(trackSprite);
            this.setContentSize(trackSprite.getContentSize());
            this._minimumValue = 0.0;
            this._maximumValue = 1.0;
            this.setValue(this._minimumValue);
            return true;
        }
        return false;
    },
    setEnabled:function (enabled) {
        this.setEnabled(enabled);
        if (this._thumbSprite !== null) {
            this._thumbSprite.setOpacity((enabled) ? 255 : 128);
        }
    },
    setValue:function (value) {
        if (value < this._minimumValue) {
            value = this._minimumValue;
        }
        if (value > this._maximumValue) {
            value = this._maximumValue;
        }
        this._value = value;
        var percent = (value - this._minimumValue) / (this._maximumValue - this._minimumValue);
        this._progressTimer.setPercentage(percent * 100.0);
        this._thumbSprite.setRotation(percent * 360.0);
        this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
    },
    getValue:function () {
        return this._value;
    },
    setMinimumValue:function (minimumValue) {
        this._minimumValue = minimumValue;
        if (this._minimumValue >= this._maximumValue) {
            this._maximumValue = this._minimumValue + 1.0;
        }
        this.setValue(this._maximumValue);
    },
    getMinimumValue:function () {
        return this._minimumValue;
    },
    setMaximumValue:function (maximumValue) {
        this._maximumValue = maximumValue;
        if (this._maximumValue <= this._minimumValue) {
            this._minimumValue = this._maximumValue - 1.0;
        }
        this.setValue(this._minimumValue);
    },
    getMaximumValue:function () {
        return this._maximumValue;
    },
    isTouchInside:function (touch) {
        var touchLocation = this.getTouchLocation(touch);
        var distance = this.distanceBetweenPointAndPoint(this._progressTimer.getPosition(), touchLocation);
        return distance < Math.min(this.getContentSize().width / 2, this.getContentSize().height / 2);
    },
    onTouchBegan:function (touch, event) {
        if (!this.isTouchInside(touch) || !this.isEnabled() || !this.isVisible()) {
            return false;
        }
        this._previousLocation = this.getTouchLocation(touch);
        this.potentiometerBegan(this._previousLocation);
        return true;
    },
    onTouchMoved:function (touch, event) {
        var location = this.getTouchLocation(touch);
        this.potentiometerMoved(location);
    },
    onTouchEnded:function (touch, event) {
        this.potentiometerEnded(cc.p(0, 0));
    },
    distanceBetweenPointAndPoint:function (point1, point2) {
        var dx = point1.x - point2.x;
        var dy = point1.y - point2.y;
        return Math.sqrt(dx * dx + dy * dy);
    },
    angleInDegreesBetweenLineFromPoint_toPoint_toLineFromPoint_toPoint:function (beginLineA, endLineA, beginLineB, endLineB) {
        var a = endLineA.x - beginLineA.x;
        var b = endLineA.y - beginLineA.y;
        var c = endLineB.x - beginLineB.x;
        var d = endLineB.y - beginLineB.y;
        var atanA = Math.atan2(a, b);
        var atanB = Math.atan2(c, d);
        return (atanA - atanB) * 180 / Math.PI;
    },
    potentiometerBegan:function (location) {
        this.setSelected(true);
        this.getThumbSprite().setColor(cc.color.GRAY);
    },
    potentiometerMoved:function (location) {
        var angle = this.angleInDegreesBetweenLineFromPoint_toPoint_toLineFromPoint_toPoint(this._progressTimer.getPosition(), location, this._progressTimer.getPosition(), this._previousLocation);
        if (angle > 180) {
            angle -= 360;
        }
        else if (angle < -180) {
            angle += 360;
        }
        this.setValue(this._value + angle / 360.0 * (this._maximumValue - this._minimumValue));
        this._previousLocation = location;
    },
    potentiometerEnded:function (location) {
        this.getThumbSprite().setColor(cc.color.WHITE);
        this.setSelected(false);
    },
    setThumbSprite:function (sprite) {
        this._thumbSprite = sprite;
    },
    getThumbSprite:function () {
        return this._thumbSprite;
    },
    setProgressTimer:function (sprite) {
        this._progressTimer = sprite;
    },
    getProgressTimer:function () {
        return this._progressTimer;
    },
    setPreviousLocation:function (point) {
        this._previousLocation = point;
    },
    getPreviousLocation:function () {
        return this._previousLocation;
    }
});
var _p = cc.ControlPotentiometer.prototype;
_p.value;
cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
_p.minValue;
cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
_p.maxValue;
cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
_p.progressTimer;
cc.defineGetterSetter(_p, "progressTimer", _p.getProgressTimer, _p.setProgressTimer);
_p.thumbSprite;
cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite, _p.setThumbSprite);
_p.prevLocation;
cc.defineGetterSetter(_p, "prevLocation", _p.getPreviousLocation, _p.setPreviousLocation);
_p = null;
cc.ControlPotentiometer.create = function (backgroundFile, progressFile, thumbFile) {
    return new cc.ControlPotentiometer(backgroundFile, progressFile, thumbFile);
};
cc.SCROLLVIEW_DIRECTION_NONE = -1;
cc.SCROLLVIEW_DIRECTION_HORIZONTAL = 0;
cc.SCROLLVIEW_DIRECTION_VERTICAL = 1;
cc.SCROLLVIEW_DIRECTION_BOTH = 2;
var SCROLL_DEACCEL_RATE = 0.95;
var SCROLL_DEACCEL_DIST = 1.0;
var BOUNCE_DURATION = 0.15;
var INSET_RATIO = 0.2;
var MOVE_INCH = 7.0/160.0;
var BOUNCE_BACK_FACTOR = 0.35;
cc.convertDistanceFromPointToInch = function(pointDis){
    var eglViewer = cc.view;
    var factor = (eglViewer.getScaleX() + eglViewer.getScaleY())/2;
    return (pointDis * factor) / 160;
};
cc.ScrollViewDelegate = cc.Class.extend({
    scrollViewDidScroll:function (view) {
    },
    scrollViewDidZoom:function (view) {
    }
});
cc.ScrollView = cc.Layer.extend({
    _zoomScale:0,
    _minZoomScale:0,
    _maxZoomScale:0,
    _delegate:null,
    _direction:cc.SCROLLVIEW_DIRECTION_BOTH,
    _dragging:false,
    _contentOffset:null,
    _container:null,
    _touchMoved:false,
    _maxInset:null,
    _minInset:null,
    _bounceable:false,
    _clippingToBounds:false,
    _scrollDistance:null,
    _touchPoint:null,
    _touchLength:0,
    _touches:null,
    _viewSize:null,
    _minScale:0,
    _maxScale:0,
    _parentScissorRect:null,
    _scissorRestored:false,
    _tmpViewRect:null,
    _touchListener: null,
    _className:"ScrollView",
    ctor:function (size, container) {
        cc.Layer.prototype.ctor.call(this);
        this._contentOffset = cc.p(0,0);
        this._maxInset = cc.p(0, 0);
        this._minInset = cc.p(0, 0);
        this._scrollDistance = cc.p(0, 0);
        this._touchPoint = cc.p(0, 0);
        this._touches = [];
        this._viewSize = cc.size(0, 0);
        this._parentScissorRect = new cc.Rect(0,0,0,0);
        this._tmpViewRect = new cc.Rect(0,0,0,0);
        if(container != undefined)
            this.initWithViewSize(size, container);
        else
            this.initWithViewSize(cc.size(200, 200), null);
    },
    init:function () {
        return this.initWithViewSize(cc.size(200, 200), null);
    },
    initWithViewSize:function (size, container) {
        var pZero = cc.p(0,0);
        if (cc.Layer.prototype.init.call(this)) {
            if (!container && !this._container) {
                container = new cc.Layer();
            }
            if (container) {
                this.setContainer(container);
            }
            this.setViewSize(size);
            this.setTouchEnabled(true);
            this._touches.length = 0;
            this._delegate = null;
            this._bounceable = true;
            this._clippingToBounds = true;
            this._direction = cc.SCROLLVIEW_DIRECTION_BOTH;
            this._container.setPosition(pZero);
            this._touchLength = 0.0;
            this._minScale = this._maxScale = 1.0;
            return true;
        }
        return false;
    },
    setContentOffset: function (offset, animated) {
        if (animated) {
            this.setContentOffsetInDuration(offset, BOUNCE_DURATION);
            return;
        }
        if (!this._bounceable) {
            var minOffset = this.minContainerOffset();
            var maxOffset = this.maxContainerOffset();
            offset.x = Math.max(minOffset.x, Math.min(maxOffset.x, offset.x));
            offset.y = Math.max(minOffset.y, Math.min(maxOffset.y, offset.y));
        }
        this._container.setPosition(offset);
        var locDelegate = this._delegate;
        if (locDelegate != null && locDelegate.scrollViewDidScroll) {
            locDelegate.scrollViewDidScroll(this);
        }
    },
    getContentOffset:function () {
        var locPos = this._container.getPosition();
        return cc.p(locPos.x, locPos.y);
    },
    setContentOffsetInDuration:function (offset, dt) {
        var scroll = cc.moveTo(dt, offset);
        var expire = cc.callFunc(this._stoppedAnimatedScroll, this);
        this._container.runAction(cc.sequence(scroll, expire));
        this.schedule(this._performedAnimatedScroll);
    },
    setZoomScale: function (scale, animated) {
        if (animated) {
            this.setZoomScaleInDuration(scale, BOUNCE_DURATION);
            return;
        }
        var locContainer = this._container;
        if (locContainer.getScale() !== scale) {
            var oldCenter, newCenter;
            var center;
            if (this._touchLength === 0.0) {
                var locViewSize = this._viewSize;
                center = cc.p(locViewSize.width * 0.5, locViewSize.height * 0.5);
                center = this.convertToWorldSpace(center);
            } else
                center = this._touchPoint;
            oldCenter = locContainer.convertToNodeSpace(center);
            locContainer.setScale(Math.max(this._minScale, Math.min(this._maxScale, scale)));
            newCenter = locContainer.convertToWorldSpace(oldCenter);
            var offset = cc.pSub(center, newCenter);
            if (this._delegate && this._delegate.scrollViewDidZoom)
                this._delegate.scrollViewDidZoom(this);
            this.setContentOffset(cc.pAdd(locContainer.getPosition(), offset));
        }
    },
    getZoomScale:function () {
        return this._container.getScale();
    },
    setZoomScaleInDuration:function (s, dt) {
        if (dt > 0) {
            var locScale = this._container.getScale();
            if (locScale !== s) {
                var scaleAction = cc.actionTween(dt, "zoomScale", locScale, s);
                this.runAction(scaleAction);
            }
        } else {
            this.setZoomScale(s);
        }
    },
    minContainerOffset:function () {
        var locContainer = this._container;
        var locContentSize = locContainer.getContentSize(), locViewSize = this._viewSize;
        return cc.p(locViewSize.width - locContentSize.width * locContainer.getScaleX(),
            locViewSize.height - locContentSize.height * locContainer.getScaleY());
    },
    maxContainerOffset:function () {
        return cc.p(0.0, 0.0);
    },
    isNodeVisible:function (node) {
        var offset = this.getContentOffset();
        var size = this.getViewSize();
        var scale = this.getZoomScale();
        var viewRect = cc.rect(-offset.x / scale, -offset.y / scale, size.width / scale, size.height / scale);
        return cc.rectIntersectsRect(viewRect, node.getBoundingBox());
    },
    pause:function (sender) {
        this._container.pause();
        var selChildren = this._container.getChildren();
        for (var i = 0; i < selChildren.length; i++) {
            selChildren[i].pause();
        }
        this._super();
    },
    resume:function (sender) {
        var selChildren = this._container.getChildren();
        for (var i = 0, len = selChildren.length; i < len; i++) {
            selChildren[i].resume();
        }
        this._container.resume();
        this._super();
    },
    isDragging:function () {
        return this._dragging;
    },
    isTouchMoved:function () {
        return this._touchMoved;
    },
    isBounceable:function () {
        return this._bounceable;
    },
    setBounceable:function (bounceable) {
        this._bounceable = bounceable;
    },
    getViewSize:function () {
        return this._viewSize;
    },
    setViewSize:function (size) {
        this._viewSize = size;
        cc.Node.prototype.setContentSize.call(this,size);
    },
    getContainer:function () {
        return this._container;
    },
    setContainer:function (container) {
        if (!container)
            return;
        this.removeAllChildren(true);
        this._container = container;
        container.ignoreAnchorPointForPosition(false);
        container.setAnchorPoint(0, 0);
        this.addChild(container);
        this.setViewSize(this._viewSize);
    },
    getDirection:function () {
        return this._direction;
    },
    setDirection:function (direction) {
        this._direction = direction;
    },
    getDelegate:function () {
        return this._delegate;
    },
    setDelegate:function (delegate) {
        this._delegate = delegate;
    },
    onTouchBegan:function (touch, event) {
        for (var c = this; c != null; c = c.parent) {
            if (!c.isVisible())
                return false;
        }
        var frame = this._getViewRect();
        var locContainer = this._container;
        var locPoint = locContainer.convertToWorldSpace(locContainer.convertTouchToNodeSpace(touch));
        var locTouches = this._touches;
        if (locTouches.length > 2 || this._touchMoved || !cc.rectContainsPoint(frame, locPoint))
            return false;
        locTouches.push(touch);
        if (locTouches.length === 1) {
            this._touchPoint = this.convertTouchToNodeSpace(touch);
            this._touchMoved = false;
            this._dragging = true;
            this._scrollDistance.x = 0;
            this._scrollDistance.y = 0;
            this._touchLength = 0.0;
        } else if (locTouches.length === 2) {
            this._touchPoint = cc.pMidpoint(this.convertTouchToNodeSpace(locTouches[0]),
                this.convertTouchToNodeSpace(locTouches[1]));
            this._touchLength = cc.pDistance(locContainer.convertTouchToNodeSpace(locTouches[0]),
                locContainer.convertTouchToNodeSpace(locTouches[1]));
            this._dragging = false;
        }
        return true;
    },
    onTouchMoved:function (touch, event) {
        if (!this.isVisible())
            return;
        this.setNodeDirty();
        if (this._touches.length === 1 && this._dragging) {
            this._touchMoved = true;
            var frame = this._getViewRect();
            var newPoint = this.convertTouchToNodeSpace(touch);
            var moveDistance = cc.pSub(newPoint, this._touchPoint);
            var dis = 0.0, locDirection = this._direction, pos;
            if (locDirection === cc.SCROLLVIEW_DIRECTION_VERTICAL){
                dis = moveDistance.y;
                pos = this._container.getPositionY();
                if (!(this.minContainerOffset().y <= pos && pos <= this.maxContainerOffset().y))
                    moveDistance.y *= BOUNCE_BACK_FACTOR;
            } else if (locDirection === cc.SCROLLVIEW_DIRECTION_HORIZONTAL){
                dis = moveDistance.x;
                pos = this._container.getPositionX();
                if (!(this.minContainerOffset().x <= pos && pos <= this.maxContainerOffset().x))
                    moveDistance.x *= BOUNCE_BACK_FACTOR;
            }else {
                dis = Math.sqrt(moveDistance.x * moveDistance.x + moveDistance.y * moveDistance.y);
                pos = this._container.getPositionY();
                var _minOffset = this.minContainerOffset(), _maxOffset = this.maxContainerOffset();
                if (!(_minOffset.y <= pos && pos <= _maxOffset.y))
                    moveDistance.y *= BOUNCE_BACK_FACTOR;
                pos = this._container.getPositionX();
                if (!(_minOffset.x <= pos && pos <= _maxOffset.x))
                    moveDistance.x *= BOUNCE_BACK_FACTOR;
            }
            if (!this._touchMoved && Math.abs(cc.convertDistanceFromPointToInch(dis)) < MOVE_INCH ){
                return;
            }
            if (!this._touchMoved){
                moveDistance.x = 0;
                moveDistance.y = 0;
            }
            this._touchPoint = newPoint;
            this._touchMoved = true;
            if (this._dragging) {
                switch (locDirection) {
                    case cc.SCROLLVIEW_DIRECTION_VERTICAL:
                        moveDistance.x = 0.0;
                        break;
                    case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
                        moveDistance.y = 0.0;
                        break;
                    default:
                        break;
                }
                var locPosition = this._container.getPosition();
                var newX = locPosition.x + moveDistance.x;
                var newY = locPosition.y + moveDistance.y;
                this._scrollDistance = moveDistance;
                this.setContentOffset(cc.p(newX, newY));
            }
        } else if (this._touches.length === 2 && !this._dragging) {
            var len = cc.pDistance(this._container.convertTouchToNodeSpace(this._touches[0]),
                this._container.convertTouchToNodeSpace(this._touches[1]));
            this.setZoomScale(this.getZoomScale() * len / this._touchLength);
        }
    },
    onTouchEnded:function (touch, event) {
        if (!this.isVisible())
            return;
        if (this._touches.length === 1 && this._touchMoved)
            this.schedule(this._deaccelerateScrolling);
        this._touches.length = 0;
        this._dragging = false;
        this._touchMoved = false;
    },
    onTouchCancelled:function (touch, event) {
        if (!this.isVisible())
            return;
        this._touches.length = 0;
        this._dragging = false;
        this._touchMoved = false;
    },
    setContentSize: function (size, height) {
        if (this.getContainer() !== null) {
            if(height === undefined)
                this.getContainer().setContentSize(size);
            else
                this.getContainer().setContentSize(size, height);
            this.updateInset();
        }
    },
    _setWidth: function (value) {
        var container = this.getContainer();
        if (container !== null) {
            container._setWidth(value);
            this.updateInset();
        }
    },
    _setHeight: function (value) {
        var container = this.getContainer();
        if (container !== null) {
            container._setHeight(value);
            this.updateInset();
        }
    },
    getContentSize:function () {
        return this._container.getContentSize();
    },
    updateInset:function () {
        if (this.getContainer() !== null) {
            var locViewSize = this._viewSize;
            var tempOffset = this.maxContainerOffset();
            this._maxInset.x = tempOffset.x + locViewSize.width * INSET_RATIO;
            this._maxInset.y = tempOffset.y + locViewSize.height * INSET_RATIO;
            tempOffset = this.minContainerOffset();
            this._minInset.x = tempOffset.x - locViewSize.width * INSET_RATIO;
            this._minInset.y = tempOffset.y - locViewSize.height * INSET_RATIO;
        }
    },
    isClippingToBounds:function () {
        return this._clippingToBounds;
    },
    setClippingToBounds:function (clippingToBounds) {
        this._clippingToBounds = clippingToBounds;
    },
    addChild:function (child, zOrder, tag) {
        if (!child)
            throw new Error("child must not nil!");
        zOrder = zOrder || child.getLocalZOrder();
        tag = tag || child.getTag();
        if (this._container !== child) {
            this._container.addChild(child, zOrder, tag);
        } else {
            cc.Layer.prototype.addChild.call(this, child, zOrder, tag);
        }
    },
    isTouchEnabled: function(){
        return this._touchListener !== null;
    },
    setTouchEnabled:function (e) {
        if(this._touchListener)
            cc.eventManager.removeListener(this._touchListener);
        this._touchListener = null;
        if (!e) {
            this._dragging = false;
            this._touchMoved = false;
            this._touches.length = 0;
        } else {
            var listener = cc.EventListener.create({
                event: cc.EventListener.TOUCH_ONE_BY_ONE
            });
            if(this.onTouchBegan)
                listener.onTouchBegan = this.onTouchBegan.bind(this);
            if(this.onTouchMoved)
                listener.onTouchMoved = this.onTouchMoved.bind(this);
            if(this.onTouchEnded)
                listener.onTouchEnded = this.onTouchEnded.bind(this);
            if(this.onTouchCancelled)
                listener.onTouchCancelled = this.onTouchCancelled.bind(this);
            this._touchListener = listener;
            cc.eventManager.addListener(listener, this);
        }
    },
    _initWithViewSize:function (size) {
        return null;
    },
    _relocateContainer:function (animated) {
        var min = this.minContainerOffset();
        var max = this.maxContainerOffset();
        var locDirection = this._direction;
        var oldPoint = this._container.getPosition();
        var newX = oldPoint.x;
        var newY = oldPoint.y;
        if (locDirection === cc.SCROLLVIEW_DIRECTION_BOTH || locDirection === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) {
            newX = Math.max(newX, min.x);
            newX = Math.min(newX, max.x);
        }
        if (locDirection === cc.SCROLLVIEW_DIRECTION_BOTH || locDirection === cc.SCROLLVIEW_DIRECTION_VERTICAL) {
            newY = Math.min(newY, max.y);
            newY = Math.max(newY, min.y);
        }
        if (newY !== oldPoint.y || newX !== oldPoint.x) {
            this.setContentOffset(cc.p(newX, newY), animated);
        }
    },
    _deaccelerateScrolling:function (dt) {
        if (this._dragging) {
            this.unschedule(this._deaccelerateScrolling);
            return;
        }
        var maxInset, minInset;
        var oldPosition = this._container.getPosition();
        var locScrollDistance = this._scrollDistance;
        this._container.setPosition(oldPosition.x + locScrollDistance.x , oldPosition.y + locScrollDistance.y);
        if (this._bounceable) {
            maxInset = this._maxInset;
            minInset = this._minInset;
        } else {
            maxInset = this.maxContainerOffset();
            minInset = this.minContainerOffset();
        }
        var newX = this._container.getPositionX();
        var newY = this._container.getPositionY();
        locScrollDistance.x = locScrollDistance.x * SCROLL_DEACCEL_RATE;
        locScrollDistance.y = locScrollDistance.y * SCROLL_DEACCEL_RATE;
        this.setContentOffset(cc.p(newX, newY));
        if ((Math.abs(locScrollDistance.x) <= SCROLL_DEACCEL_DIST &&
            Math.abs(locScrollDistance.y) <= SCROLL_DEACCEL_DIST) ||
            newY > maxInset.y || newY < minInset.y ||
            newX > maxInset.x || newX < minInset.x ||
            newX === maxInset.x || newX === minInset.x ||
            newY === maxInset.y || newY === minInset.y) {
            this.unschedule(this._deaccelerateScrolling);
            this._relocateContainer(true);
        }
    },
    _performedAnimatedScroll:function (dt) {
        if (this._dragging) {
            this.unschedule(this._performedAnimatedScroll);
            return;
        }
        if (this._delegate && this._delegate.scrollViewDidScroll)
            this._delegate.scrollViewDidScroll(this);
    },
    _stoppedAnimatedScroll:function (node) {
        this.unschedule(this._performedAnimatedScroll);
        if (this._delegate && this._delegate.scrollViewDidScroll) {
            this._delegate.scrollViewDidScroll(this);
        }
    },
    _handleZoom:function () {
    },
    _getViewRect:function(){
        var screenPos = this.convertToWorldSpace(cc.p(0,0));
        var locViewSize = this._viewSize;
        var scaleX = this.getScaleX();
        var scaleY = this.getScaleY();
        for (var p = this._parent; p != null; p = p.getParent()) {
            scaleX *= p.getScaleX();
            scaleY *= p.getScaleY();
        }
        if (scaleX < 0) {
            screenPos.x += locViewSize.width * scaleX;
            scaleX = -scaleX;
        }
        if (scaleY < 0) {
            screenPos.y += locViewSize.height * scaleY;
            scaleY = -scaleY;
        }
        var locViewRect = this._tmpViewRect;
        locViewRect.x = screenPos.x;
        locViewRect.y = screenPos.y;
        locViewRect.width = locViewSize.width * scaleX;
        locViewRect.height = locViewSize.height * scaleY;
        return locViewRect;
    },
    _createRenderCmd: function(){
        if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
            return new cc.ScrollView.CanvasRenderCmd(this);
        } else {
            return new cc.ScrollView.WebGLRenderCmd(this);
        }
    }
});
var _p = cc.ScrollView.prototype;
_p.minOffset;
cc.defineGetterSetter(_p, "minOffset", _p.minContainerOffset);
_p.maxOffset;
cc.defineGetterSetter(_p, "maxOffset", _p.maxContainerOffset);
_p.bounceable;
cc.defineGetterSetter(_p, "bounceable", _p.isBounceable, _p.setBounceable);
_p.viewSize;
cc.defineGetterSetter(_p, "viewSize", _p.getViewSize, _p.setViewSize);
_p.container;
cc.defineGetterSetter(_p, "container", _p.getContainer, _p.setContainer);
_p.direction;
cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
_p.delegate;
cc.defineGetterSetter(_p, "delegate", _p.getDelegate, _p.setDelegate);
_p.clippingToBounds;
cc.defineGetterSetter(_p, "clippingToBounds", _p.isClippingToBounds, _p.setClippingToBounds);
_p = null;
cc.ScrollView.create = function (size, container) {
    return new cc.ScrollView(size, container);
};
(function() {
    cc.ScrollView.CanvasRenderCmd = function(renderable){
        cc.Layer.CanvasRenderCmd.call(this, renderable);
        this._needDraw = false;
        this.startCmd = new cc.CustomRenderCmd(this, this._startCmd);
        this.startCmd._canUseDirtyRegion = true;
        this.endCmd = new cc.CustomRenderCmd(this, this._endCmd);
        this.endCmd._canUseDirtyRegion = true;
    };
    var proto = cc.ScrollView.CanvasRenderCmd.prototype = Object.create(cc.Layer.CanvasRenderCmd.prototype);
    proto.constructor = cc.ScrollView.CanvasRenderCmd;
    proto._startCmd = function(ctx, scaleX, scaleY){
        var node = this._node;
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        wrapper.save();
        if (node._clippingToBounds) {
            this._scissorRestored = false;
            wrapper.setTransform(this._worldTransform, scaleX, scaleY);
            var locScaleX = node.getScaleX(), locScaleY = node.getScaleY();
            var getWidth = (node._viewSize.width * locScaleX);
            var getHeight = (node._viewSize.height * locScaleY);
            context.beginPath();
            context.rect(0, 0, getWidth, -getHeight);
            context.closePath();
            context.clip();
        }
    };
    proto._endCmd = function(wrapper){
        wrapper = wrapper || cc._renderContext;
        wrapper.restore();
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible) return;
        var i, locChildren = node._children, childrenLen;
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this.startCmd);
        if (locChildren && locChildren.length > 0) {
            childrenLen = locChildren.length;
            node.sortAllChildren();
            for (i = 0; i < childrenLen; i++) {
                locChildren[i]._renderCmd.visit(this);
            }
        }
        cc.renderer.pushRenderCommand(this.endCmd);
        this._dirtyFlag = 0;
    };
})();
cc.SortableObject = cc.Class.extend({
    setObjectID:function (objectId) {
    },
    getObjectID:function () {
        return 0;
    }
});
cc.SortedObject = cc.SortableObject.extend({
    _objectID:0,
    ctor:function () {
        this._objectID = 0;
    },
    setObjectID:function (objectID) {
        this._objectID = objectID;
    },
    getObjectID:function () {
        return this._objectID;
    }
});
var _compareObject = function (val1, val2) {
    return (val1.getObjectID() - val2.getObjectID());
};
cc.ArrayForObjectSorting = cc.Class.extend({
    _saveObjectArr:null,
    ctor:function () {
        this._saveObjectArr = [];
    },
    insertSortedObject:function (addObject) {
        if(!addObject)
            throw new Error("cc.ArrayForObjectSorting.insertSortedObject(): addObject should be non-null.");
        var idx = this.indexOfSortedObject(addObject);
        this.insertObject(addObject, idx);
    },
    removeSortedObject:function (delObject) {
        if (this.count() === 0) {
            return;
        }
        var idx = this.indexOfSortedObject(delObject);
        if (idx < this.count() && idx !== cc.INVALID_INDEX) {
            var foundObj = this.objectAtIndex(idx);
            if (foundObj.getObjectID() === delObject.getObjectID()) {
                this.removeObjectAtIndex(idx);
            }
        }
    },
    setObjectID_ofSortedObject:function (tag, setObject) {
        var idx = this.indexOfSortedObject(setObject);
        if (idx < this.count() && idx !== cc.INVALID_INDEX) {
            var foundObj = this.objectAtIndex(idx);
            if (foundObj.getObjectID() === setObject.getObjectID()) {
                this.removeObjectAtIndex(idx);
                foundObj.setObjectID(tag);
                this.insertSortedObject(foundObj);
            }
        }
    },
    objectWithObjectID:function (tag) {
        if (this.count() === 0) {
            return null;
        }
        var foundObj = new cc.SortedObject();
        foundObj.setObjectID(tag);
        var idx = this.indexOfSortedObject(foundObj);
        if (idx < this.count() && idx !== cc.INVALID_INDEX) {
            foundObj = this.objectAtIndex(idx);
            if (foundObj.getObjectID() !== tag)
                foundObj = null;
        }
        return foundObj;
    },
    getObjectWithObjectID:function (tag) {
        return null;
    },
    indexOfSortedObject:function (idxObj) {
        var idx = 0;
        if (idxObj) {
            var uPrevObjectID = 0;
            var uOfSortObjectID = idxObj.getObjectID();
            var locObjectArr = this._saveObjectArr;
            for (var i = 0; i < locObjectArr.length; i++) {
                var pSortableObj = locObjectArr[i];
                var curObjectID = pSortableObj.getObjectID();
                if ((uOfSortObjectID === curObjectID) ||
                    (uOfSortObjectID >= uPrevObjectID && uOfSortObjectID < curObjectID)) {
                    break;
                }
                uPrevObjectID = curObjectID;
                idx++;
            }
        } else {
            idx = cc.INVALID_INDEX;
        }
        return idx;
    },
    count:function () {
        return this._saveObjectArr.length;
    },
    lastObject:function () {
        var locObjectArr = this._saveObjectArr;
        if (locObjectArr.length === 0)
            return null;
        return locObjectArr[locObjectArr.length - 1];
    },
    objectAtIndex:function (idx) {
        return this._saveObjectArr[idx];
    },
    addObject:function (addObj) {
        this._saveObjectArr.push(addObj);
        this._saveObjectArr.sort(_compareObject);
    },
    removeObjectAtIndex:function (idx) {
        this._saveObjectArr.splice(idx, 1);
        this._saveObjectArr.sort(_compareObject);
    },
    insertObject:function (addObj, idx) {
        this._saveObjectArr.splice(idx, 0, addObj);
        this._saveObjectArr.sort(_compareObject);
    }
});
cc.TABLEVIEW_FILL_TOPDOWN = 0;
cc.TABLEVIEW_FILL_BOTTOMUP = 1;
cc.TableViewCell = cc.Node.extend({
    _idx:0,
    _className:"TableViewCell",
    getIdx:function () {
        return this._idx;
    },
    setIdx:function (idx) {
        this._idx = idx;
    },
    reset:function () {
        this._idx = cc.INVALID_INDEX;
    },
    setObjectID:function (idx) {
        this._idx = idx;
    },
    getObjectID:function () {
        return this._idx;
    }
});
var _p = cc.TableViewCell.prototype;
_p.objectId;
cc.defineGetterSetter(_p, "objectId", _p.getObjectID, _p.setObjectID);
_p = null;
cc.TableViewDelegate = cc.ScrollViewDelegate.extend({
    tableCellTouched:function (table, cell) {
    },
    tableCellHighlight:function(table, cell){
    },
    tableCellUnhighlight:function(table, cell){
    },
    tableCellWillRecycle:function(table, cell){
    }
});
cc.TableViewDataSource = cc.Class.extend({
    tableCellSizeForIndex:function(table, idx){
        return this.cellSizeForTable(table);
    },
    cellSizeForTable:function (table) {
        return cc.size(0,0);
    },
    tableCellAtIndex:function (table, idx) {
        return null;
    },
    numberOfCellsInTableView:function (table) {
        return 0;
    }
});
cc.TableView = cc.ScrollView.extend({
    _vOrdering:null,
    _indices:null,
    _cellsFreed:null,
    _dataSource:null,
    _tableViewDelegate:null,
    _oldDirection:null,
    _cellsPositions:null,
    _touchedCell:null,
    ctor:function (dataSource, size, container) {
        cc.ScrollView.prototype.ctor.call(this);
        this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE;
        this._cellsPositions = [];
        this.initWithViewSize(size, container);
        this.setDataSource(dataSource);
        this._updateCellPositions();
        this._updateContentSize();
    },
    __indexFromOffset:function (offset) {
        var low = 0;
        var high = this._dataSource.numberOfCellsInTableView(this) - 1;
        var search;
        switch (this.getDirection()) {
            case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
                search = offset.x;
                break;
            default:
                search = offset.y;
                break;
        }
        var locCellsPositions = this._cellsPositions;
        while (high >= low){
            var index = 0|(low + (high - low) / 2);
            var cellStart = locCellsPositions[index];
            var cellEnd = locCellsPositions[index + 1];
            if (search >= cellStart && search <= cellEnd){
                return index;
            } else if (search < cellStart){
                high = index - 1;
            }else {
                low = index + 1;
            }
        }
        if (low <= 0)
            return 0;
        return -1;
    },
    _indexFromOffset:function (offset) {
        var locOffset = {x: offset.x, y: offset.y};
        var locDataSource = this._dataSource;
        var maxIdx = locDataSource.numberOfCellsInTableView(this) - 1;
        if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN)
            locOffset.y = this.getContainer().getContentSize().height - locOffset.y;
        var index = this.__indexFromOffset(locOffset);
        if (index !== -1) {
            index = Math.max(0, index);
            if (index > maxIdx)
                index = cc.INVALID_INDEX;
        }
        return index;
    },
    __offsetFromIndex:function (index) {
        var offset;
        switch (this.getDirection()) {
            case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
                offset = cc.p(this._cellsPositions[index], 0);
                break;
            default:
                offset = cc.p(0, this._cellsPositions[index]);
                break;
        }
        return offset;
    },
    _offsetFromIndex:function (index) {
        var offset = this.__offsetFromIndex(index);
        var cellSize = this._dataSource.tableCellSizeForIndex(this, index);
        if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN)
            offset.y = this.getContainer().getContentSize().height - offset.y - cellSize.height;
        return offset;
    },
    _updateCellPositions:function(){
        var cellsCount = this._dataSource.numberOfCellsInTableView(this);
        var locCellsPositions = this._cellsPositions;
        if (cellsCount > 0){
            var currentPos = 0;
            var cellSize, locDataSource = this._dataSource;
            for (var i=0; i < cellsCount; i++) {
                locCellsPositions[i] = currentPos;
                cellSize = locDataSource.tableCellSizeForIndex(this, i);
                switch (this.getDirection()) {
                    case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
                        currentPos += cellSize.width;
                        break;
                    default:
                        currentPos += cellSize.height;
                        break;
                }
            }
            this._cellsPositions[cellsCount] = currentPos;//1 extra value allows us to get right/bottom of the last cell
        }
    },
    _updateContentSize:function () {
        var size = cc.size(0, 0);
        var cellsCount = this._dataSource.numberOfCellsInTableView(this);
        if(cellsCount > 0){
            var maxPosition = this._cellsPositions[cellsCount];
            switch (this.getDirection()) {
                case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
                    size = cc.size(maxPosition, this._viewSize.height);
                    break;
                default:
                    size = cc.size(this._viewSize.width, maxPosition);
                    break;
            }
        }
        this.setContentSize(size);
        if (this._oldDirection !== this._direction) {
            if (this._direction === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) {
                this.setContentOffset(cc.p(0, 0));
            } else {
                this.setContentOffset(cc.p(0, this.minContainerOffset().y));
            }
            this._oldDirection = this._direction;
        }
    },
    _moveCellOutOfSight:function (cell) {
        if(this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle)
            this._tableViewDelegate.tableCellWillRecycle(this, cell);
        this._cellsFreed.addObject(cell);
        this._cellsUsed.removeSortedObject(cell);
        cc.arrayRemoveObject(this._indices, cell.getIdx());
        cell.reset();
        if (cell.getParent() === this.getContainer()) {
            this.getContainer().removeChild(cell, true);
        }
    },
    _setIndexForCell:function (index, cell) {
        cell.setAnchorPoint(0, 0);
        cell.setPosition(this._offsetFromIndex(index));
        cell.setIdx(index);
    },
    _addCellIfNecessary:function (cell) {
        if (cell.getParent() !== this.getContainer()) {
            this.getContainer().addChild(cell);
        }
        this._cellsUsed.insertSortedObject(cell);
        var locIndices = this._indices, addIdx = cell.getIdx();
        if(locIndices.indexOf(addIdx) === -1){
            locIndices.push(addIdx);
            locIndices.sort(function(a,b){return a-b;});
        }
    },
    getDataSource:function () {
        return this._dataSource;
    },
    setDataSource:function (source) {
        this._dataSource = source;
    },
    getDelegate:function () {
        return this._tableViewDelegate;
    },
    setDelegate:function (delegate) {
        this._tableViewDelegate = delegate;
    },
    setVerticalFillOrder:function (fillOrder) {
        if (this._vOrdering !== fillOrder) {
            this._vOrdering = fillOrder;
            if (this._cellsUsed.count() > 0) {
                this.reloadData();
            }
        }
    },
    getVerticalFillOrder:function () {
        return this._vOrdering;
    },
    initWithViewSize:function (size, container) {
        if (cc.ScrollView.prototype.initWithViewSize.call(this, size, container)) {
            this._cellsUsed = new cc.ArrayForObjectSorting();
            this._cellsFreed = new cc.ArrayForObjectSorting();
            this._indices = [];
            this._tableViewDelegate = null;
            this._vOrdering = cc.TABLEVIEW_FILL_BOTTOMUP;
            this.setDirection(cc.SCROLLVIEW_DIRECTION_VERTICAL);
            cc.ScrollView.prototype.setDelegate.call(this, this);
            return true;
        }
        return false;
    },
    updateCellAtIndex:function (idx) {
        if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
            return;
        var cell = this.cellAtIndex(idx);
        if (cell)
            this._moveCellOutOfSight(cell);
        cell = this._dataSource.tableCellAtIndex(this, idx);
        this._setIndexForCell(idx, cell);
        this._addCellIfNecessary(cell);
    },
    insertCellAtIndex:function (idx) {
        if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
            return;
        var newIdx, locCellsUsed = this._cellsUsed;
        var cell = locCellsUsed.objectWithObjectID(idx);
        if (cell) {
            newIdx = locCellsUsed.indexOfSortedObject(cell);
            for (var i = newIdx; i < locCellsUsed.count(); i++) {
                cell = locCellsUsed.objectAtIndex(i);
                this._setIndexForCell(cell.getIdx() + 1, cell);
            }
        }
        cell = this._dataSource.tableCellAtIndex(this, idx);
        this._setIndexForCell(idx, cell);
        this._addCellIfNecessary(cell);
        this._updateCellPositions();
        this._updateContentSize();
    },
    removeCellAtIndex:function (idx) {
        if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
            return;
        var cell = this.cellAtIndex(idx);
        if (!cell)
            return;
        var locCellsUsed = this._cellsUsed;
        var newIdx = locCellsUsed.indexOfSortedObject(cell);
        this._moveCellOutOfSight(cell);
        cc.arrayRemoveObject(this._indices, idx);
        this._updateCellPositions();
        for (var i = locCellsUsed.count() - 1; i > newIdx; i--) {
            cell = locCellsUsed.objectAtIndex(i);
            this._setIndexForCell(cell.getIdx() - 1, cell);
        }
    },
    reloadData:function () {
        this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE;
        var locCellsUsed = this._cellsUsed, locCellsFreed = this._cellsFreed, locContainer = this.getContainer();
        for (var i = 0, len = locCellsUsed.count(); i < len; i++) {
            var cell = locCellsUsed.objectAtIndex(i);
            if(this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle)
                this._tableViewDelegate.tableCellWillRecycle(this, cell);
            locCellsFreed.addObject(cell);
            cell.reset();
            if (cell.getParent() === locContainer)
                locContainer.removeChild(cell, true);
        }
        this._indices = [];
        this._cellsUsed = new cc.ArrayForObjectSorting();
        this._updateCellPositions();
        this._updateContentSize();
        if (this._dataSource.numberOfCellsInTableView(this) > 0)
            this.scrollViewDidScroll(this);
        this.setNodeDirty();
    },
    dequeueCell:function () {
        if (this._cellsFreed.count() === 0) {
            return null;
        } else {
            var cell = this._cellsFreed.objectAtIndex(0);
            this._cellsFreed.removeObjectAtIndex(0);
            return cell;
        }
    },
    cellAtIndex:function (idx) {
        var i = this._indices.indexOf(idx);
        if (i === -1)
            return null;
        return this._cellsUsed.objectWithObjectID(idx);
    },
    scrollViewDidScroll:function (view) {
        var locDataSource = this._dataSource;
        var countOfItems = locDataSource.numberOfCellsInTableView(this);
        if (0 === countOfItems)
            return;
        if (this._tableViewDelegate !== null && this._tableViewDelegate.scrollViewDidScroll)
            this._tableViewDelegate.scrollViewDidScroll(this);
        var  idx = 0, locViewSize = this._viewSize, locContainer = this.getContainer();
        var offset = this.getContentOffset();
        offset.x *= -1;
        offset.y *= -1;
        var maxIdx = Math.max(countOfItems-1, 0);
        if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN)
            offset.y = offset.y + locViewSize.height/locContainer.getScaleY();
        var startIdx = this._indexFromOffset(offset);
        if (startIdx === cc.INVALID_INDEX)
            startIdx = countOfItems - 1;
        if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN)
            offset.y -= locViewSize.height/locContainer.getScaleY();
        else
            offset.y += locViewSize.height/locContainer.getScaleY();
        offset.x += locViewSize.width/locContainer.getScaleX();
        var endIdx = this._indexFromOffset(offset);
        if (endIdx === cc.INVALID_INDEX)
            endIdx = countOfItems - 1;
        var cell, locCellsUsed = this._cellsUsed;
        if (locCellsUsed.count() > 0) {
            cell = locCellsUsed.objectAtIndex(0);
            idx = cell.getIdx();
            while (idx < startIdx) {
                this._moveCellOutOfSight(cell);
                if (locCellsUsed.count() > 0) {
                    cell = locCellsUsed.objectAtIndex(0);
                    idx = cell.getIdx();
                } else
                    break;
            }
        }
        if (locCellsUsed.count() > 0) {
            cell = locCellsUsed.lastObject();
            idx = cell.getIdx();
            while (idx <= maxIdx && idx > endIdx) {
                this._moveCellOutOfSight(cell);
                if (locCellsUsed.count() > 0) {
                    cell = locCellsUsed.lastObject();
                    idx = cell.getIdx();
                } else
                    break;
            }
        }
        var locIndices = this._indices;
        for (var i = startIdx; i <= endIdx; i++) {
            if (locIndices.indexOf(i) !== -1)
                continue;
            this.updateCellAtIndex(i);
        }
    },
    scrollViewDidZoom:function (view) {
    },
    onTouchEnded:function (touch, event) {
        if (!this.isVisible())
            return;
        if (this._touchedCell){
            var bb = this.getBoundingBox();
            var tmpOrigin = cc.p(bb.x, bb.y);
            tmpOrigin = this._parent.convertToWorldSpace(tmpOrigin);
            bb.x = tmpOrigin.x;
            bb.y = tmpOrigin.y;
            var locTableViewDelegate = this._tableViewDelegate;
            if (cc.rectContainsPoint(bb, touch.getLocation()) && locTableViewDelegate !== null){
                if(locTableViewDelegate.tableCellUnhighlight)
                    locTableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
                if(locTableViewDelegate.tableCellTouched)
                    locTableViewDelegate.tableCellTouched(this, this._touchedCell);
            }
            this._touchedCell = null;
        }
        cc.ScrollView.prototype.onTouchEnded.call(this, touch, event);
    },
    onTouchBegan:function(touch, event){
        for (var c = this; c != null; c = c.parent) {
            if (!c.isVisible())
                return false;
        }
        var touchResult = cc.ScrollView.prototype.onTouchBegan.call(this, touch, event);
        if(this._touches.length === 1) {
            var index, point;
            point = this.getContainer().convertTouchToNodeSpace(touch);
            index = this._indexFromOffset(point);
            if (index === cc.INVALID_INDEX)
                this._touchedCell = null;
            else
                this._touchedCell  = this.cellAtIndex(index);
            if (this._touchedCell && this._tableViewDelegate !== null && this._tableViewDelegate.tableCellHighlight)
                this._tableViewDelegate.tableCellHighlight(this, this._touchedCell);
        } else if(this._touchedCell) {
            if(this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight)
                this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
            this._touchedCell = null;
        }
        return touchResult;
    },
    onTouchMoved: function(touch, event){
        cc.ScrollView.prototype.onTouchMoved.call(this, touch, event);
        if (this._touchedCell && this.isTouchMoved()) {
            if(this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight)
                this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
            this._touchedCell = null;
        }
    },
    onTouchCancelled: function(touch, event){
        cc.ScrollView.prototype.onTouchCancelled.call(this, touch, event);
        if (this._touchedCell) {
            if(this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight)
                this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
            this._touchedCell = null;
        }
    }
});
var _p = cc.TableView.prototype;
_p.dataSource;
cc.defineGetterSetter(_p, "dataSource", _p.getDataSource, _p.setDataSource);
_p.delegate;
cc.defineGetterSetter(_p, "delegate", _p.getDelegate, _p.setDelegate);
_p.verticalFillOrder;
cc.defineGetterSetter(_p, "verticalFillOrder", _p.getVerticalFillOrder, _p.setVerticalFillOrder);
_p = null;
cc.TableView.create = function (dataSource, size, container) {
    return new cc.TableView(dataSource, size, container);
};
(function() {
    cc.ScrollView.WebGLRenderCmd = function(renderable){
        cc.Layer.WebGLRenderCmd.call(this, renderable);
        this._needDraw = false;
        this.startCmd = new cc.CustomRenderCmd(this, this._startCmd);
        this.endCmd = new cc.CustomRenderCmd(this, this._endCmd);
    };
    var proto = cc.ScrollView.WebGLRenderCmd.prototype = Object.create(cc.Layer.WebGLRenderCmd.prototype);
    proto.constructor = cc.ScrollView.WebGLRenderCmd;
    proto._startCmd = function(){
        var node = this._node;
        var EGLViewer = cc.view;
        var frame = node._getViewRect();
        if(EGLViewer.isScissorEnabled()){
            node._scissorRestored = true;
            node._parentScissorRect = EGLViewer.getScissorRect();
            if (cc.rectIntersection(frame, node._parentScissorRect)) {
                var locPSRect = node._parentScissorRect;
                var x = Math.max(frame.x, locPSRect.x);
                var y = Math.max(frame.y, locPSRect.y);
                var xx = Math.min(frame.x + frame.width, locPSRect.x + locPSRect.width);
                var yy = Math.min(frame.y + frame.height, locPSRect.y + locPSRect.height);
                EGLViewer.setScissorInPoints(x, y, xx - x, yy - y);
            }
        }else{
            var ctx = cc._renderContext;
            ctx.enable(ctx.SCISSOR_TEST);
            EGLViewer.setScissorInPoints(frame.x, frame.y, frame.width, frame.height);
        }
    };
    proto._endCmd = function(){
        var node = this._node;
        if (node._scissorRestored) {
            var rect = node._parentScissorRect;
            cc.view.setScissorInPoints(rect.x, rect.y, rect.width, rect.height);
        }else{
            var ctx = cc._renderContext;
            ctx.disable(ctx.SCISSOR_TEST);
        }
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible) return;
        var i, locChildren = node._children, selChild, childrenLen;
        this._syncStatus(parentCmd);
        if (node._clippingToBounds) {
            cc.renderer.pushRenderCommand(this.startCmd);
        }
        if (locChildren && locChildren.length > 0) {
            childrenLen = locChildren.length;
            for (i = 0; i < childrenLen; i++) {
                selChild = locChildren[i];
                if (selChild && selChild._localZOrder < 0)
                    selChild._renderCmd.visit();
                else
                    break;
            }
            for (; i < childrenLen; i++)
                locChildren[i]._renderCmd.visit();
        }
        if (node._clippingToBounds) {
            cc.renderer.pushRenderCommand(this.endCmd);
        }
        this._dirtyFlag = 0;
    };
})();
var PROPERTY_POSITION = "position";
var PROPERTY_CONTENTSIZE = "contentSize";
var PROPERTY_SKEW = "skew";
var PROPERTY_ANCHORPOINT = "anchorPoint";
var PROPERTY_SCALE = "scale";
var PROPERTY_ROTATION = "rotation";
var PROPERTY_TAG = "tag";
var PROPERTY_IGNOREANCHORPOINTFORPOSITION = "ignoreAnchorPointForPosition";
var PROPERTY_VISIBLE = "visible";
var ASSERT_FAIL_UNEXPECTED_PROPERTY = function (propertyName) {
    cc.log("Unexpected property: '" + propertyName + "'!");
};
var ASSERT_FAIL_UNEXPECTED_PROPERTYTYPE = function (propertyName) {
    cc.log("Unexpected property type: '" + propertyName + "'!");
};
function BlockData(selMenuHander, target) {
    this.selMenuHander = selMenuHander;
    this.target = target;
}
function BlockCCControlData(selCCControlHandler, target, controlEvents) {
    this.selCCControlHandler = selCCControlHandler;
    this.target = target;
    this.controlEvents = controlEvents;
}
cc.NodeLoader = cc.Class.extend({
    _customProperties:null,
    ctor:function(){
        this._customProperties = new cc._Dictionary();
    },
    loadCCNode:function (parent, ccbReader) {
        return this._createCCNode(parent, ccbReader);
    },
    parseProperties:function (node, parent, ccbReader) {
        var numRegularProps = ccbReader.readInt(false);
        var numExturaProps = ccbReader.readInt(false);
        var propertyCount = numRegularProps + numExturaProps;
        for (var i = 0; i < propertyCount; i++) {
            var isExtraProp = (i >= numRegularProps);
            var type = ccbReader.readInt(false);
            var propertyName = ccbReader.readCachedString();
            var setProp = false;
            var platform = ccbReader.readByte();
            if ((platform === CCB_PLATFORM_ALL) ||(platform === CCB_PLATFORM_IOS) ||(platform === CCB_PLATFORM_MAC) )
                setProp = true;
            if(node instanceof cc.BuilderFile){
                if(node.getCCBFileNode() && isExtraProp){
                    node = node.getCCBFileNode();
                    var getExtraPropsNames = node.userObject;
                    setProp = getExtraPropsNames.indexOf(propertyName) !== -1;
                }
            } else if(isExtraProp && node === ccbReader.getAnimationManager().getRootNode()){
                var extraPropsNames = node.userObject;
                if(!extraPropsNames){
                    extraPropsNames = [];
                    node.userObject = extraPropsNames;
                }
                extraPropsNames.push(propertyName);
            }
            switch (type) {
                case CCB_PROPTYPE_POSITION:
                {
                    var position = this.parsePropTypePosition(node, parent, ccbReader, propertyName);
                    if (setProp)
                        this.onHandlePropTypePosition(node, parent, propertyName, position, ccbReader);
                    break;
                }
                case CCB_PROPTYPE_POINT:
                {
                    var point = this.parsePropTypePoint(node, parent, ccbReader);
                    if (setProp)
                        this.onHandlePropTypePoint(node, parent, propertyName, point, ccbReader);
                    break;
                }
                case CCB_PROPTYPE_POINTLOCK:
                {
                    var pointLock = this.parsePropTypePointLock(node, parent, ccbReader);
                    if (setProp)
                        this.onHandlePropTypePointLock(node, parent, propertyName, pointLock, ccbReader);
                    break;
                }
                case CCB_PROPTYPE_SIZE:
                {
                    var size = this.parsePropTypeSize(node, parent, ccbReader);
                    if (setProp)
                        this.onHandlePropTypeSize(node, parent, propertyName, size, ccbReader);
                    break;
                }
                case CCB_PROPTYPE_SCALELOCK:
                {
                    var scaleLock = this.parsePropTypeScaleLock(node, parent, ccbReader, propertyName);
                    if (setProp)
                        this.onHandlePropTypeScaleLock(node, parent, propertyName, scaleLock, ccbReader);
                    break;
                }
                case CCB_PROPTYPE_FLOATXY:
                {
                    var xy = this.parsePropTypeFloatXY(node, parent, ccbReader);
                    if (setProp)
                        this.onHandlePropTypeFloatXY(node, parent, propertyName, xy, ccbReader);
                    break;
                }
                case CCB_PROPTYPE_FLOAT:
                {
                    var f = this.parsePropTypeFloat(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeFloat(node, parent, propertyName, f, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_DEGREES:
                {
                    var degrees = this.parsePropTypeDegrees(node, parent, ccbReader, propertyName);
                    if (setProp) {
                        this.onHandlePropTypeDegrees(node, parent, propertyName, degrees, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_FLOATSCALE:
                {
                    var floatScale = this.parsePropTypeFloatScale(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeFloatScale(node, parent, propertyName, floatScale, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_INTEGER:
                {
                    var integer = this.parsePropTypeInteger(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeInteger(node, parent, propertyName, integer, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_INTEGERLABELED:
                {
                    var integerLabeled = this.parsePropTypeIntegerLabeled(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeIntegerLabeled(node, parent, propertyName, integerLabeled, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_FLOATVAR:
                {
                    var floatVar = this.parsePropTypeFloatVar(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeFloatVar(node, parent, propertyName, floatVar, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_CHECK:
                {
                    var check = this.parsePropTypeCheck(node, parent, ccbReader, propertyName);
                    if (setProp) {
                        this.onHandlePropTypeCheck(node, parent, propertyName, check, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_SPRITEFRAME:
                {
                    var ccSpriteFrame = this.parsePropTypeSpriteFrame(node, parent, ccbReader, propertyName);
                    if (setProp) {
                        this.onHandlePropTypeSpriteFrame(node, parent, propertyName, ccSpriteFrame, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_ANIMATION:
                {
                    var ccAnimation = this.parsePropTypeAnimation(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeAnimation(node, parent, propertyName, ccAnimation, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_TEXTURE:
                {
                    var ccTexture2D = this.parsePropTypeTexture(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeTexture(node, parent, propertyName, ccTexture2D, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_BYTE:
                {
                    var byteValue = this.parsePropTypeByte(node, parent, ccbReader, propertyName);
                    if (setProp) {
                        this.onHandlePropTypeByte(node, parent, propertyName, byteValue, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_COLOR3:
                {
                    var color = this.parsePropTypeColor3(node, parent, ccbReader, propertyName);
                    if (setProp) {
                        this.onHandlePropTypeColor3(node, parent, propertyName, color, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_COLOR4VAR:
                {
                    var color4FVar = this.parsePropTypeColor4FVar(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeColor4FVar(node, parent, propertyName, color4FVar, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_FLIP:
                {
                    var flip = this.parsePropTypeFlip(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeFlip(node, parent, propertyName, flip, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_BLENDMODE:
                {
                    var blendFunc = this.parsePropTypeBlendFunc(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeBlendFunc(node, parent, propertyName, blendFunc, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_FNTFILE:
                {
                    var fntFile = ccbReader.getCCBRootPath() + this.parsePropTypeFntFile(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeFntFile(node, parent, propertyName, fntFile, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_FONTTTF:
                {
                    var fontTTF = this.parsePropTypeFontTTF(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeFontTTF(node, parent, propertyName, fontTTF, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_STRING:
                {
                    var stringValue = this.parsePropTypeString(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeString(node, parent, propertyName, stringValue, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_TEXT:
                {
                    var textValue = this.parsePropTypeText(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeText(node, parent, propertyName, textValue, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_BLOCK:
                {
                    var blockData = this.parsePropTypeBlock(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeBlock(node, parent, propertyName, blockData, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_BLOCKCCCONTROL:
                {
                    var blockCCControlData = this.parsePropTypeBlockCCControl(node, parent, ccbReader);
                    if (setProp && blockCCControlData != null) {
                        this.onHandlePropTypeBlockCCControl(node, parent, propertyName, blockCCControlData, ccbReader);
                    }
                    break;
                }
                case CCB_PROPTYPE_CCBFILE:
                {
                    var ccbFileNode = this.parsePropTypeCCBFile(node, parent, ccbReader);
                    if (setProp) {
                        this.onHandlePropTypeCCBFile(node, parent, propertyName, ccbFileNode, ccbReader);
                    }
                    break;
                }
                default:
                    ASSERT_FAIL_UNEXPECTED_PROPERTYTYPE(type);
                    break;
            }
        }
    },
    getCustomProperties:function(){
        return this._customProperties;
    },
    _createCCNode:function (parent, ccbReader) {
        return new cc.Node();
    },
    parsePropTypePosition:function (node, parent, ccbReader, propertyName) {
        var x = ccbReader.readFloat();
        var y = ccbReader.readFloat();
        var type = ccbReader.readInt(false);
        var containerSize = ccbReader.getAnimationManager().getContainerSize(parent);
        var pt = cc._getAbsolutePosition(x,y,type,containerSize,propertyName);
        node.setPosition(cc.getAbsolutePosition(pt,type,containerSize,propertyName));
        if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
            var baseValue = [x,y,type];
            ccbReader.getAnimationManager().setBaseValue(baseValue,node,propertyName);
        }
        return pt;
    },
    parsePropTypePoint:function (node, parent, ccbReader) {
        var x = ccbReader.readFloat();
        var y = ccbReader.readFloat();
        return cc.p(x, y);
    },
    parsePropTypePointLock:function (node, parent, ccbReader) {
        var x = ccbReader.readFloat();
        var y = ccbReader.readFloat();
        return cc.p(x, y);
    },
    parsePropTypeSize:function (node, parent, ccbReader) {
        var width = ccbReader.readFloat();
        var height = ccbReader.readFloat();
        var type = ccbReader.readInt(false);
        var containerSize = ccbReader.getAnimationManager().getContainerSize(parent);
        switch (type) {
            case CCB_SIZETYPE_ABSOLUTE:
                break;
            case CCB_SIZETYPE_RELATIVE_CONTAINER:
                width = containerSize.width - width;
                height = containerSize.height - height;
                break;
            case CCB_SIZETYPE_PERCENT:
                width = (containerSize.width * width / 100.0);
                height = (containerSize.height * height / 100.0);
                break;
            case CCB_SIZETYPE_HORIZONTAL_PERCENT:
                width = (containerSize.width * width / 100.0);
                break;
            case CCB_SIZETYPE_VERTICAL_PERCENT:
                height = (containerSize.height * height / 100.0);
                break;
            case CCB_SIZETYPE_MULTIPLY_RESOLUTION:
                var resolutionScale = cc.BuilderReader.getResolutionScale();
                width *= resolutionScale;
                height *= resolutionScale;
                break;
            default:
                cc.log("Unknown CCB type.");
                break;
        }
        return cc.size(width, height);
    },
    parsePropTypeScaleLock:function (node, parent, ccbReader, propertyName) {
        var x = ccbReader.readFloat();
        var y = ccbReader.readFloat();
        var type = ccbReader.readInt(false);
        cc.setRelativeScale(node,x,y,type,propertyName);
        if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
            ccbReader.getAnimationManager().setBaseValue([x,y,type],node,propertyName);
        }
        if (type === CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
            x *= cc.BuilderReader.getResolutionScale();
            y *= cc.BuilderReader.getResolutionScale();
        }
        return [x, y];
    },
    parsePropTypeFloat:function (node, parent, ccbReader) {
        return ccbReader.readFloat();
    },
    parsePropTypeDegrees:function (node, parent, ccbReader, propertyName) {
        var ret = ccbReader.readFloat();
        if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
            ccbReader.getAnimationManager().setBaseValue(ret,node, propertyName);
        }
        return ret;
    },
    parsePropTypeFloatScale:function (node, parent, ccbReader) {
        var f = ccbReader.readFloat();
        var type = ccbReader.readInt(false);
        if (type === CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
            f *= cc.BuilderReader.getResolutionScale();
        }
        return f;
    },
    parsePropTypeInteger:function (node, parent, ccbReader) {
        return ccbReader.readInt(true);
    },
    parsePropTypeIntegerLabeled:function (node, parent, ccbReader) {
        return ccbReader.readInt(true);
    },
    parsePropTypeFloatVar:function (node, parent, ccbReader) {
        var f = ccbReader.readFloat();
        var fVar = ccbReader.readFloat();
        return [f, fVar];
    },
    parsePropTypeCheck:function (node, parent, ccbReader, propertyName) {
        var ret = ccbReader.readBool();
        if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
            ccbReader.getAnimationManager().setBaseValue(ret,node, propertyName);
        }
        return ret;
    },
    parsePropTypeSpriteFrame:function (node, parent, ccbReader, propertyName) {
        var spriteSheet = ccbReader.readCachedString();
        var spriteFile =  ccbReader.readCachedString();
        var spriteFrame;
        if(spriteFile != null && spriteFile.length !== 0){
            if(spriteSheet.length === 0){
                spriteFile = ccbReader.getCCBRootPath() + spriteFile;
                var texture = cc.textureCache.addImage(spriteFile);
                var locContentSize = texture.getContentSize();
                var bounds = cc.rect(0, 0, locContentSize.width, locContentSize.height);
                spriteFrame = new cc.SpriteFrame(texture, bounds);
            } else {
                var frameCache = cc.spriteFrameCache;
                spriteSheet = ccbReader.getCCBRootPath() + spriteSheet;
                if(ccbReader.getLoadedSpriteSheet().indexOf(spriteSheet) === -1){
                    frameCache.addSpriteFrames(spriteSheet);
                    ccbReader.getLoadedSpriteSheet().push(spriteSheet);
                }
                spriteFrame = frameCache.getSpriteFrame(spriteFile);
            }
            if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
                ccbReader.getAnimationManager().setBaseValue(spriteFrame,node,propertyName);
            }
        }
        return spriteFrame;
    },
    parsePropTypeAnimation:function (node, parent, ccbReader) {
        var animationFile = ccbReader.getCCBRootPath() + ccbReader.readCachedString();
        var animation = ccbReader.readCachedString();
        var ccAnimation = null;
        animation = cc.BuilderReader.lastPathComponent(animation);
        animationFile = cc.BuilderReader.lastPathComponent(animationFile);
        if (animation != null && animation !== "") {
            var animationCache = cc.animationCache;
            animationCache.addAnimations(animationFile);
            ccAnimation = animationCache.getAnimation(animation);
        }
        return ccAnimation;
    },
    parsePropTypeTexture:function (node, parent, ccbReader) {
        var spriteFile = ccbReader.getCCBRootPath() + ccbReader.readCachedString();
        if(spriteFile !== "")
            return cc.textureCache.addImage(spriteFile);
        return null;
    },
    parsePropTypeByte:function (node, parent, ccbReader, propertyName) {
        var ret = ccbReader.readByte();
        if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
            ccbReader.getAnimationManager().setBaseValue(ret,node, propertyName);
        }
        return ret;
    },
    parsePropTypeColor3:function (node, parent, ccbReader, propertyName) {
        var red = ccbReader.readByte();
        var green = ccbReader.readByte();
        var blue = ccbReader.readByte();
        var color = {r:red, g:green, b:blue };
        if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
            ccbReader.getAnimationManager().setBaseValue(cc.Color3BWapper.create(color),node, propertyName);
        }
        return color;
    },
    parsePropTypeColor4FVar:function (node, parent, ccbReader) {
        var red = 0 | (ccbReader.readFloat() * 255);
        var green = 0 | (ccbReader.readFloat() * 255);
        var blue = 0 | (ccbReader.readFloat() * 255);
        var alpha = ccbReader.readFloat();
        alpha = alpha <= 1 ? (0 | (alpha * 255)) : alpha;
        var redVar = 0 | (ccbReader.readFloat() * 255);
        var greenVar = 0 | (ccbReader.readFloat() * 255);
        var blueVar = 0 | (ccbReader.readFloat() * 255);
        var alphaVar = ccbReader.readFloat();
        alphaVar = alphaVar <= 1 ? (0 | (alphaVar * 255)) : alphaVar;
        var colors = [];
        colors[0] = {r:red, g:green, b:blue, a:alpha};
        colors[1] = {r:redVar, g:greenVar, b:blueVar, a:alphaVar};
        return colors;
    },
    parsePropTypeFlip:function (node, parent, ccbReader) {
        var flipX = ccbReader.readBool();
        var flipY = ccbReader.readBool();
        return [flipX, flipY];
    },
    parsePropTypeBlendFunc:function (node, parent, ccbReader) {
        var source = ccbReader.readInt(false);
        var destination = ccbReader.readInt(false);
        return new cc.BlendFunc(source, destination);
    },
    parsePropTypeFntFile:function (node, parent, ccbReader) {
        return ccbReader.readCachedString();
    },
    parsePropTypeString:function (node, parent, ccbReader) {
        return ccbReader.readCachedString();
    },
    parsePropTypeText:function (node, parent, ccbReader) {
        return ccbReader.readCachedString();
    },
    parsePropTypeFontTTF:function (node, parent, ccbReader) {
        return ccbReader.readCachedString();
    },
    parsePropTypeBlock:function (node, parent, ccbReader) {
        var selectorName = ccbReader.readCachedString();
        var selectorTarget = ccbReader.readInt(false);
        if (selectorTarget !== CCB_TARGETTYPE_NONE) {
            var target = null;
            if(!ccbReader.isJSControlled()) {
                if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) {
                    target = ccbReader.getAnimationManager().getRootNode();
                } else if (selectorTarget === CCB_TARGETTYPE_OWNER) {
                    target = ccbReader.getOwner();
                }
                if (target !== null) {
                    if (selectorName.length > 0) {
                        var selMenuHandler = 0;
                        if (target.onResolveCCBCCMenuItemSelector)
                            selMenuHandler = target.onResolveCCBCCMenuItemSelector(target, selectorName);
                        if (selMenuHandler === 0) {
                            var ccbSelectorResolver = ccbReader.getCCBSelectorResolver();
                            if (ccbSelectorResolver != null)
                                selMenuHandler = ccbSelectorResolver.onResolveCCBCCMenuItemSelector(target, selectorName);
                        }
                        if (selMenuHandler === 0) {
                            cc.log("Skipping selector '" +selectorName+ "' since no CCBSelectorResolver is present.");
                        } else {
                            return new BlockData(selMenuHandler,target);
                        }
                    } else {
                        cc.log("Unexpected empty selector.");
                    }
                } else {
                    cc.log("Unexpected NULL target for selector.");
                }
            } else {
                if(selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT){
                    ccbReader.addDocumentCallbackNode(node);
                    ccbReader.addDocumentCallbackName(selectorName);
                    ccbReader.addDocumentCallbackControlEvents(0);
                } else {
                    ccbReader.addOwnerCallbackNode(node);
                    ccbReader.addOwnerCallbackName(selectorName);
                    ccbReader.addOwnerCallbackControlEvents(0);
                }
            }
        }
        return null;
    },
    parsePropTypeBlockCCControl:function (node, parent, ccbReader) {
        var selectorName = ccbReader.readCachedString();
        var selectorTarget = ccbReader.readInt(false);
        var controlEvents = ccbReader.readInt(false);
        if (selectorTarget !== CCB_TARGETTYPE_NONE) {
            if(!ccbReader.isJSControlled()){
                var target = null;
                if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) {
                    target = ccbReader.getAnimationManager().getRootNode();
                } else if (selectorTarget === CCB_TARGETTYPE_OWNER) {
                    target = ccbReader.getOwner();
                }
                if (target !== null) {
                    if (selectorName.length > 0) {
                        var selCCControlHandler = 0;
                        if (target.onResolveCCBCCControlSelector) {
                            selCCControlHandler = target.onResolveCCBCCControlSelector(target, selectorName);
                        }
                        if (selCCControlHandler === 0) {
                            var ccbSelectorResolver = ccbReader.getCCBSelectorResolver();
                            if (ccbSelectorResolver != null) {
                                selCCControlHandler = ccbSelectorResolver.onResolveCCBCCControlSelector(target, selectorName);
                            }
                        }
                        if (selCCControlHandler === 0) {
                            cc.log("Skipping selector '" + selectorName + "' since no CCBSelectorResolver is present.");
                        } else {
                            return new BlockCCControlData(selCCControlHandler,target,controlEvents);
                        }
                    } else {
                        cc.log("Unexpected empty selector.");
                    }
                } else {
                    cc.log("Unexpected NULL target for selector.");
                }
            } else {
                if(selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT){
                    ccbReader.addDocumentCallbackNode(node);
                    ccbReader.addDocumentCallbackName(selectorName);
                    ccbReader.addDocumentCallbackControlEvents(controlEvents);
                } else {
                    ccbReader.addOwnerCallbackNode(node);
                    ccbReader.addOwnerCallbackName(selectorName);
                    ccbReader.addOwnerCallbackControlEvents(controlEvents);
                }
            }
        }
        return null;
    },
    parsePropTypeCCBFile:function (node, parent, ccbReader) {
        var ccbFileName = ccbReader.getCCBRootPath() + ccbReader.readCachedString();
        var ccbFileWithoutPathExtension = cc.BuilderReader.deletePathExtension(ccbFileName);
        ccbFileName = ccbFileWithoutPathExtension + ".ccbi";
        var myCCBReader = new cc.BuilderReader(ccbReader);
        var bytes = cc.loader.getRes(ccbFileName);
        if(!bytes){
            var realUrl = cc.loader.getUrl(ccbFileName);
            bytes = cc.loader.loadBinarySync(realUrl);
            cc.loader.cache[ccbFileName] = bytes;
        }
        myCCBReader.initWithData(bytes,ccbReader.getOwner());
        myCCBReader.getAnimationManager().setRootContainerSize(parent.getContentSize());
        myCCBReader.setAnimationManagers(ccbReader.getAnimationManagers());
        myCCBReader.getAnimationManager().setOwner(ccbReader.getOwner());
        var ccbFileNode = myCCBReader.readFileWithCleanUp(false);
        ccbReader.setAnimationManagers(myCCBReader.getAnimationManagers());
        if(ccbFileNode && myCCBReader.getAnimationManager().getAutoPlaySequenceId() !== -1)
            myCCBReader.getAnimationManager().runAnimations(myCCBReader.getAnimationManager().getAutoPlaySequenceId(),0);
        return ccbFileNode;
    },
    parsePropTypeFloatXY:function(node, parent, ccbReader){
        var x = ccbReader.readFloat();
        var y = ccbReader.readFloat();
        return [x,y];
    },
    onHandlePropTypePosition:function (node, parent, propertyName, position, ccbReader) {
        if (propertyName === PROPERTY_POSITION) {
            node.setPosition(position);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypePoint:function (node, parent, propertyName, position, ccbReader) {
        if (propertyName === PROPERTY_ANCHORPOINT) {
            node.setAnchorPoint(position);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypePointLock:function (node, parent, propertyName, pointLock, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeSize:function (node, parent, propertyName, sizeValue, ccbReader) {
        if (propertyName === PROPERTY_CONTENTSIZE) {
            node.setContentSize(sizeValue);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypeScaleLock:function (node, parent, propertyName, scaleLock, ccbReader) {
        if (propertyName === PROPERTY_SCALE) {
            node.setScaleX(scaleLock[0]);
            node.setScaleY(scaleLock[1]);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypeFloatXY: function (node, parent, propertyName, xy, ccbReader) {
        if (propertyName === PROPERTY_SKEW) {
            node.setSkewX(xy[0]);
            node.setSkewY(xy[1]);
        } else {
            var nameX = propertyName + "X";
            var nameY = propertyName + "Y";
            if (!node[nameX] || !node[nameY])
                ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
            node[nameX](xy[0]);
            node[nameY](xy[1]);
        }
    },
    onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) {
        this._customProperties.setObject(floatValue, propertyName);
    },
    onHandlePropTypeDegrees:function (node, parent, propertyName, degrees, ccbReader) {
        if (propertyName === PROPERTY_ROTATION) {
            node.setRotation(degrees);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeInteger:function (node, parent, propertyName, integer, ccbReader) {
        if (propertyName === PROPERTY_TAG) {
            node.setTag(integer);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeFloatVar:function (node, parent, propertyName, floatVar, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName === PROPERTY_VISIBLE) {
            node.setVisible(check);
        } else if (propertyName === PROPERTY_IGNOREANCHORPOINTFORPOSITION) {
            node.ignoreAnchorPointForPosition(check);
        } else {
            ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
        }
    },
    onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeAnimation:function (node, parent, propertyName, ccAnimation, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeTexture:function (node, parent, propertyName, ccTexture2D, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeColor4FVar:function (node, parent, propertyName, ccColor4FVar, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeFlip:function (node, parent, propertyName, flip, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeFntFile:function (node, parent, propertyName, fntFile, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeString:function (node, parent, propertyName, strValue, ccbReader) {
        this._customProperties.setObject(strValue, propertyName);
    },
    onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeBlock:function (node, parent, propertyName, blockData, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeBlockCCControl:function (node, parent, propertyName, blockCCControlData, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    },
    onHandlePropTypeCCBFile:function (node, parent, propertyName, ccbFileNode, ccbReader) {
        ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
    }
});
cc.NodeLoader.loader = function () {
    return new cc.NodeLoader();
};
cc.NodeLoaderListener = cc.Class.extend({
    onNodeLoaded:function(node,nodeLoader){}
});
cc.BuilderSelectorResolver = cc.Class.extend({
    onResolveCCBCCMenuItemSelector:function(target, selectorName){},
    onResolveCCBCCCallFuncSelector:function(target, selectorName){},
    onResolveCCBCCControlSelector:function(target,selectorName){}
});
cc.BuilderScriptOwnerProtocol = cc.Class.extend({
    createNew:function(){}
});
cc.BuilderMemberVariableAssigner = cc.Class.extend({
    onAssignCCBMemberVariable:function(target,memberVariableName, node){ return false;},
    onAssignCCBCustomProperty:function(target, memberVariableName, value){ return false; }
});
var PROPERTY_CCBFILE = "ccbFile";
cc.BuilderFileLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return cc.BuilderFile.create();
    },
    onHandlePropTypeCCBFile:function (node, parent, propertyName, ccbFileNode, ccbReader) {
        if (propertyName === PROPERTY_CCBFILE) {
            node.setCCBFileNode(ccbFileNode);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeCCBFile.call(this, node, parent, propertyName, ccbFileNode, ccbReader);
        }
    }
});
cc.BuilderFileLoader.loader = function () {
    return new cc.BuilderFileLoader();
};
var PROPERTY_ENABLED = "enabled";
var PROPERTY_SELECTED = "selected";
var PROPERTY_CCCONTROL = "ccControl";
cc.ControlLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReander) {
    },
    onHandlePropTypeBlockCCControl:function (node, parent, propertyName, blockCCControlData, ccbReader) {
        if (propertyName === PROPERTY_CCCONTROL) {
            node.addTargetWithActionForControlEvents(blockCCControlData.target, blockCCControlData.selCCControlHandler, blockCCControlData.controlEvents);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlockCCControl.call(this, node, parent, propertyName, blockCCControlData, ccbReader);
        }
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName === PROPERTY_ENABLED) {
            node.setEnabled(check);
        } else if (propertyName === PROPERTY_SELECTED) {
            node.setSelected(check);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
        }
    }
});
var PROPERTY_ZOOMONTOUCHDOWN = "zoomOnTouchDown";
var PROPERTY_TITLE_NORMAL = "title|1";
var PROPERTY_TITLE_HIGHLIGHTED = "title|2";
var PROPERTY_TITLE_DISABLED = "title|3";
var PROPERTY_TITLECOLOR_NORMAL = "titleColor|1";
var PROPERTY_TITLECOLOR_HIGHLIGHTED = "titleColor|2";
var PROPERTY_TITLECOLOR_DISABLED = "titleColor|3";
var PROPERTY_TITLETTF_NORMAL = "titleTTF|1";
var PROPERTY_TITLETTF_HIGHLIGHTED = "titleTTF|2";
var PROPERTY_TITLETTF_DISABLED = "titleTTF|3";
var PROPERTY_TITLETTFSIZE_NORMAL = "titleTTFSize|1";
var PROPERTY_TITLETTFSIZE_HIGHLIGHTED = "titleTTFSize|2";
var PROPERTY_TITLETTFSIZE_DISABLED = "titleTTFSize|4";
var PROPERTY_LABELANCHORPOINT = "labelAnchorPoint";
var PROPERTY_PREFEREDSIZE = "preferedSize";
var PROPERTY_BACKGROUNDSPRITEFRAME_NORMAL = "backgroundSpriteFrame|1";
var PROPERTY_BACKGROUNDSPRITEFRAME_HIGHLIGHTED = "backgroundSpriteFrame|2";
var PROPERTY_BACKGROUNDSPRITEFRAME_DISABLED = "backgroundSpriteFrame|3";
cc.ControlButtonLoader = cc.ControlLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.ControlButton();
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName === PROPERTY_ZOOMONTOUCHDOWN) {
            node.setZoomOnTouchDown(check);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
        }
    },
    onHandlePropTypeString:function (node, parent, propertyName, stringValue, ccbReader) {
        if (propertyName === PROPERTY_TITLE_NORMAL) {
            node.setTitleForState(stringValue, cc.CONTROL_STATE_NORMAL);
        } else if (propertyName === PROPERTY_TITLE_HIGHLIGHTED) {
            node.setTitleForState(stringValue, cc.CONTROL_STATE_HIGHLIGHTED);
        } else if (propertyName === PROPERTY_TITLE_DISABLED) {
            node.setTitleForState(stringValue, cc.CONTROL_STATE_DISABLED);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeString.call(this, node, parent, propertyName, stringValue, ccbReader);
        }
    },
    onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) {
        if (propertyName === PROPERTY_TITLETTF_NORMAL) {
            node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_NORMAL);
        } else if (propertyName === PROPERTY_TITLETTF_HIGHLIGHTED) {
            node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_HIGHLIGHTED);
        } else if (propertyName === PROPERTY_TITLETTF_DISABLED) {
            node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_DISABLED);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeFontTTF.call(this, node, parent, propertyName, fontTTF, ccbReader);
        }
    },
    onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) {
        if (propertyName === PROPERTY_TITLETTFSIZE_NORMAL) {
            node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_NORMAL);
        } else if (propertyName === PROPERTY_TITLETTFSIZE_HIGHLIGHTED) {
            node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_HIGHLIGHTED);
        } else if (propertyName === PROPERTY_TITLETTFSIZE_DISABLED) {
            node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_DISABLED);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeFloatScale.call(this, node, parent, propertyName, floatScale, ccbReader);
        }
    },
    onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) {
        if (propertyName === PROPERTY_LABELANCHORPOINT) {
            node.setLabelAnchorPoint(point);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader);
        }
    },
    onHandlePropTypeSize:function (node, parent, propertyName, size, ccbReader) {
        if (propertyName === PROPERTY_PREFEREDSIZE) {
            node.setPreferredSize(size);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader);
        }
    },
    onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) {
        if (propertyName === PROPERTY_BACKGROUNDSPRITEFRAME_NORMAL) {
            if (spriteFrame != null) {
                node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_NORMAL);
            }
        } else if (propertyName === PROPERTY_BACKGROUNDSPRITEFRAME_HIGHLIGHTED) {
            if (spriteFrame != null) {
                node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_HIGHLIGHTED);
            }
        } else if (propertyName === PROPERTY_BACKGROUNDSPRITEFRAME_DISABLED) {
            if (spriteFrame != null) {
                node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_DISABLED);
            }
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame, ccbReader);
        }
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        if (propertyName === PROPERTY_TITLECOLOR_NORMAL) {
            node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_NORMAL);
        } else if (propertyName === PROPERTY_TITLECOLOR_HIGHLIGHTED) {
            node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_HIGHLIGHTED);
        } else if (propertyName === PROPERTY_TITLECOLOR_DISABLED) {
            node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_DISABLED);
        } else {
            cc.ControlLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
        }
    }
});
cc.ControlButtonLoader.loader = function () {
    return new cc.ControlButtonLoader();
};
var PROPERTY_CONTAINER = "container";
var PROPERTY_DIRECTION = "direction";
var PROPERTY_CLIPSTOBOUNDS = "clipsToBounds";
var PROPERTY_BOUNCES = "bounces";
var PROPERTY_SCALE = "scale";
cc.ScrollViewLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.ScrollView();
    },
    onHandlePropTypeSize:function(node,parent,propertyName,size,ccbReader){
        if(propertyName === PROPERTY_CONTENTSIZE){
            node.setViewSize(size);
        }else{
            cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node,parent,propertyName,size,ccbReader);
        }
    },
    onHandlePropTypeCCBFile:function (node, parent, propertyName, ccbFileNode, ccbReader) {
        if (propertyName === PROPERTY_CONTAINER) {
            node.setContainer(ccbFileNode);
            node.updateInset();
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeCCBFile.call(this, node, parent, propertyName, ccbFileNode, ccbReader);
        }
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName === PROPERTY_CLIPSTOBOUNDS) {
            node.setClippingToBounds(check);
        } else if (propertyName === PROPERTY_BOUNCES) {
            node.setBounceable(check);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
        }
    },
    onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) {
        if (propertyName === PROPERTY_SCALE) {
            node.setScale(floatValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader);
        }
    },
    onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
        if (propertyName === PROPERTY_DIRECTION) {
            node.setDirection(integerLabeled);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader);
        }
    }
});
cc.ScrollViewLoader.loader = function () {
    return new cc.ScrollViewLoader();
};
var PROPERTY_CONTENTSIZE = "contentSize";
var PROPERTY_SPRITEFRAME = "spriteFrame";
var PROPERTY_COLOR = "color";
var PROPERTY_OPACITY = "opacity";
var PROPERTY_BLENDFUNC = "blendFunc";
var PROPERTY_INSETLEFT = "insetLeft";
var PROPERTY_INSETTOP = "insetTop" ;
var PROPERTY_INSETRIGHT = "insetRight";
var PROPERTY_INSETBOTTOM = "insetBottom";
cc.Scale9SpriteLoader = cc.NodeLoader.extend({
    _createCCNode:function(parent,ccbReader){
        var sprite = new cc.Scale9Sprite();
        sprite.setAnchorPoint(0, 0);
        return sprite;
    },
    onHandlePropTypeColor3:function(node, parent, propertyName, ccColor3B,ccbReader){
        if(propertyName === PROPERTY_COLOR) {
            if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
                node.setColor(ccColor3B);
            }
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B,ccbReader);
        }
    },
    onHandlePropTypeByte:function(node, parent, propertyName, byteValue,ccbReader){
        if(propertyName === PROPERTY_OPACITY) {
            node.setOpacity(byteValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue,ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function(node, parent, propertyName, ccBlendFunc,ccbReader){
        if(propertyName === PROPERTY_BLENDFUNC) {
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc,ccbReader);
        }
    },
    onHandlePropTypeSpriteFrame:function(node, parent, propertyName, spriteFrame,ccbReader){
        if(propertyName === PROPERTY_SPRITEFRAME) {
            node.setSpriteFrame(spriteFrame);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame,ccbReader);
        }
    },
    onHandlePropTypeSize:function(node, parent, propertyName, size,ccbReader){
        if(propertyName === PROPERTY_CONTENTSIZE) {
        } else if(propertyName === PROPERTY_PREFEREDSIZE) {
            node.setPreferredSize(size);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size,ccbReader);
        }
    },
    onHandlePropTypeFloat:function(node, parent, propertyName, floatValue,ccbReader){
        if(propertyName === PROPERTY_INSETLEFT) {
            node.setInsetLeft(floatValue);
        } else if(propertyName === PROPERTY_INSETTOP) {
            node.setInsetTop(floatValue);
        } else if(propertyName === PROPERTY_INSETRIGHT) {
            node.setInsetRight(floatValue);
        } else if(propertyName === PROPERTY_INSETBOTTOM) {
            node.setInsetBottom(floatValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue,ccbReader);
        }
    }
});
cc.Scale9SpriteLoader.loader = function(){
   return new cc.Scale9SpriteLoader();
};
var PROPERTY_FLIP = "flip";
var PROPERTY_DISPLAYFRAME = "displayFrame";
var PROPERTY_COLOR = "color";
var PROPERTY_OPACITY = "opacity";
var PROPERTY_BLENDFUNC = "blendFunc";
cc.SpriteLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.Sprite();
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        if (propertyName === PROPERTY_COLOR) {
            if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
                node.setColor(ccColor3B);
            }
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
        }
    },
    onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
        if (propertyName === PROPERTY_OPACITY) {
            node.setOpacity(byteValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccbBlendFunc, ccbReader) {
        if (propertyName === PROPERTY_BLENDFUNC) {
            node.setBlendFunc(ccbBlendFunc);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccbBlendFunc, ccbReader);
        }
    },
    onHandlePropTypeSpriteFrame:function (node, parent, propertyName, ccSpriteFrame, ccbReader) {
        if (propertyName === PROPERTY_DISPLAYFRAME) {
            if(ccSpriteFrame)
                node.setSpriteFrame(ccSpriteFrame);
            else
                cc.log("ERROR: SpriteFrame is null");
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, ccSpriteFrame, ccbReader);
        }
    },
    onHandlePropTypeFlip:function (node, parent, propertyName, flip, ccbReader) {
        if (propertyName === PROPERTY_FLIP) {
            node.setFlippedX(flip[0]);
            node.setFlippedY(flip[1]);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFlip.call(this, node, parent, propertyName, flip, ccbReader);
        }
    }
});
cc.SpriteLoader.loader = function () {
    return new cc.SpriteLoader();
};
var PROPERTY_TOUCH_ENABLED = "touchEnabled";
var PROPERTY_IS_TOUCH_ENABLED = "isTouchEnabled";
var PROPERTY_ACCELEROMETER_ENABLED = "accelerometerEnabled";
var PROPERTY_IS_ACCELEROMETER_ENABLED = "isAccelerometerEnabled";
var PROPERTY_IS_MOUSE_ENABLED = "isMouseEnabled";
var PROPERTY_MOUSE_ENABLED = "mouseEnabled";
var PROPERTY_KEYBOARD_ENABLED = "keyboardEnabled";
var PROPERTY_IS_KEYBOARD_ENABLED = "isKeyboardEnabled";
cc.LayerLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        var layer = new cc.Layer();
        layer.setContentSize(0,0);
        return layer;
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName === PROPERTY_TOUCH_ENABLED || propertyName === PROPERTY_IS_TOUCH_ENABLED) {
        } else if (propertyName === PROPERTY_ACCELEROMETER_ENABLED || propertyName === PROPERTY_IS_ACCELEROMETER_ENABLED) {
        } else if (propertyName === PROPERTY_MOUSE_ENABLED || propertyName === PROPERTY_IS_MOUSE_ENABLED ) {
        } else if (propertyName === PROPERTY_KEYBOARD_ENABLED || propertyName === PROPERTY_IS_KEYBOARD_ENABLED) {
            if(node.setKeyboardEnabled && !cc.sys.isNative) {
                node.setKeyboardEnabled(check);
            } else {
                cc.log("The property '" + PROPERTY_IS_KEYBOARD_ENABLED + "' is not supported!");
            }
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
        }
    }
});
cc.LayerLoader.loader = function () {
    return new cc.LayerLoader();
};
cc.LayerColorLoader = cc.LayerLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.LayerColor();
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        if (propertyName === PROPERTY_COLOR) {
            node.setColor(ccColor3B);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
        }
    },
    onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
        if (propertyName === PROPERTY_OPACITY) {
            node.setOpacity(byteValue);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
        if (propertyName === PROPERTY_BLENDFUNC) {
            node.setBlendFunc(ccBlendFunc);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader);
        }
    }
});
cc.LayerColorLoader.loader = function () {
    return new cc.LayerColorLoader();
};
var PROPERTY_STARTCOLOR = "startColor";
var PROPERTY_ENDCOLOR = "endColor";
var PROPERTY_STARTOPACITY = "startOpacity";
var PROPERTY_ENDOPACITY = "endOpacity";
var PROPERTY_VECTOR = "vector";
cc.LayerGradientLoader = cc.LayerLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.LayerGradient();
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        if (propertyName === PROPERTY_STARTCOLOR) {
            node.setStartColor(ccColor3B);
        } else if (propertyName === PROPERTY_ENDCOLOR) {
            node.setEndColor(ccColor3B);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
        }
    },
    onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
        if (propertyName === PROPERTY_STARTOPACITY) {
            node.setStartOpacity(byteValue);
        } else if (propertyName === PROPERTY_ENDOPACITY) {
            node.setEndOpacity(byteValue);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader);
        }
    },
    onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) {
        if (propertyName === PROPERTY_VECTOR) {
            node.setVector(point);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
        if (propertyName === PROPERTY_BLENDFUNC) {
            node.setBlendFunc(ccBlendFunc);
        } else {
            cc.LayerLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader);
        }
    }
});
cc.LayerGradientLoader.loader = function () {
    return new cc.LayerGradientLoader();
};
cc.MenuLoader = cc.LayerLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        var menu = new cc.Menu();
        menu.setContentSize(0,0);
        return menu;
    }
});
cc.MenuLoader.loader = function () {
    return new cc.MenuLoader();
};
var PROPERTY_BLOCK = "block";
var PROPERTY_ISENABLED = "isEnabled";
cc.MenuItemLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return null;
    },
    onHandlePropTypeBlock:function (node, parent, propertyName, blockData, ccbReader) {
        if (propertyName === PROPERTY_BLOCK) {
            if (null != blockData) {
                node.setTarget(blockData.selMenuHander, blockData.target);
            }
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlock.call(this, node, parent, propertyName, blockData, ccbReader);
        }
    },
    onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
        if (propertyName === PROPERTY_ISENABLED) {
            node.setEnabled(check);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
        }
    }
});
var PROPERTY_NORMALDISPLAYFRAME = "normalSpriteFrame";
var PROPERTY_SELECTEDDISPLAYFRAME = "selectedSpriteFrame";
var PROPERTY_DISABLEDDISPLAYFRAME = "disabledSpriteFrame";
cc.MenuItemImageLoader = cc.MenuItemLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.MenuItemImage();
    },
    onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) {
        if (propertyName === PROPERTY_NORMALDISPLAYFRAME) {
            if (spriteFrame != null) {
                node.setNormalSpriteFrame(spriteFrame);
            }
        } else if (propertyName === PROPERTY_SELECTEDDISPLAYFRAME) {
            if (spriteFrame != null) {
                node.setSelectedSpriteFrame(spriteFrame);
            }
        } else if (propertyName === PROPERTY_DISABLEDDISPLAYFRAME) {
            if (spriteFrame != null) {
                node.setDisabledSpriteFrame(spriteFrame);
            }
        } else {
            cc.MenuItemLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame, ccbReader);
        }
    }
});
cc.MenuItemImageLoader.loader = function () {
    return new cc.MenuItemImageLoader();
};
var PROPERTY_FONTNAME = "fontName";
var PROPERTY_FONTSIZE = "fontSize";
var PROPERTY_HORIZONTALALIGNMENT = "horizontalAlignment";
var PROPERTY_VERTICALALIGNMENT = "verticalAlignment";
var PROPERTY_STRING = "string";
var PROPERTY_DIMENSIONS = "dimensions";
cc.LabelTTFLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.LabelTTF();
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        if (propertyName === PROPERTY_COLOR) {
            if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
                node.setColor(ccColor3B);
            }
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
        }
    },
    onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
        if (propertyName === PROPERTY_OPACITY) {
            node.setOpacity(byteValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
        if (propertyName === PROPERTY_BLENDFUNC) {
            node.setBlendFunc(ccBlendFunc);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader);
        }
    },
    onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) {
        if (propertyName === PROPERTY_FONTNAME) {
            node.setFontName(fontTTF);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFontTTF.call(this, node, parent, propertyName, fontTTF, ccbReader);
        }
    },
    onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) {
        if (propertyName === PROPERTY_STRING) {
            node.setString(textValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeText.call(this, node, parent, propertyName, textValue, ccbReader);
        }
    },
    onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) {
        if (propertyName === PROPERTY_FONTSIZE) {
            node.setFontSize(floatScale);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFloatScale.call(this, node, parent, propertyName, floatScale, ccbReader);
        }
    },
    onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
        if (propertyName === PROPERTY_HORIZONTALALIGNMENT) {
            node.setHorizontalAlignment(integerLabeled);
        } else if (propertyName === PROPERTY_VERTICALALIGNMENT) {
            node.setVerticalAlignment(integerLabeled);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader);
        }
    },
    onHandlePropTypeSize:function (node, parent, propertyName, size, ccbReader) {
        if (propertyName === PROPERTY_DIMENSIONS) {
            node.setDimensions(size);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader);
        }
    }
});
cc.LabelTTFLoader.loader = function () {
    return new cc.LabelTTFLoader();
};
var PROPERTY_FNTFILE = "fntFile";
cc.LabelBMFontLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.LabelBMFont();
    },
    onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
        if (propertyName === PROPERTY_COLOR) {
            if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
                node.setColor(ccColor3B);
            }
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
        }
    },
    onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
        if (propertyName === PROPERTY_OPACITY) {
            node.setOpacity(byteValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
        if (propertyName === PROPERTY_BLENDFUNC) {
            node.setBlendFunc(ccBlendFunc);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader);
        }
    },
    onHandlePropTypeFntFile:function (node, parent, propertyName, fntFile, ccbReader) {
        if (propertyName === PROPERTY_FNTFILE) {
            node.setFntFile(fntFile);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFntFile.call(this, node, parent, propertyName, fntFile, ccbReader);
        }
    },
    onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) {
        if (propertyName === PROPERTY_STRING) {
            node.setString(textValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeText.call(this, node, parent, propertyName, textValue, ccbReader);
        }
    }
});
cc.LabelBMFontLoader.loader = function () {
    return new cc.LabelBMFontLoader();
};
var PROPERTY_EMITERMODE = "emitterMode";
var PROPERTY_POSVAR = "posVar";
var PROPERTY_EMISSIONRATE = "emissionRate";
var PROPERTY_DURATION = "duration";
var PROPERTY_TOTALPARTICLES = "totalParticles";
var PROPERTY_LIFE = "life";
var PROPERTY_STARTSIZE = "startSize";
var PROPERTY_ENDSIZE = "endSize";
var PROPERTY_STARTSPIN = "startSpin";
var PROPERTY_ENDSPIN = "endSpin";
var PROPERTY_ANGLE = "angle";
var PROPERTY_GRAVITY = "gravity";
var PROPERTY_SPEED = "speed";
var PROPERTY_TANGENTIALACCEL = "tangentialAccel";
var PROPERTY_RADIALACCEL = "radialAccel";
var PROPERTY_TEXTURE = "texture";
var PROPERTY_STARTRADIUS = "startRadius";
var PROPERTY_ENDRADIUS = "endRadius";
var PROPERTY_ROTATEPERSECOND = "rotatePerSecond";
cc.ParticleSystemLoader = cc.NodeLoader.extend({
    _createCCNode:function (parent, ccbReader) {
        return new cc.ParticleSystem();
    },
    onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
        if (propertyName === PROPERTY_EMITERMODE) {
            node.setEmitterMode(integerLabeled);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader);
        }
    },
    onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) {
        if (propertyName === PROPERTY_POSVAR) {
            node.setPosVar(point);
        } else if (propertyName === PROPERTY_GRAVITY) {
            node.setGravity(point);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader);
        }
    },
    onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) {
        if (propertyName === PROPERTY_EMISSIONRATE) {
            node.setEmissionRate(floatValue);
        } else if (propertyName === PROPERTY_DURATION) {
            node.setDuration(floatValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader);
        }
    },
    onHandlePropTypeInteger:function (node, parent, propertyName, integerValue, ccbReader) {
        if (propertyName === PROPERTY_TOTALPARTICLES) {
            node.setTotalParticles(integerValue);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeInteger.call(this, node, parent, propertyName, integerValue, ccbReader);
        }
    },
    onHandlePropTypeFloatVar:function (node, parent, propertyName, floatVar, ccbReader) {
        if (propertyName === PROPERTY_LIFE) {
            node.setLife(floatVar[0]);
            node.setLifeVar(floatVar[1]);
        } else if (propertyName === PROPERTY_STARTSIZE) {
            node.setStartSize(floatVar[0]);
            node.setStartSizeVar(floatVar[1]);
        } else if (propertyName === PROPERTY_ENDSIZE) {
            node.setEndSize(floatVar[0]);
            node.setEndSizeVar(floatVar[1]);
        } else if (propertyName === PROPERTY_STARTSPIN) {
            node.setStartSpin(floatVar[0]);
            node.setStartSpinVar(floatVar[1]);
        } else if (propertyName === PROPERTY_ENDSPIN) {
            node.setEndSpin(floatVar[0]);
            node.setEndSpinVar(floatVar[1]);
        } else if (propertyName === PROPERTY_ANGLE) {
            node.setAngle(floatVar[0]);
            node.setAngleVar(floatVar[1]);
        } else if (propertyName === PROPERTY_SPEED) {
            node.setSpeed(floatVar[0]);
            node.setSpeedVar(floatVar[1]);
        } else if (propertyName === PROPERTY_TANGENTIALACCEL) {
            node.setTangentialAccel(floatVar[0]);
            node.setTangentialAccelVar(floatVar[1]);
        } else if (propertyName === PROPERTY_RADIALACCEL) {
            node.setRadialAccel(floatVar[0]);
            node.setRadialAccelVar(floatVar[1]);
        } else if (propertyName === PROPERTY_STARTRADIUS) {
            node.setStartRadius(floatVar[0]);
            node.setStartRadiusVar(floatVar[1]);
        } else if (propertyName === PROPERTY_ENDRADIUS) {
            node.setEndRadius(floatVar[0]);
            node.setEndRadiusVar(floatVar[1]);
        } else if (propertyName === PROPERTY_ROTATEPERSECOND) {
            node.setRotatePerSecond(floatVar[0]);
            node.setRotatePerSecondVar(floatVar[1]);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeFloatVar.call(this, node, parent, propertyName, floatVar, ccbReader);
        }
    },
    onHandlePropTypeColor4FVar:function (node, parent, propertyName, ccColor4FVar, ccbReader) {
        if (propertyName === PROPERTY_STARTCOLOR) {
            node.setStartColor(ccColor4FVar[0]);
            node.setStartColorVar(ccColor4FVar[1]);
        } else if (propertyName === PROPERTY_ENDCOLOR) {
            node.setEndColor(ccColor4FVar[0]);
            node.setEndColorVar(ccColor4FVar[1]);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeColor4FVar.call(this, node, parent, propertyName, ccColor4FVar, ccbReader);
        }
    },
    onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
        if (propertyName === PROPERTY_BLENDFUNC) {
            node.setBlendFunc(ccBlendFunc);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader);
        }
    },
    onHandlePropTypeTexture:function (node, parent, propertyName, ccTexture2D, ccbReader) {
        if (propertyName === PROPERTY_TEXTURE) {
            node.setTexture(ccTexture2D);
        } else {
            cc.NodeLoader.prototype.onHandlePropTypeTexture.call(this, node, parent, propertyName, ccTexture2D, ccbReader);
        }
    }
});
cc.ParticleSystemLoader.loader = function () {
    return new cc.ParticleSystemLoader();
};
cc.NodeLoaderLibrary = cc.Class.extend({
    _ccNodeLoaders:null,
    ctor:function(){
        this._ccNodeLoaders = {};
    },
    registerDefaultCCNodeLoaders:function(){
        this.registerCCNodeLoader("CCNode", cc.NodeLoader.loader());
        this.registerCCNodeLoader("CCLayer", cc.LayerLoader.loader());
        this.registerCCNodeLoader("CCLayerColor", cc.LayerColorLoader.loader());
        this.registerCCNodeLoader("CCLayerGradient", cc.LayerGradientLoader.loader());
        this.registerCCNodeLoader("CCSprite", cc.SpriteLoader.loader());
        this.registerCCNodeLoader("CCLabelBMFont", cc.LabelBMFontLoader.loader());
        this.registerCCNodeLoader("CCLabelTTF", cc.LabelTTFLoader.loader());
        this.registerCCNodeLoader("CCScale9Sprite", cc.Scale9SpriteLoader.loader());
        this.registerCCNodeLoader("CCScrollView", cc.ScrollViewLoader.loader());
        this.registerCCNodeLoader("CCBFile", cc.BuilderFileLoader.loader());
        this.registerCCNodeLoader("CCMenu", cc.MenuLoader.loader());
        this.registerCCNodeLoader("CCMenuItemImage", cc.MenuItemImageLoader.loader());
        this.registerCCNodeLoader("CCControlButton", cc.ControlButtonLoader.loader());
        this.registerCCNodeLoader("CCParticleSystemQuad", cc.ParticleSystemLoader.loader());
    },
    registerCCNodeLoader:function(className,ccNodeLoader){
        this._ccNodeLoaders[className] =  ccNodeLoader;
    },
    unregisterCCNodeLoader:function(className){
        if(this._ccNodeLoaders[className]){
           delete this._ccNodeLoaders[className];
        }
    },
    getCCNodeLoader:function(className){
        if(this._ccNodeLoaders[className])
            return this._ccNodeLoaders[className];
        return null;
    },
    purge:function(releaseCCNodeLoaders){
        if(releaseCCNodeLoaders) {
            for(var className in this._ccNodeLoaders) {
                delete this._ccNodeLoaders[className];
            }
        }
        this._ccNodeLoaders = {};
    }
});
cc.NodeLoaderLibrary.sSharedCCNodeLoaderLibrary = null;
cc.NodeLoaderLibrary.library = function(){
    return new cc.NodeLoaderLibrary();
};
cc.NodeLoaderLibrary.sharedCCNodeLoaderLibrary = function(){
    if(cc.NodeLoaderLibrary.sSharedCCNodeLoaderLibrary == null) {
        cc.NodeLoaderLibrary.sSharedCCNodeLoaderLibrary = new cc.NodeLoaderLibrary();
        cc.NodeLoaderLibrary.sSharedCCNodeLoaderLibrary.registerDefaultCCNodeLoaders();
    }
    return cc.NodeLoaderLibrary.sSharedCCNodeLoaderLibrary;
};
cc.NodeLoaderLibrary.purgeSharedCCNodeLoaderLibrary = function(){
    cc.NodeLoaderLibrary.sSharedCCNodeLoaderLibrary = null;
};
cc.NodeLoaderLibrary.newDefaultCCNodeLoaderLibrary = function(){
    var ccNodeLoaderLibrary = cc.NodeLoaderLibrary.library();
    ccNodeLoaderLibrary.registerDefaultCCNodeLoaders();
    return ccNodeLoaderLibrary;
};
var CCB_VERSION = 5;
var CCB_PROPTYPE_POSITION = 0;
var CCB_PROPTYPE_SIZE = 1;
var CCB_PROPTYPE_POINT = 2;
var CCB_PROPTYPE_POINTLOCK = 3;
var CCB_PROPTYPE_SCALELOCK = 4;
var CCB_PROPTYPE_DEGREES = 5;
var CCB_PROPTYPE_INTEGER = 6;
var CCB_PROPTYPE_FLOAT = 7;
var CCB_PROPTYPE_FLOATVAR = 8;
var CCB_PROPTYPE_CHECK = 9;
var CCB_PROPTYPE_SPRITEFRAME = 10;
var CCB_PROPTYPE_TEXTURE = 11;
var CCB_PROPTYPE_BYTE = 12;
var CCB_PROPTYPE_COLOR3 = 13;
var CCB_PROPTYPE_COLOR4VAR = 14;
var CCB_PROPTYPE_FLIP = 15;
var CCB_PROPTYPE_BLENDMODE = 16;
var CCB_PROPTYPE_FNTFILE = 17;
var CCB_PROPTYPE_TEXT = 18;
var CCB_PROPTYPE_FONTTTF = 19;
var CCB_PROPTYPE_INTEGERLABELED = 20;
var CCB_PROPTYPE_BLOCK = 21;
var CCB_PROPTYPE_ANIMATION = 22;
var CCB_PROPTYPE_CCBFILE = 23;
var CCB_PROPTYPE_STRING = 24;
var CCB_PROPTYPE_BLOCKCCCONTROL = 25;
var CCB_PROPTYPE_FLOATSCALE = 26;
var CCB_PROPTYPE_FLOATXY = 27;
var CCB_FLOAT0 = 0;
var CCB_FLOAT1 = 1;
var CCB_FLOAT_MINUS1 = 2;
var CCB_FLOAT05 = 3;
var CCB_FLOAT_INTEGER = 4;
var CCB_FLOAT_FULL = 5;
var CCB_PLATFORM_ALL = 0;
var CCB_PLATFORM_IOS = 1;
var CCB_PLATFORM_MAC = 2;
var CCB_TARGETTYPE_NONE = 0;
var CCB_TARGETTYPE_DOCUMENTROOT = 1;
var CCB_TARGETTYPE_OWNER = 2;
var CCB_KEYFRAME_EASING_INSTANT = 0;
var CCB_KEYFRAME_EASING_LINEAR = 1;
var CCB_KEYFRAME_EASING_CUBIC_IN = 2;
var CCB_KEYFRAME_EASING_CUBIC_OUT = 3;
var CCB_KEYFRAME_EASING_CUBIC_INOUT = 4;
var CCB_KEYFRAME_EASING_ELASTIC_IN = 5;
var CCB_KEYFRAME_EASING_ELASTIC_OUT = 6;
var CCB_KEYFRAME_EASING_ELASTIC_INOUT = 7;
var CCB_KEYFRAME_EASING_BOUNCE_IN = 8;
var CCB_KEYFRAME_EASING_BOUNCE_OUT = 9;
var CCB_KEYFRAME_EASING_BOUNCE_INOUT = 10;
var CCB_KEYFRAME_EASING_BACK_IN = 11;
var CCB_KEYFRAME_EASING_BACK_OUT = 12;
var CCB_KEYFRAME_EASING_BACK_INOUT = 13;
var CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT = 0;
var CCB_POSITIONTYPE_RELATIVE_TOP_LEFT = 1;
var CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT = 2;
var CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT = 3;
var CCB_POSITIONTYPE_PERCENT = 4;
var CCB_POSITIONTYPE_MULTIPLY_RESOLUTION = 5;
var CCB_SIZETYPE_ABSOLUTE = 0;
var CCB_SIZETYPE_PERCENT = 1;
var CCB_SIZETYPE_RELATIVE_CONTAINER = 2;
var CCB_SIZETYPE_HORIZONTAL_PERCENT = 3;
var CCB_SIZETYPE_VERTICAL_PERCENT = 4;
var CCB_SIZETYPE_MULTIPLY_RESOLUTION = 5;
var CCB_SCALETYPE_ABSOLUTE = 0;
var CCB_SCALETYPE_MULTIPLY_RESOLUTION = 1;
cc.BuilderFile = cc.Node.extend({
    _ccbFileNode:null,
    getCCBFileNode:function () {
        return this._ccbFileNode;
    },
    setCCBFileNode:function (node) {
        this._ccbFileNode = node;
    }
});
cc.BuilderFile.create = function () {
    return new cc.BuilderFile();
};
cc.BuilderReader = cc.Class.extend({
    _jsControlled:false,
    _data:null,
    _ccbRootPath:"",
    _bytes:0,
    _currentByte:0,
    _currentBit:0,
    _stringCache:null,
    _loadedSpriteSheets:null,
    _owner:null,
    _animationManager:null,
    _animationManagers:null,
    _animatedProps:null,
    _ccNodeLoaderLibrary:null,
    _ccNodeLoaderListener:null,
    _ccbMemberVariableAssigner:null,
    _ccbSelectorResolver:null,
    _ownerOutletNames:null,
    _ownerOutletNodes:null,
    _nodesWithAnimationManagers:null,
    _animationManagerForNodes:null,
    _ownerCallbackNames:null,
    _ownerCallbackNodes:null,
    _ownerCallbackEvents:null,
    _readNodeGraphFromData:false,
    ctor:function (ccNodeLoaderLibrary, ccbMemberVariableAssigner, ccbSelectorResolver, ccNodeLoaderListener) {
        this._stringCache = [];
        this._loadedSpriteSheets = [];
        this._currentBit = -1;
        this._currentByte = -1;
        if (arguments.length !== 0) {
            if (ccNodeLoaderLibrary instanceof cc.BuilderReader) {
                var ccbReader = ccNodeLoaderLibrary;
                this._loadedSpriteSheets = ccbReader._loadedSpriteSheets;
                this._ccNodeLoaderLibrary = ccbReader._ccNodeLoaderLibrary;
                this._ccbMemberVariableAssigner = ccbReader._ccbMemberVariableAssigner;
                this._ccbSelectorResolver = ccbReader._ccbSelectorResolver;
                this._ccNodeLoaderListener = ccbReader._ccNodeLoaderListener;
                this._ownerCallbackNames = ccbReader._ownerCallbackNames;
                this._ownerCallbackNodes = ccbReader._ownerCallbackNodes;
                this._ownerCallbackEvents = ccbReader._ownerCallbackEvents;
                this._ownerOutletNames = ccbReader._ownerOutletNames;
                this._ownerOutletNodes = ccbReader._ownerOutletNodes;
                this._ccbRootPath = ccbReader._ccbRootPath;
            } else {
                this._ccNodeLoaderLibrary = ccNodeLoaderLibrary;
                this._ccbMemberVariableAssigner = ccbMemberVariableAssigner;
                this._ccbSelectorResolver = ccbSelectorResolver;
                this._ccNodeLoaderListener = ccNodeLoaderListener;
            }
        }
    },
    getCCBRootPath:function () {
        return this._ccbRootPath;
    },
    setCCBRootPath:function (rootPath) {
        this._ccbRootPath = rootPath;
    },
    initWithData:function (data, owner) {
        this._animationManager = new cc.BuilderAnimationManager();
        this._data = data;
        this._bytes = data.length;
        this._currentBit = 0;
        this._currentByte = 0;
        this._owner = owner;
        this._animationManager.setRootContainerSize(cc.director.getWinSize());
        return true;
    },
    _loadBinarySync : function(url){
        var self = this;
        var req = this.getXMLHttpRequest();
        var errInfo = "load " + url + " failed!";
        req.open('GET', url, false);
        var arrayInfo = null;
        if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
            req.setRequestHeader("Accept-Charset", "x-user-defined");
            req.send(null);
            if (req.status !== 200) {
                cc.log(errInfo);
                return null;
            }
            var fileContents = cc._convertResponseBodyToText(req["responseBody"]);
            if (fileContents) {
                arrayInfo = this._stringConvertToArray(fileContents);
                this._fileDataCache[url] = arrayInfo;
            }
        } else {
            if (req.overrideMimeType)
                req.overrideMimeType('text\/plain; charset=x-user-defined');
            req.send(null);
            if (req.status !== 200) {
                cc.log(errInfo);
                return null;
            }
            arrayInfo = this._stringConvertToArray(req.responseText);
            this._fileDataCache[url] = arrayInfo;
        }
        return arrayInfo;
    },
    readNodeGraphFromFile:function (ccbFileName, owner, parentSize, animationManager) {
        if (parentSize == null) {
            parentSize = cc.director.getWinSize();
        } else if (parentSize instanceof  cc.BuilderAnimationManager) {
            animationManager = parentSize;
            parentSize = cc.director.getWinSize();
        }
        var data = cc.loader.getRes(ccbFileName);
        if(!data){
            var realUrl = cc.loader.getUrl(ccbFileName);
            data = cc.loader.loadBinarySync(realUrl);
            cc.loader.cache[ccbFileName] = data;
        }
        return this.readNodeGraphFromData(data, owner, parentSize, animationManager);
    },
    readNodeGraphFromData:function (data, owner, parentSize) {
        this.initWithData(data, owner);
        var locAnimationManager = this._animationManager;
        locAnimationManager.setRootContainerSize(parentSize);
        locAnimationManager.setOwner(owner);
        this._ownerOutletNames = [];
        this._ownerOutletNodes = [];
        this._ownerCallbackNames = [];
        this._ownerCallbackNodes = [];
        this._ownerCallbackEvents = [];
        this._animationManagers = new cc._Dictionary();
        var nodeGraph = this.readFileWithCleanUp(true);
        if (nodeGraph && locAnimationManager.getAutoPlaySequenceId() !== -1) {
            locAnimationManager.runAnimations(locAnimationManager.getAutoPlaySequenceId(), 0);
        }
        if (this._jsControlled) {
            var locNodes = [];
            var locAnimations = [];
            var locAnimationManagers = this._animationManagers;
            var getAllKeys = locAnimationManagers.allKeys();
            for (var i = 0; i < getAllKeys.length; i++) {
                locNodes.push(getAllKeys[i]);
                locAnimations.push(locAnimationManagers.objectForKey(getAllKeys[i]));
            }
            this._nodesWithAnimationManagers = locNodes;
            this._animationManagerForNodes = locAnimations;
        }
        return nodeGraph;
    },
    createSceneWithNodeGraphFromFile:function (ccbFileName, owner, parentSize, animationManager) {
        var node = this.readNodeGraphFromFile(ccbFileName, owner, parentSize, animationManager);
        var scene = new cc.Scene();
        scene.addChild(node);
        return scene;
    },
    getCCBMemberVariableAssigner:function () {
        return this._ccbMemberVariableAssigner;
    },
    getCCBSelectorResolver:function () {
        return this._ccbSelectorResolver;
    },
    getAnimationManager:function () {
        return this._animationManager;
    },
    setAnimationManager:function (animationManager) {
        this._animationManager = animationManager;
    },
    getAnimatedProperties:function () {
        return this._animatedProps;
    },
    getLoadedSpriteSheet:function () {
        return this._loadedSpriteSheets;
    },
    getOwner:function () {
        return this._owner;
    },
    readInt:function (signed) {
        var numBits = 0;
        while (!this._getBit()) {
            numBits++;
        }
        var current = 0;
        for (var a = numBits - 1; a >= 0; a--) {
            if (this._getBit()) {
                current |= 1 << a;
            }
        }
        current |= 1 << numBits;
        var num;
        if (signed) {
            var s = current % 2;
            if (s) {
                num = 0 | (current / 2);
            } else {
                num = 0 | (-current / 2);
            }
        } else {
            num = current - 1;
        }
        this._alignBits();
        return num;
    },
    readByte:function () {
        var byteValue = this._data[this._currentByte];
        this._currentByte++;
        return byteValue;
    },
    readBool:function () {
        return (0 !== this.readByte());
    },
    readFloat:function () {
        var type = this.readByte();
        switch (type) {
            case CCB_FLOAT0:
                return 0;
            case CCB_FLOAT1:
                return 1;
            case CCB_FLOAT_MINUS1:
                return -1;
            case CCB_FLOAT05:
                return 0.5;
            case CCB_FLOAT_INTEGER:
                return this.readInt(true);
            default:
                var pF = this._decodeFloat(23, 8);
                return pF;
        }
    },
    _decodeFloat:function (precisionBits, exponentBits) {
        var length = precisionBits + exponentBits + 1;
        var size = length >> 3;
        this._checkSize(length);
        var bias = Math.pow(2, exponentBits - 1) - 1;
        var signal = this._readBitsOnly(precisionBits + exponentBits, 1, size);
        var exponent = this._readBitsOnly(precisionBits, exponentBits, size);
        var significand = 0;
        var divisor = 2;
        var curByte = 0;
        do {
            var byteValue = this._readByteOnly(++curByte, size);
            var startBit = precisionBits % 8 || 8;
            var mask = 1 << startBit;
            while (mask >>= 1) {
                if (byteValue & mask) {
                    significand += 1 / divisor;
                }
                divisor *= 2;
            }
        } while (precisionBits -= startBit);
        this._currentByte += size;
        return exponent === (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
            : (1 + signal * -2) * (exponent || significand ? !exponent ? Math.pow(2, -bias + 1) * significand
            : Math.pow(2, exponent - bias) * (1 + significand) : 0);
    },
    _readBitsOnly:function (start, length, size) {
        var offsetLeft = (start + length) % 8;
        var offsetRight = start % 8;
        var curByte = size - (start >> 3) - 1;
        var lastByte = size + (-(start + length) >> 3);
        var diff = curByte - lastByte;
        var sum = (this._readByteOnly(curByte, size) >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1);
        if (diff && offsetLeft) {
            sum += (this._readByteOnly(lastByte++, size) & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight;
        }
        while (diff) {
            sum += this._shl(this._readByteOnly(lastByte++, size), (diff-- << 3) - offsetRight);
        }
        return sum;
    },
    _readByteOnly:function (i, size) {
        return this._data[this._currentByte + size - i - 1];
    },
    _shl:function (a, b) {
        for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) === 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
        return a;
    },
    _checkSize:function (neededBits) {
        if (!(this._currentByte + Math.ceil(neededBits / 8) < this._data.length)) {
            throw new Error("Index out of bound");
        }
    },
    readCachedString:function () {
        return this._stringCache[this.readInt(false)];
    },
    isJSControlled:function () {
        return this._jsControlled;
    },
    getOwnerCallbackNames:function () {
        return this._ownerCallbackNames;
    },
    getOwnerCallbackNodes:function () {
        return this._ownerCallbackNodes;
    },
    getOwnerCallbackControlEvents:function(){
        return this._ownerCallbackEvents;
    },
    getOwnerOutletNames:function () {
        return this._ownerOutletNames;
    },
    getOwnerOutletNodes:function () {
        return this._ownerOutletNodes;
    },
    getNodesWithAnimationManagers:function () {
        return this._nodesWithAnimationManagers;
    },
    getAnimationManagersForNodes:function () {
        return this._animationManagerForNodes;
    },
    getAnimationManagers:function () {
        return this._animationManagers;
    },
    setAnimationManagers:function (animationManagers) {
        this._animationManagers = animationManagers;
    },
    addOwnerCallbackName:function (name) {
        this._ownerCallbackNames.push(name)
    },
    addOwnerCallbackNode:function (node) {
        this._ownerCallbackNodes.push(node);
    },
    addOwnerCallbackControlEvents:function(event){
        this._ownerCallbackEvents.push(event);
    },
    addDocumentCallbackName:function (name) {
        this._animationManager.addDocumentCallbackName(name);
    },
    addDocumentCallbackNode:function (node) {
        this._animationManager.addDocumentCallbackNode(node);
    },
    addDocumentCallbackControlEvents:function(controlEvents){
        this._animationManager.addDocumentCallbackControlEvents(controlEvents);
    },
    readFileWithCleanUp:function (cleanUp) {
        if (!this._readHeader())
            return null;
        if (!this._readStringCache())
            return null;
        if (!this._readSequences())
            return null;
        var node = this._readNodeGraph();
        this._animationManagers.setObject(this._animationManager, node);
        if (cleanUp)
            this._cleanUpNodeGraph(node);
        return node;
    },
    addOwnerOutletName: function(name){
         this._ownerOutletNames.push(name);
    },
    addOwnerOutletNode: function(node){
         if(node == null)
            return;
        this._ownerOutletNodes.push(node);
    },
    _cleanUpNodeGraph:function (node) {
        node.userObject = null;
        var getChildren = node.getChildren();
        for (var i = 0, len = getChildren.length; i < len; i++) {
            this._cleanUpNodeGraph(getChildren[i]);
        }
    },
    _readCallbackKeyframesForSeq:function(seq) {
        var numKeyframes = this.readInt(false);
        if (!numKeyframes)
            return true;
        var channel = new cc.BuilderSequenceProperty();
        var locJsControlled = this._jsControlled, locAnimationManager = this._animationManager, locKeyframes = channel.getKeyframes();
        for (var i = 0; i < numKeyframes; i++) {
            var time = this.readFloat();
            var callbackName = this.readCachedString();
            var callbackType = this.readInt(false);
            var value = [ callbackName, callbackType];
            var keyframe = new cc.BuilderKeyframe();
            keyframe.setTime(time);
            keyframe.setValue(value);
            if(locJsControlled)
                locAnimationManager.getKeyframeCallbacks().push(callbackType+":"+callbackName);
            locKeyframes.push(keyframe);
        }
        seq.setCallbackChannel(channel);
        return true;
    },
    _readSoundKeyframesForSeq:function(seq) {
        var numKeyframes = this.readInt(false);
        if (!numKeyframes)
            return true;
        var channel = new cc.BuilderSequenceProperty();
        var locKeyframes = channel.getKeyframes();
        for (var i = 0; i < numKeyframes; i++) {
            var time = this.readFloat();
            var soundFile = this.readCachedString();
            var pitch = this.readFloat();
            var pan = this.readFloat();
            var gain = this.readFloat();
            var value  = [soundFile, pitch, pan, gain];
            var keyframe = new cc.BuilderKeyframe();
            keyframe.setTime(time);
            keyframe.setValue(value);
            locKeyframes.push(keyframe);
        }
        seq.setSoundChannel(channel);
        return true;
    },
    _readSequences:function () {
        var sequences = this._animationManager.getSequences();
        var numSeqs = this.readInt(false);
        for (var i = 0; i < numSeqs; i++) {
            var seq = new cc.BuilderSequence();
            seq.setDuration(this.readFloat());
            seq.setName(this.readCachedString());
            seq.setSequenceId(this.readInt(false));
            seq.setChainedSequenceId(this.readInt(true));
            if (!this._readCallbackKeyframesForSeq(seq))
                return false;
            if (!this._readSoundKeyframesForSeq(seq))
                return false;
            sequences.push(seq);
        }
        this._animationManager.setAutoPlaySequenceId(this.readInt(true));
        return true;
    },
    readKeyframe:function (type) {
        var keyframe = new cc.BuilderKeyframe();
        keyframe.setTime(this.readFloat());
        var easingType = this.readInt(false);
        var easingOpt = 0;
        var value = null;
        if (easingType === CCB_KEYFRAME_EASING_CUBIC_IN
            || easingType === CCB_KEYFRAME_EASING_CUBIC_OUT
            || easingType === CCB_KEYFRAME_EASING_CUBIC_INOUT
            || easingType === CCB_KEYFRAME_EASING_ELASTIC_IN
            || easingType === CCB_KEYFRAME_EASING_ELASTIC_OUT
            || easingType === CCB_KEYFRAME_EASING_ELASTIC_INOUT) {
            easingOpt = this.readFloat();
        }
        keyframe.setEasingType(easingType);
        keyframe.setEasingOpt(easingOpt);
        if (type === CCB_PROPTYPE_CHECK) {
            value = this.readBool();
        } else if (type === CCB_PROPTYPE_BYTE) {
            value = this.readByte();
        } else if (type === CCB_PROPTYPE_COLOR3) {
            var c = cc.color(this.readByte(), this.readByte(), this.readByte());
            value = cc.Color3BWapper.create(c);
        } else if (type === CCB_PROPTYPE_FLOATXY) {
            value = [this.readFloat(), this.readFloat()];
        } else if (type === CCB_PROPTYPE_DEGREES) {
            value = this.readFloat();
        } else if (type === CCB_PROPTYPE_SCALELOCK || type === CCB_PROPTYPE_POSITION || type === CCB_PROPTYPE_FLOATXY) {
            value = [this.readFloat(), this.readFloat()];
        } else if (type === CCB_PROPTYPE_SPRITEFRAME) {
            var spriteSheet = this.readCachedString();
            var spriteFile = this.readCachedString();
            if (spriteSheet === "") {
                spriteFile = this._ccbRootPath + spriteFile;
                var texture = cc.textureCache.addImage(spriteFile);
                var locContentSize = texture.getContentSize();
                var bounds = cc.rect(0, 0, locContentSize.width, locContentSize.height);
                value = new cc.SpriteFrame(texture, bounds);
            } else {
                spriteSheet = this._ccbRootPath + spriteSheet;
                var frameCache = cc.spriteFrameCache;
                if (this._loadedSpriteSheets.indexOf(spriteSheet) === -1) {
                    frameCache.addSpriteFrames(spriteSheet);
                    this._loadedSpriteSheets.push(spriteSheet);
                }
                value = frameCache.getSpriteFrame(spriteFile);
            }
        }
        keyframe.setValue(value);
        return keyframe;
    },
    _readHeader:function () {
        if (!this._data)
            return false;
        var magicBytes = this._readStringFromBytes(this._currentByte, 4, true);
        this._currentByte += 4;
        if (magicBytes !== 'ccbi') {
            return false;
        }
        var version = this.readInt(false);
        if (version !== CCB_VERSION) {
            cc.log("WARNING! Incompatible ccbi file version (file: " + version + " reader: " + CCB_VERSION + ")");
            return false;
        }
        this._jsControlled = this.readBool();
        this._animationManager._jsControlled = this._jsControlled;
        return true;
    },
    _readStringFromBytes:function (startIndex, strLen, reverse) {
        reverse = reverse || false;
        var strValue = "";
        var i, locData = this._data, locCurrentByte = this._currentByte;
        if (reverse) {
            for (i = strLen - 1; i >= 0; i--)
                strValue += String.fromCharCode(locData[locCurrentByte + i]);
        } else {
            for (i = 0; i < strLen; i++)
                strValue += String.fromCharCode(locData[locCurrentByte + i]);
        }
        return strValue;
    },
    _readStringCache:function () {
        var numStrings = this.readInt(false);
        for (var i = 0; i < numStrings; i++)
            this._readStringCacheEntry();
        return true;
    },
    _readStringCacheEntry:function () {
        var b0 = this.readByte();
        var b1 = this.readByte();
        var numBytes = b0 << 8 | b1;
        var str = "", locData = this._data, locCurrentByte = this._currentByte;
        for (var i = 0; i < numBytes; i++) {
            var hexChar = locData[locCurrentByte + i].toString("16").toUpperCase();
            hexChar = hexChar.length > 1 ? hexChar : "0" + hexChar;
            str += "%" + hexChar;
        }
        str = decodeURIComponent(str);
        this._currentByte += numBytes;
        this._stringCache.push(str);
    },
    _readNodeGraph:function (parent) {
        var className = this.readCachedString();
        var jsControlledName, locJsControlled = this._jsControlled, locActionManager = this._animationManager;
        if (locJsControlled)
            jsControlledName = this.readCachedString();
        var memberVarAssignmentType = this.readInt(false);
        var memberVarAssignmentName;
        if (memberVarAssignmentType !== CCB_TARGETTYPE_NONE) {
            memberVarAssignmentName = this.readCachedString();
        }
        var ccNodeLoader = this._ccNodeLoaderLibrary.getCCNodeLoader(className);
        if (!ccNodeLoader) {
            ccNodeLoader = this._ccNodeLoaderLibrary.getCCNodeLoader("CCNode");
        }
        var node = ccNodeLoader.loadCCNode(parent, this);
        if (!locActionManager.getRootNode())
            locActionManager.setRootNode(node);
        if (locJsControlled && node === locActionManager.getRootNode()) {
            locActionManager.setDocumentControllerName(jsControlledName);
        }
        var seqs = new cc._Dictionary();
        this._animatedProps = [];
        var i, locAnimatedProps = this._animatedProps;
        var numSequence = this.readInt(false);
        for (i = 0; i < numSequence; ++i) {
            var seqId = this.readInt(false);
            var seqNodeProps = new cc._Dictionary();
            var numProps = this.readInt(false);
            for (var j = 0; j < numProps; ++j) {
                var seqProp = new cc.BuilderSequenceProperty();
                seqProp.setName(this.readCachedString());
                seqProp.setType(this.readInt(false));
                locAnimatedProps.push(seqProp.getName());
                var numKeyframes = this.readInt(false);
                var locKeyframes = seqProp.getKeyframes();
                for (var k = 0; k < numKeyframes; ++k) {
                    var keyFrame = this.readKeyframe(seqProp.getType());
                    locKeyframes.push(keyFrame);
                }
                seqNodeProps.setObject(seqProp, seqProp.getName());
            }
            seqs.setObject(seqNodeProps, seqId);
        }
        if (seqs.count() > 0)
            locActionManager.addNode(node, seqs);
        ccNodeLoader.parseProperties(node, parent, this);
        var isCCBFileNode = node instanceof cc.BuilderFile;
        if (isCCBFileNode) {
            var embeddedNode = node.getCCBFileNode();
            embeddedNode.setPosition(node.getPosition());
            embeddedNode.setRotation(node.getRotation());
            embeddedNode.setScaleX(node.getScaleX());
            embeddedNode.setScaleY(node.getScaleY());
            embeddedNode.setTag(node.getTag());
            embeddedNode.setVisible(true);
            locActionManager.moveAnimationsFromNode(node, embeddedNode);
            node.setCCBFileNode(null);
            node = embeddedNode;
        }
        var target = null, locMemberAssigner = null;
        if (memberVarAssignmentType !== CCB_TARGETTYPE_NONE) {
            if (!locJsControlled) {
                if (memberVarAssignmentType === CCB_TARGETTYPE_DOCUMENTROOT) {
                    target = locActionManager.getRootNode();
                } else if (memberVarAssignmentType === CCB_TARGETTYPE_OWNER) {
                    target = this._owner;
                }
                if (!target) {
                    var assigned = false;
                    if (target.onAssignCCBMemberVariable)
                        assigned = target.onAssignCCBMemberVariable(target, memberVarAssignmentName, node);
                    locMemberAssigner = this._ccbMemberVariableAssigner;
                    if (!assigned && locMemberAssigner != null && locMemberAssigner.onAssignCCBMemberVariable) {
                        locMemberAssigner.onAssignCCBMemberVariable(target, memberVarAssignmentName, node);
                    }
                }
            } else {
                if (memberVarAssignmentType === CCB_TARGETTYPE_DOCUMENTROOT) {
                    locActionManager.addDocumentOutletName(memberVarAssignmentName);
                    locActionManager.addDocumentOutletNode(node);
                } else {
                    this._ownerOutletNames.push(memberVarAssignmentName);
                    this._ownerOutletNodes.push(node);
                }
            }
        }
        if (ccNodeLoader.getCustomProperties().length > 0) {
            var customAssigned = false;
            if(!locJsControlled) {
                target = node;
                if(target != null && target.onAssignCCBCustomProperty != null) {
                    var customProperties = ccNodeLoader.getCustomProperties();
                    var customPropKeys = customProperties.allKeys();
                    for(i = 0;i < customPropKeys.length;i++){
                        var customPropValue = customProperties.objectForKey(customPropKeys[i]);
                        customAssigned = target.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue);
                        locMemberAssigner = this._ccbMemberVariableAssigner;
                        if(!customAssigned && (locMemberAssigner != null) && (locMemberAssigner.onAssignCCBCustomProperty != null))
                            customAssigned = locMemberAssigner.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue);
                    }
                }
            }
        }
        this._animatedProps = null;
        var numChildren = this.readInt(false);
        for (i = 0; i < numChildren; i++) {
            var child = this._readNodeGraph(node);
            node.addChild(child);
        }
        if (!isCCBFileNode) {
            if (node != null && node.onNodeLoaded)
                node.onNodeLoaded(node, ccNodeLoader);
            else if (this._ccNodeLoaderListener != null)
                this._ccNodeLoaderListener.onNodeLoaded(node, ccNodeLoader);
        }
        return node;
    },
    _getBit:function () {
        var bit = (this._data[this._currentByte] & (1 << this._currentBit)) !== 0;
        this._currentBit++;
        if (this._currentBit >= 8) {
            this._currentBit = 0;
            this._currentByte++;
            if(this._currentByte > this._data.length)
                throw new Error("out of the data bound");
        }
        return bit;
    },
    _alignBits:function () {
        if (this._currentBit) {
            this._currentBit = 0;
            this._currentByte++;
        }
    },
    _readUTF8:function () {
    }
});
cc.BuilderReader._ccbResolutionScale = 1;
cc.BuilderReader.setResolutionScale = function(scale){
    cc.BuilderReader._ccbResolutionScale = scale;
};
cc.BuilderReader.getResolutionScale = function () {
    return cc.BuilderReader._ccbResolutionScale;
};
cc.BuilderReader.loadAsScene = function (ccbFilePath, owner, parentSize, ccbRootPath) {
    ccbRootPath = ccbRootPath || cc.BuilderReader.getResourcePath();
    var getNode = cc.BuilderReader.load(ccbFilePath, owner, parentSize, ccbRootPath);
    var scene = new cc.Scene();
    scene.addChild(getNode);
    return scene;
};
cc.BuilderReader._controllerClassCache = {};
cc.BuilderReader.registerController = function(controllerName, controller){
    cc.BuilderReader._controllerClassCache[controllerName] = cc.Class.extend(controller);
};
cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
    ccbRootPath = ccbRootPath || cc.BuilderReader.getResourcePath();
    var reader = new cc.BuilderReader(cc.NodeLoaderLibrary.newDefaultCCNodeLoaderLibrary());
    reader.setCCBRootPath(ccbRootPath);
    if((ccbFilePath.length < 5)||(ccbFilePath.toLowerCase().lastIndexOf(".ccbi") !== ccbFilePath.length - 5))
        ccbFilePath = ccbFilePath + ".ccbi";
    var node = reader.readNodeGraphFromFile(ccbFilePath, owner, parentSize);
    var i;
    var callbackName, callbackNode, callbackControlEvents, outletName, outletNode;
    if (owner) {
        var ownerCallbackNames = reader.getOwnerCallbackNames();
        var ownerCallbackNodes = reader.getOwnerCallbackNodes();
        var ownerCallbackControlEvents = reader.getOwnerCallbackControlEvents();
        for (i = 0; i < ownerCallbackNames.length; i++) {
            callbackName = ownerCallbackNames[i];
            callbackNode = ownerCallbackNodes[i];
            callbackControlEvents = ownerCallbackControlEvents[i];
            if(callbackNode instanceof cc.ControlButton)
                callbackNode.addTargetWithActionForControlEvents(owner, owner[callbackName], callbackControlEvents);
            else
                callbackNode.setCallback(owner[callbackName], owner);
        }
        var ownerOutletNames = reader.getOwnerOutletNames();
        var ownerOutletNodes = reader.getOwnerOutletNodes();
        for (i = 0; i < ownerOutletNames.length; i++) {
            outletName = ownerOutletNames[i];
            outletNode = ownerOutletNodes[i];
            owner[outletName] = outletNode;
        }
    }
    var nodesWithAnimationManagers = reader.getNodesWithAnimationManagers();
    var animationManagersForNodes = reader.getAnimationManagersForNodes();
    if(!nodesWithAnimationManagers || !animationManagersForNodes)
        return node;
    var controllerClassCache = cc.BuilderReader._controllerClassCache;
    for (i = 0; i < nodesWithAnimationManagers.length; i++) {
        var innerNode = nodesWithAnimationManagers[i];
        var animationManager = animationManagersForNodes[i];
        var j;
        innerNode.animationManager = animationManager;
        var controllerName = animationManager.getDocumentControllerName();
        if (!controllerName) continue;
        var controllerClass = controllerClassCache[controllerName];
        if(!controllerClass) throw new Error("Can not find controller : " + controllerName);
        var controller = new controllerClass();
        controller.controllerName = controllerName;
        innerNode.controller = controller;
        controller.rootNode = innerNode;
        var documentCallbackNames = animationManager.getDocumentCallbackNames();
        var documentCallbackNodes = animationManager.getDocumentCallbackNodes();
        var documentCallbackControlEvents = animationManager.getDocumentCallbackControlEvents();
        for (j = 0; j < documentCallbackNames.length; j++) {
            callbackName = documentCallbackNames[j];
            callbackNode = documentCallbackNodes[j];
            callbackControlEvents = documentCallbackControlEvents[j];
            if(callbackNode instanceof cc.ControlButton)
                callbackNode.addTargetWithActionForControlEvents(controller, controller[callbackName], callbackControlEvents);
            else
                callbackNode.setCallback(controller[callbackName], controller);
        }
        var documentOutletNames = animationManager.getDocumentOutletNames();
        var documentOutletNodes = animationManager.getDocumentOutletNodes();
        for (j = 0; j < documentOutletNames.length; j++) {
            outletName = documentOutletNames[j];
            outletNode = documentOutletNodes[j];
            controller[outletName] = outletNode;
        }
        if (controller.onDidLoadFromCCB && cc.isFunction(controller.onDidLoadFromCCB))
            controller.onDidLoadFromCCB();
        var keyframeCallbacks = animationManager.getKeyframeCallbacks();
        for (j = 0; j < keyframeCallbacks.length; j++) {
            var callbackSplit = keyframeCallbacks[j].split(":");
            var callbackType = callbackSplit[0];
            var kfCallbackName = callbackSplit[1];
            if (callbackType == 1){
                animationManager.setCallFunc(cc.callFunc(controller[kfCallbackName], controller), keyframeCallbacks[j]);
            } else if (callbackType == 2 && owner) {// Owner callback
                animationManager.setCallFunc(cc.callFunc(owner[kfCallbackName], owner), keyframeCallbacks[j]);
            }
        }
    }
    animationManager.runAnimations(animationManager.getAutoPlaySequenceId(), 0);
    return node;
};
cc.BuilderReader._resourcePath = "";
cc.BuilderReader.setResourcePath = function (rootPath) {
    cc.BuilderReader._resourcePath = rootPath;
};
cc.BuilderReader.getResourcePath = function () {
    return cc.BuilderReader._resourcePath;
};
cc.BuilderReader.lastPathComponent = function (pathStr) {
    var slashPos = pathStr.lastIndexOf("/");
    if (slashPos !== -1) {
        return pathStr.substring(slashPos + 1, pathStr.length - slashPos);
    }
    return pathStr;
};
cc.BuilderReader.deletePathExtension = function (pathStr) {
    var dotPos = pathStr.lastIndexOf(".");
    if (dotPos !== -1) {
        return pathStr.substring(0, dotPos);
    }
    return pathStr;
};
cc.BuilderReader.toLowerCase = function (sourceStr) {
    return sourceStr.toLowerCase();
};
cc.BuilderReader.endsWith = function (sourceStr, ending) {
    if (sourceStr.length >= ending.length)
        return (sourceStr.lastIndexOf(ending) === 0);
    else
        return false;
};
cc.BuilderReader.concat = function (stringA, stringB) {
    return stringA + stringB;
};
cc.loader.register(["ccbi"], cc._binaryLoader);
cc.INT_VALUE = 0;
cc.FLOAT_VALUE = 1;
cc.POINTER_VALUE = 2;
cc.BOOL_VALUE = 3;
cc.UNSIGNEDCHAR_VALUE = 4;
cc.Color3BWapper = cc.Class.extend({
    _color:null,
    ctor:function () {
        this._color = cc.color(0, 0, 0);
    },
    getColor:function () {
        return this._color;
    }
});
cc.Color3BWapper.create = function (color) {
    var ret = new cc.Color3BWapper();
    if (ret) {
        ret._color.r = color.r;
        ret._color.g = color.g;
        ret._color.b = color.b;
    }
    return ret;
};
cc.BuilderValue = cc.Class.extend({
    _value:null,
    _type:0,
    getIntValue:function () {
    },
    getFloatValue:function () {
    },
    getBoolValue:function () {
    },
    getByteValue:function () {
    },
    getPointer:function () {
    },
    getValue:function(){
        return this._value;
    }
});
cc.BuilderValue.create = function (value) {
    return new cc.BuilderValue();
};
cc.BuilderKeyframe = cc.Class.extend({
    _value:null,
    _time:0,
    _easingType:0,
    _easingOpt:0,
    getValue:function(){
        return this._value;
    },
    setValue:function(value){
        this._value = value;
    },
    getTime:function(){
        return this._time;
    },
    setTime:function(time){
        this._time = time;
    },
    getEasingType:function(){
        return this._easingType;
    },
    setEasingType:function(easingType){
        this._easingType = easingType;
    },
    getEasingOpt:function(){
        return this._easingOpt;
    },
    setEasingOpt:function(easingOpt){
        this._easingOpt = easingOpt;
    }
});
cc.BuilderSequence = cc.Class.extend({
    _duration:0,
    _name:"",
    _sequenceId:0,
    _chainedSequenceId:0,
    _callbackChannel:null,
    _soundChannel:null,
    ctor:function(){
        this._name = "";
    },
    getDuration:function(){
        return this._duration;
    },
    setDuration:function(duration){
        this._duration = duration;
    },
    getName:function(){
        return this._name;
    },
    setName:function(name){
        this._name = name;
    },
    getSequenceId:function(){
        return this._sequenceId;
    },
    setSequenceId:function(sequenceId){
        this._sequenceId = sequenceId;
    },
    getChainedSequenceId:function(){
        return this._chainedSequenceId;
    },
    setChainedSequenceId:function(chainedSequenceId){
        this._chainedSequenceId = chainedSequenceId;
    },
    getCallbackChannel:function() {
        return this._callbackChannel;
    },
    setCallbackChannel:function(channel) {
        this._callbackChannel = channel;
    },
    getSoundChannel:function() {
        return this._soundChannel;
    },
    setSoundChannel:function(channel) {
        this._soundChannel = channel;
    }
});
cc.BuilderSequenceProperty = cc.Class.extend({
    _name : null,
    _type:0,
    _keyFrames:null,
    ctor:function(){
        this.init();
    },
    init:function(){
        this._keyFrames = [];
        this._name = "";
    },
    getName:function(){
        return this._name;
    },
    setName :function(name){
        this._name = name;
    },
    getType:function(){
        return this._type;
    },
    setType :function(type){
        this._type = type;
    },
    getKeyframes:function(){
        return this._keyFrames;
    }
});
cc.getAbsolutePosition = function(pt, type, containerSize, propName){
    var absPt = cc.p(0,0);
    if(type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT)
        absPt = pt;
    else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){
        absPt.x = pt.x;
        absPt.y = containerSize.height - pt.y;
    } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){
        absPt.x = containerSize.width - pt.x;
        absPt.y = containerSize.height - pt.y;
    } else if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) {
        absPt.x = containerSize.width - pt.x;
        absPt.y = pt.y;
    } else if (type === CCB_POSITIONTYPE_PERCENT) {
        absPt.x = (containerSize.width * pt.x / 100.0);
        absPt.y = (containerSize.height * pt.y / 100.0);
    } else if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) {
        var resolutionScale = cc.BuilderReader.getResolutionScale();
        absPt.x = pt.x * resolutionScale;
        absPt.y = pt.y * resolutionScale;
    }
    return absPt;
};
cc._getAbsolutePosition = function(x, y, type, containerSize, propName){
    var absPt = cc.p(0,0);
    if(type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT){
        absPt.x = x;
        absPt.y = y;
    } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){
        absPt.x = x;
        absPt.y = containerSize.height - y;
    } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){
        absPt.x = containerSize.width - x;
        absPt.y = containerSize.height - y;
    } else if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) {
        absPt.x = containerSize.width - x;
        absPt.y = y;
    } else if (type === CCB_POSITIONTYPE_PERCENT) {
        absPt.x = (containerSize.width * x / 100.0);
        absPt.y = (containerSize.height * y / 100.0);
    } else if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) {
        var resolutionScale = cc.BuilderReader.getResolutionScale();
        absPt.x = x * resolutionScale;
        absPt.y = y * resolutionScale;
    }
    return absPt;
};
cc.setRelativeScale = function(node,scaleX, scaleY, type, propName){
    if(!node)
        throw new Error("cc.setRelativeScale(): node should be non-null");
    if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) {
        var resolutionScale = cc.BuilderReader.getResolutionScale();
        scaleX *= resolutionScale;
        scaleY *= resolutionScale;
    }
    node.setScaleX(scaleX);
    node.setScaleY(scaleY);
};
cc.BuilderAnimationManagerDelegate = cc.Class.extend({
    completedAnimationSequenceNamed:function (name) {}
});
cc.BuilderAnimationManager = cc.Class.extend({
    _sequences:null,
    _nodeSequences:null,
    _baseValues:null,
    _autoPlaySequenceId:0,
    _rootNode:null,
    _owner:null,
    _rootContainerSize:null,
    _delegate:null,
    _runningSequence:null,
    _documentOutletNames:null,
    _documentOutletNodes:null,
    _documentCallbackNames:null,
    _documentCallbackNodes:null,
    _documentCallbackControlEvents:null,
    _documentControllerName:"",
    _lastCompletedSequenceName:"",
    _keyframeCallbacks:null,
    _keyframeCallFuncs:null,
    _animationCompleteCallbackFunc:null,
    _target:null,
    _jsControlled:false,
    ctor:function () {
        this._rootContainerSize = cc.size(0, 0);
        this.init();
    },
    init:function () {
        this._sequences = [];
        this._nodeSequences = new cc._Dictionary();
        this._baseValues = new cc._Dictionary();
        this._documentOutletNames = [];
        this._documentOutletNodes = [];
        this._documentCallbackNames = [];
        this._documentCallbackNodes = [];
        this._documentCallbackControlEvents = [];
        this._keyframeCallbacks = [];
        this._keyframeCallFuncs = {};
        return true;
    },
    getSequences:function () {
        return this._sequences;
    },
    setSequences:function(seqs){
        this._sequences = seqs;
    },
    getAutoPlaySequenceId:function () {
        return this._autoPlaySequenceId;
    },
    setAutoPlaySequenceId:function (autoPlaySequenceId) {
        this._autoPlaySequenceId = autoPlaySequenceId;
    },
    getRootNode:function () {
        return this._rootNode;
    },
    setRootNode:function (rootNode) {
        this._rootNode = rootNode;
    },
    getOwner:function () {
        return this._owner;
    },
    setOwner:function (owner) {
        this._owner = owner;
    },
    addDocumentCallbackNode:function(node){
        this._documentCallbackNodes.push(node);
    },
    addDocumentCallbackName:function(name){
        this._documentCallbackNames.push(name);
    },
    addDocumentCallbackControlEvents:function(controlEvents){
        this._documentCallbackControlEvents.push(controlEvents);
    },
    addDocumentOutletNode:function(node){
        this._documentOutletNodes.push(node);
    },
    addDocumentOutletName:function(name){
        this._documentOutletNames.push(name);
    },
    setDocumentControllerName:function(name){
        this._documentControllerName = name;
    },
    getDocumentControllerName:function(){
        return this._documentControllerName;
    },
    getDocumentCallbackNames:function(){
        return this._documentCallbackNames;
    },
    getDocumentCallbackNodes:function(){
        return this._documentCallbackNodes;
    },
    getDocumentCallbackControlEvents:function(){
        return this._documentCallbackControlEvents;
    },
    getDocumentOutletNames:function(){
        return this._documentOutletNames;
    },
    getDocumentOutletNodes:function(){
        return this._documentOutletNodes;
    },
    getLastCompletedSequenceName:function(){
        return this._lastCompletedSequenceName;
    },
    getKeyframeCallbacks:function(){
        return this._keyframeCallbacks;
    },
    getRootContainerSize:function () {
        return this._rootContainerSize;
    },
    setRootContainerSize:function (rootContainerSize) {
        this._rootContainerSize = cc.size(rootContainerSize.width, rootContainerSize.height);
    },
    getDelegate:function () {
        return this._delegate;
    },
    setDelegate:function (delegate) {
        this._delegate = delegate;
    },
    getRunningSequenceName:function () {
        if(this._runningSequence)
            return this._runningSequence.getName();
        return null;
    },
    getContainerSize:function (node) {
        if (node)
            return node.getContentSize();
        else
            return this._rootContainerSize;
    },
    addNode:function (node, seq) {
        this._nodeSequences.setObject(seq, node);
    },
    setBaseValue:function (value, node, propName) {
        var props = this._baseValues.objectForKey(node);
        if (!props) {
            props = new cc._Dictionary();
            this._baseValues.setObject(props, node);
        }
        props.setObject(value, propName);
    },
    moveAnimationsFromNode:function(fromNode,toNode){
        var locBaseValues = this._baseValues;
        var baseValue = locBaseValues.objectForKey(fromNode);
        if(baseValue !== null) {
            locBaseValues.setObject(baseValue, toNode);
            locBaseValues.removeObjectForKey(fromNode);
        }
        var locNodeSequences = this._nodeSequences;
        var seqs = locNodeSequences.objectForKey(fromNode);
        if(seqs != null) {
            locNodeSequences.setObject(seqs, toNode);
            locNodeSequences.removeObjectForKey(fromNode);
        }
    },
    getActionForCallbackChannel:function(channel) {
        var lastKeyframeTime = 0;
        var actions = [];
        var keyframes = channel.getKeyframes();
        var numKeyframes = keyframes.length;
        for (var i = 0; i < numKeyframes; ++i) {
            var keyframe = keyframes[i];
            var timeSinceLastKeyframe = keyframe.getTime() - lastKeyframeTime;
            lastKeyframeTime = keyframe.getTime();
            if(timeSinceLastKeyframe > 0) {
                actions.push(cc.delayTime(timeSinceLastKeyframe));
            }
            var keyVal = keyframe.getValue();
            var selectorName = keyVal[0];
            var selectorTarget = keyVal[1];
            if(this._jsControlled) {
                var callbackName = selectorTarget + ":" + selectorName;
                var callback = this._keyframeCallFuncs[callbackName];
                if(callback != null)
                    actions.push(callback);
            } else {
                var target;
                if(selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT)
                    target = this._rootNode;
                else if (selectorTarget === CCB_TARGETTYPE_OWNER)
                    target = this._owner;
                if(target != null) {
                    if(selectorName.length > 0) {
                        var selCallFunc = 0;
                        if(target.onResolveCCBCCCallFuncSelector != null)
                            selCallFunc = target.onResolveCCBCCCallFuncSelector(target, selectorName);
                        if(selCallFunc === 0)
                            cc.log("Skipping selector '" + selectorName + "' since no CCBSelectorResolver is present.");
                        else
                            actions.push(cc.callFunc(selCallFunc,target));
                    } else {
                        cc.log("Unexpected empty selector.");
                    }
                }
            }
        }
        if(actions.length < 1)
            return null;
        return cc.sequence(actions);
    },
    getActionForSoundChannel:function(channel) {
        var lastKeyframeTime = 0;
        var actions = [];
        var keyframes = channel.getKeyframes();
        var numKeyframes = keyframes.length;
        for (var i = 0; i < numKeyframes; ++i) {
            var keyframe = keyframes[i];
            var timeSinceLastKeyframe = keyframe.getTime() - lastKeyframeTime;
            lastKeyframeTime = keyframe.getTime();
            if(timeSinceLastKeyframe > 0) {
                actions.push(cc.delayTime(timeSinceLastKeyframe));
            }
            var keyVal = keyframe.getValue();
            var soundFile = cc.BuilderReader.getResourcePath() + keyVal[0];
            var pitch = parseFloat(keyVal[1]), pan = parseFloat(keyVal[2]), gain = parseFloat(keyVal[3]);
            actions.push(cc.BuilderSoundEffect.create(soundFile, pitch, pan, gain));
        }
        if(actions.length < 1)
            return null;
        return cc.sequence(actions);
    },
    runAnimationsForSequenceNamed:function(name){
        this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), 0);
    },
    runAnimationsForSequenceNamedTweenDuration:function(name, tweenDuration){
         this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), tweenDuration);
    },
    runAnimationsForSequenceIdTweenDuration:function(nSeqId, tweenDuration){
        if(nSeqId === -1)
            throw new Error("cc.BuilderAnimationManager.runAnimationsForSequenceIdTweenDuration(): Sequence id should not be -1");
        tweenDuration = tweenDuration || 0;
        this._rootNode.stopAllActions();
        var allKeys = this._nodeSequences.allKeys();
        for(var i  = 0,len = allKeys.length  ; i< len;i++){
            var node = allKeys[i];
            node.stopAllActions();
            var seqs = this._nodeSequences.objectForKey(node);
            var seqNodeProps = seqs.objectForKey(nSeqId);
            var j;
            var seqNodePropNames = [];
            if(seqNodeProps){
                var propKeys = seqNodeProps.allKeys();
                for(j = 0; j < propKeys.length; j++){
                    var propName = propKeys[j];
                    var seqProp = seqNodeProps.objectForKey(propName);
                    seqNodePropNames.push(propName);
                    this._setFirstFrame(node, seqProp,tweenDuration);
                    this._runAction(node,seqProp,tweenDuration);
                }
            }
            var nodeBaseValues = this._baseValues.objectForKey(node);
            if(nodeBaseValues){
                var baseKeys = nodeBaseValues.allKeys();
                for(j = 0; j < baseKeys.length;j++){
                    var selBaseKey =  baseKeys[j];
                    if(seqNodePropNames.indexOf(selBaseKey) === -1){
                        var value = nodeBaseValues.objectForKey(selBaseKey);
                        if(value != null)
                            this._setAnimatedProperty(selBaseKey,node, value, tweenDuration);
                    }
                }
            }
        }
        var seq = this._getSequence(nSeqId);
        var completeAction = cc.sequence(cc.delayTime(seq.getDuration() + tweenDuration),
            cc.callFunc(this._sequenceCompleted,this));
        this._rootNode.runAction(completeAction);
        var action;
        if (seq.getCallbackChannel()) {
            action = this.getActionForCallbackChannel(seq.getCallbackChannel());
            if (action) {
                this._rootNode.runAction(action);
            }
        }
        if (seq.getSoundChannel()) {
            action = this.getActionForSoundChannel(seq.getSoundChannel());
            if (action) {
                this._rootNode.runAction(action);
            }
        }
        this._runningSequence = this._getSequence(nSeqId);
    },
    runAnimations:function (name, tweenDuration) {
        tweenDuration = tweenDuration || 0;
        var nSeqId;
        if(cc.isString(name))
            nSeqId = this._getSequenceId(name);
        else
            nSeqId = name;
        this.runAnimationsForSequenceIdTweenDuration(nSeqId, tweenDuration);
    },
    setAnimationCompletedCallback:function(target,callbackFunc){
        this._target = target;
        this._animationCompleteCallbackFunc = callbackFunc;
    },
    setCompletedAnimationCallback:function(target,callbackFunc){
        this.setAnimationCompletedCallback(target,callbackFunc);
    },
    setCallFunc:function(callFunc, callbackNamed) {
        this._keyframeCallFuncs[callbackNamed] = callFunc;
    },
    debug:function () {
    },
    _getBaseValue:function (node, propName) {
        var props = this._baseValues.objectForKey(node);
        if (props)
            return props.objectForKey(propName);
        return null;
    },
    _getSequenceId:function (sequenceName) {
        var element = null;
        var locSequences = this._sequences;
        for (var i = 0, len = locSequences.length; i < len; i++) {
            element = locSequences[i];
            if (element && element.getName() === sequenceName)
                return element.getSequenceId();
        }
        return -1;
    },
    _getSequence:function (sequenceId) {
        var element = null;
        var locSequences = this._sequences;
        for (var i = 0, len = locSequences.length; i < len; i++) {
            element = locSequences[i];
            if (element && element.getSequenceId() === sequenceId)
                return element;
        }
        return null;
    },
    _getAction:function (keyframe0, keyframe1, propName, node) {
        var duration = keyframe1.getTime() - (keyframe0 ? keyframe0.getTime() : 0);
        var getArr,type,getValueArr, x, y;
        if (propName === "rotation") {
            return cc.BuilderRotateTo.create(duration, keyframe1.getValue());
        } else if (propName === "rotationX") {
            return cc.BuilderRotateXTo.create(duration, keyframe1.getValue());
        } else if (propName === "rotationY") {
            return cc.BuilderRotateYTo.create(duration, keyframe1.getValue());
        } else if (propName === "opacity") {
            return cc.fadeTo(duration, keyframe1.getValue());
        } else if (propName === "color") {
            var selColor = keyframe1.getValue().getColor();
            return cc.tintTo(duration, selColor.r, selColor.g, selColor.b);
        } else if (propName === "visible") {
            var isVisible = keyframe1.getValue();
            if (isVisible) {
                return cc.sequence(cc.delayTime(duration), cc.show());
            } else {
                return cc.sequence(cc.delayTime(duration), cc.hide());
            }
        } else if (propName === "displayFrame") {
            return cc.sequence(cc.delayTime(duration), cc.BuilderSetSpriteFrame.create(keyframe1.getValue()));
        } else if(propName === "position"){
            getArr = this._getBaseValue(node,propName);
            type = getArr[2];
            getValueArr = keyframe1.getValue();
            x = getValueArr[0];
            y = getValueArr[1];
            var containerSize = this.getContainerSize(node.getParent());
            var absPos = cc._getAbsolutePosition(x,y, type,containerSize,propName);
            return cc.moveTo(duration,absPos);
        } else if( propName === "scale"){
            getArr = this._getBaseValue(node,propName);
            type = getArr[2];
            getValueArr = keyframe1.getValue();
            x = getValueArr[0];
            y = getValueArr[1];
            if(type === CCB_SCALETYPE_MULTIPLY_RESOLUTION){
                var resolutionScale = cc.BuilderReader.getResolutionScale();
                x *= resolutionScale;
                y *= resolutionScale;
            }
            return cc.scaleTo(duration,x,y);
        } else if( propName === "skew") {
            getValueArr = keyframe1.getValue();
            x = getValueArr[0];
            y = getValueArr[1];
            return cc.skewTo(duration,x,y);
        } else {
            cc.log("BuilderReader: Failed to create animation for property: " + propName);
        }
        return null;
    },
    _setAnimatedProperty:function (propName, node, value, tweenDuration) {
        if(tweenDuration > 0){
            var kf1 = new cc.BuilderKeyframe();
            kf1.setValue(value);
            kf1.setTime(tweenDuration);
            kf1.setEasingType(CCB_KEYFRAME_EASING_LINEAR);
            var tweenAction = this._getAction(null, kf1, propName, node);
            node.runAction(tweenAction);
        } else {
            var getArr, nType, x,y;
            if(propName === "position"){
                getArr = this._getBaseValue(node,propName);
                nType = getArr[2];
                x = value[0];
                y = value[1];
                node.setPosition(cc._getAbsolutePosition(x,y,nType, this.getContainerSize(node.getParent()),propName));
            }else if(propName === "scale"){
                getArr = this._getBaseValue(node,propName);
                nType = getArr[2];
                x = value[0];
                y = value[1];
                cc.setRelativeScale(node,x,y,nType,propName);
            } else if( propName === "skew") {
                x = value[0];
                y = value[1];
                node.setSkewX(x);
                node.setSkewY(y);
            }else {
                if(propName === "rotation"){
                    node.setRotation(value);
                }  else if(propName === "rotationX")
                {
                    node.setRotationSkewX(value);
                }else if(propName === "rotationY")
                {
                    node.setRotationSkewY(value);
                }else if(propName === "opacity"){
                    node.setOpacity(value);
                } else if(propName === "displayFrame"){
                    node.setSpriteFrame(value);
                } else if(propName === "color"){
                    var ccColor3B = value.getColor();
                    if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
                        node.setColor(ccColor3B);
                    }
                } else if( propName === "visible"){
                    value = value || false;
                    node.setVisible(value);
                } else {
                    cc.log("unsupported property name is "+ propName);
                }
            }
        }
    },
    _setFirstFrame:function (node, seqProp, tweenDuration) {
        var keyframes = seqProp.getKeyframes();
        if (keyframes.length === 0) {
            var baseValue = this._getBaseValue(node, seqProp.getName());
            if(!baseValue)
                cc.log("cc.BuilderAnimationManager._setFirstFrame(): No baseValue found for property");
            this._setAnimatedProperty(seqProp.getName(), node, baseValue, tweenDuration);
        } else {
            var keyframe = keyframes[0];
            this._setAnimatedProperty(seqProp.getName(), node, keyframe.getValue(), tweenDuration);
        }
    },
    _getEaseAction:function (action, easingType, easingOpt) {
        if (easingType === CCB_KEYFRAME_EASING_LINEAR || easingType === CCB_KEYFRAME_EASING_INSTANT ) {
            return action;
        } else if (easingType === CCB_KEYFRAME_EASING_CUBIC_IN) {
            return action.easing(cc.easeIn(easingOpt));
        } else if (easingType === CCB_KEYFRAME_EASING_CUBIC_OUT) {
            return action.easing(cc.easeOut(easingOpt));
        } else if (easingType === CCB_KEYFRAME_EASING_CUBIC_INOUT) {
            return action.easing(cc.easeInOut(easingOpt));
        } else if (easingType === CCB_KEYFRAME_EASING_BACK_IN) {
            return action.easing(cc.easeBackIn());
        } else if (easingType === CCB_KEYFRAME_EASING_BACK_OUT) {
            return action.easing(cc.easeBackOut());
        } else if (easingType === CCB_KEYFRAME_EASING_BACK_INOUT) {
            return action.easing(cc.easeBackInOut());
        } else if (easingType === CCB_KEYFRAME_EASING_BOUNCE_IN) {
            return action.easing(cc.easeBounceIn());
        } else if (easingType === CCB_KEYFRAME_EASING_BOUNCE_OUT) {
            return action.easing(cc.easeBounceOut());
        } else if (easingType === CCB_KEYFRAME_EASING_BOUNCE_INOUT) {
            return action.easing(cc.easeBounceInOut());
        } else if (easingType === CCB_KEYFRAME_EASING_ELASTIC_IN) {
            return action.easing(cc.easeElasticIn(easingOpt));
        } else if (easingType === CCB_KEYFRAME_EASING_ELASTIC_OUT) {
            return action.easing(cc.easeElasticOut(easingOpt));
        } else if (easingType === CCB_KEYFRAME_EASING_ELASTIC_INOUT) {
            return action.easing(cc.easeElasticInOut(easingOpt));
        } else {
            cc.log("BuilderReader: Unknown easing type " + easingType);
            return action;
        }
    },
    _runAction:function (node, seqProp, tweenDuration) {
        var keyframes = seqProp.getKeyframes();
        var numKeyframes = keyframes.length;
        if (numKeyframes > 1) {
            var actions = [];
            var keyframeFirst = keyframes[0];
            var timeFirst = keyframeFirst.getTime() + tweenDuration;
            if (timeFirst > 0) {
                actions.push(cc.delayTime(timeFirst));
            }
            for (var i = 0; i < numKeyframes - 1; ++i) {
                var kf0 = keyframes[i];
                var kf1 = keyframes[(i+1)];
                var action = this._getAction(kf0, kf1, seqProp.getName(), node);
                if (action) {
                    action = this._getEaseAction(action, kf0.getEasingType(), kf0.getEasingOpt());
                    actions.push(action);
                }
            }
            node.runAction(cc.sequence(actions));
        }
    },
    _sequenceCompleted:function () {
        var locRunningSequence = this._runningSequence;
        var locRunningName = locRunningSequence.getName();
        if(this._lastCompletedSequenceName != locRunningSequence.getName()){
            this._lastCompletedSequenceName = locRunningSequence.getName();
        }
        var nextSeqId = locRunningSequence.getChainedSequenceId();
        this._runningSequence = null;
        if (nextSeqId !== -1)
            this.runAnimations(nextSeqId, 0);
        if (this._delegate)
            this._delegate.completedAnimationSequenceNamed(locRunningName);
        if(this._target && this._animationCompleteCallbackFunc){
            this._animationCompleteCallbackFunc.call(this._target);
        }
    }
});
cc.BuilderSetSpriteFrame = cc.ActionInstant.extend({
    _spriteFrame:null,
    initWithSpriteFrame:function (spriteFrame) {
        this._spriteFrame = spriteFrame;
        return true;
    },
    update:function (time) {
        this.target.setSpriteFrame(this._spriteFrame);
    }
});
cc.BuilderSetSpriteFrame.create = function (spriteFrame) {
    var ret = new cc.BuilderSetSpriteFrame();
    if (ret) {
        if (ret.initWithSpriteFrame(spriteFrame))
            return ret;
    }
    return null;
};
cc.BuilderRotateTo = cc.ActionInterval.extend({
    _startAngle:0,
    _dstAngle:0,
    _diffAngle:0,
    initWithDuration:function (duration, angle) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._dstAngle = angle;
            return true;
        } else {
            return false;
        }
    },
    update:function (time) {
        this.target.setRotation(this._startAngle + (this._diffAngle * time));
    },
    startWithTarget:function (node) {
        cc.ActionInterval.prototype.startWithTarget.call(this, node);
        this._startAngle = this.target.getRotation();
        this._diffAngle = this._dstAngle - this._startAngle;
    }
});
cc.BuilderRotateTo.create = function (duration, angle) {
    var ret = new cc.BuilderRotateTo();
    if (ret) {
        if (ret.initWithDuration(duration, angle))
            return ret;
    }
    return null;
};
cc.BuilderRotateXTo = cc.ActionInterval.extend({
});
cc.BuilderRotateXTo.create = function (duration, angle) {
    throw new Error("rotationX has not been implemented in cocos2d-html5");
};
cc.BuilderRotateYTo = cc.ActionInterval.extend({
});
cc.BuilderRotateYTo.create = function (duration, angle) {
    throw new Error("rotationY has not been implemented in cocos2d-html5");
};
cc.BuilderSoundEffect = cc.ActionInstant.extend({
    init:function(file) {
        this._file = file;
        return true;
    },
    update:function(dt) {
        cc.audioEngine.playEffect(this._file);
    }
});
cc.BuilderSoundEffect.create = function (file, pitch, pan, gain) {
    var ret = new cc.BuilderSoundEffect();
    if (ret && ret.init(file)) {
            return ret;
    }
    return null;
};
cc.DOM = {};
cc.DOM._addMethods = function (node) {
    for (var funcs in cc.DOM.methods) {
        node[funcs] = cc.DOM.methods[funcs];
    }
    cc.defineGetterSetter(node, "x", node.getPositionX, node.setPositionX);
    cc.defineGetterSetter(node, "y", node.getPositionY, node.setPositionY);
    cc.defineGetterSetter(node, "width", node._getWidth, node._setWidth);
    cc.defineGetterSetter(node, "height", node._getHeight, node._setHeight);
    cc.defineGetterSetter(node, "anchorX", node._getAnchorX, node._setAnchorX);
    cc.defineGetterSetter(node, "anchorY", node._getAnchorY, node._setAnchorY);
    cc.defineGetterSetter(node, "scale", node.getScale, node.setScale);
    cc.defineGetterSetter(node, "scaleX", node.getScaleX, node.setScaleX);
    cc.defineGetterSetter(node, "scaleY", node.getScaleY, node.setScaleY);
    cc.defineGetterSetter(node, "rotation", node.getRotation, node.setRotation);
     cc.defineGetterSetter(node, "skewX", node.getSkewX, node.setSkewX);
    cc.defineGetterSetter(node, "skewY", node.getSkewY, node.setSkewY);
    cc.defineGetterSetter(node, "visible", node.isVisible, node.setVisible);
    cc.defineGetterSetter(node, "parent", node.getParent, node.setParent);
    cc.defineGetterSetter(node, "opacity", node.getOpacity, node.setOpacity);
};
cc.DOM.methods = {
    setPosition:function (x, y) {
        if (y === undefined) {
            this._position.x = x.x;
            this._position.y = x.y;
        } else {
            this._position.x = x;
            this._position.y = y;
        }
        this.setNodeDirty();
        this.dom.translates(this._position.x, -this._position.y);
    },
    setPositionY:function (y) {
        this._position.y = y;
        this.setNodeDirty();
        this.dom.translates(this._position.x, -this._position.y);
    },
    setPositionX:function (x) {
        this._position.x = x;
        this.setNodeDirty();
        this.dom.translates(this._position.x, -this._position.y);
    },
    setScale:function (scale, scaleY) {
        this._scaleX = scale;
        this._scaleY = scaleY || scale;
        this.setNodeDirty();
        this.dom.resize(this._scaleX, this._scaleY);
    },
    setScaleX:function (x) {
        this._scaleX = x;
        this.setNodeDirty();
        this.dom.resize(this._scaleX, this._scaleY);
    },
    setScaleY:function (y) {
        this._scaleY = y;
        this.setNodeDirty();
        this.dom.resize(this._scaleX, this._scaleY);
    },
    setAnchorPoint:function (point, y) {
        var cmd = this._renderCmd;
        var locAnchorPoint = this._anchorPoint;
        if (y === undefined) {
            locAnchorPoint.x = point.x;
            locAnchorPoint.y = point.y;
        } else {
            locAnchorPoint.x = point;
            locAnchorPoint.y = y;
        }
        var locAPP = cmd._anchorPointInPoints, locSize = this._contentSize;
        locAPP.x = locSize.width * locAnchorPoint.x;
        locAPP.y = locSize.height * locAnchorPoint.y;
        this.dom.style[cc.$.pfx + 'TransformOrigin'] = '' + locAPP.x + 'px ' + -locAPP.y + 'px';
        if (this.ignoreAnchor) {
            this.dom.style.marginLeft = 0;
            this.dom.style.marginBottom = 0;
        } else {
            this.dom.style.marginLeft = (this.isToggler) ? 0 : -locAPP.x + 'px';
            this.dom.style.marginBottom = -locAPP.y + 'px';
        }
        this.setNodeDirty();
    },
    _setAnchorX:function (x) {
        var locAnchorPoint = this._anchorPoint;
        var cmd = this._renderCmd;
        if (x === locAnchorPoint.x)
            return;
        locAnchorPoint.x = x;
        var locAPP = cmd._anchorPointInPoints, locSize = this._contentSize;
        locAPP.x = locSize.width * locAnchorPoint.x;
        this.dom.style[cc.$.pfx + 'TransformOrigin'] = '' + locAPP.x + 'px ' + -locAPP.y + 'px';
        if (this.ignoreAnchor) {
            this.dom.style.marginLeft = 0;
            this.dom.style.marginBottom = 0;
        } else {
            this.dom.style.marginLeft = (this.isToggler) ? 0 : -locAPP.x + 'px';
        }
        this.setNodeDirty();
    },
    _setAnchorY:function (y) {
        var locAnchorPoint = this._anchorPoint;
        var cmd = this._renderCmd;
        if (y === locAnchorPoint.y)
            return;
        locAnchorPoint.y = y;
        var locAPP = cmd._anchorPointInPoints, locSize = this._contentSize;
        locAPP.y = locSize.height * locAnchorPoint.y;
        this.dom.style[cc.$.pfx + 'TransformOrigin'] = '' + locAPP.x + 'px ' + -locAPP.y + 'px';
        if (this.ignoreAnchor) {
            this.dom.style.marginLeft = 0;
            this.dom.style.marginBottom = 0;
        } else {
            this.dom.style.marginBottom = -locAPP.y + 'px';
        }
        this.setNodeDirty();
    },
    setContentSize:function (size, height) {
        var cmd = this._renderCmd;
        var locContentSize = this._contentSize;
        if (height === undefined) {
            locContentSize.width = size.width;
            locContentSize.height = size.height;
        } else {
            locContentSize.width = size;
            locContentSize.height = height;
        }
        var locAPP = cmd._anchorPointInPoints, locAnchorPoint = this._anchorPoint;
        locAPP.x = locContentSize.width * locAnchorPoint.x;
        locAPP.y = locContentSize.height * locAnchorPoint.y;
        this.dom.width = locContentSize.width;
        this.dom.height = locContentSize.height;
        this.setAnchorPoint(this.getAnchorPoint());
        if (this.canvas) {
            this.canvas.width = locContentSize.width;
            this.canvas.height = locContentSize.height;
        }
        this.setNodeDirty();
        this.redraw();
    },
    _setWidth:function (width) {
        var locContentSize = this._contentSize;
        var cmd = this._renderCmd;
        if (width === locContentSize.width)
            return;
        locContentSize.width = width;
        var locAPP = cmd._anchorPointInPoints, locAnchorPoint = this._anchorPoint;
        locAPP.x = locContentSize.width * locAnchorPoint.x;
        this.dom.width = locContentSize.width;
        this.anchorX = locAnchorPoint.x;
        if (this.canvas) {
            this.canvas.width = locContentSize.width;
        }
        this.setNodeDirty();
        this.redraw();
    },
    _setHeight:function (height) {
        var locContentSize = this._contentSize;
        var cmd = this._renderCmd;
        if (height === locContentSize.height)
            return;
        locContentSize.height = height;
        var locAPP = cmd._anchorPointInPoints, locAnchorPoint = this._anchorPoint;
        locAPP.y = locContentSize.height * locAnchorPoint.y;
        this.dom.height = locContentSize.height;
        this.anchorY = locAnchorPoint.y;
        if (this.canvas) {
            this.canvas.height = locContentSize.height;
        }
        this.setNodeDirty();
        this.redraw();
    },
    setRotation:function (newRotation) {
        if (this._rotation === newRotation)
            return;
        this._rotationX = this._rotationY = newRotation;
        this.setNodeDirty();
        this.dom.rotate(newRotation);
    },
    setSkewX:function (x) {
        this._skewX = x;
        this.setNodeDirty();
        this.dom.setSkew(this._skewX, this._skewY);
    },
    setSkewY:function (y) {
        this._skewY = y;
        this.setNodeDirty();
        this.dom.setSkew(this._skewX, this._skewY);
    },
    setVisible:function (x) {
        this._visible = x;
        this.setNodeDirty();
        if (this.dom)
            this.dom.style.display = (x) ? 'block' : 'none';
    },
    _setLocalZOrder:function (z) {
        this._localZOrder = z;
        this.setNodeDirty();
        if (this.dom)
            this.dom.zIndex = z;
    },
    setParent:function (p) {
        this._parent = p;
        if (p !== null) {
            p.setAnchorPoint(p.getAnchorPoint());
            this.setNodeDirty();
            cc.DOM.parentDOM(this);
        }
    },
    resume:function () {
        this.getScheduler().resumeTarget(this);
        this.getActionManager().resumeTarget(this);
        cc.eventManager.resumeTarget(this);
        if (this.dom && !this.dom.parentNode) {
            if (!this.getParent()) {
                if(this.dom.id === ""){
                    cc.DOM._createEGLViewDiv(this);
                }else{
                    this.dom.appendTo(cc.container);
                }
            } else {
                cc.DOM.parentDOM(this);
            }
        }
        if (this.dom)
            this.dom.style.visibility = "visible";
    },
    pause:function () {
        this.getScheduler().pauseTarget(this);
        this.getActionManager().pauseTarget(this);
        cc.eventManager.pauseTarget(this);
        if (this.dom) {
            this.dom.style.visibility = 'hidden';
        }
    },
    cleanup:function () {
        this.stopAllActions();
        this.unscheduleAllCallbacks();
        cc.eventManager.removeListeners(this);
        this._arrayMakeObjectsPerformSelector(this._children, cc.Node._stateCallbackType.cleanup);
        if (this.dom) {
            this.dom.remove();
        }
    },
    setOpacity:function (o) {
        this._opacity = o;
        this.dom.style.opacity = o / 255;
    },
    redraw:function () {
        if (this.isSprite) {
            var tmp = this._children;
            this._children = [];
            cc.Sprite.prototype.visit.call(this, this.ctx);
            this._children = tmp;
        }
        else {
            cc.Sprite.prototype.visit.call(this, this.ctx);
        }
    }
};
cc.DOM._resetEGLViewDiv = function(){
    var div = cc.$("#EGLViewDiv");
    if(div){
        var view = cc.view;
        var designSize = view.getDesignResolutionSize();
        var viewPortRect = view.getViewPortRect();
        var screenSize = view.getFrameSize();
        var pixelRatio = view.getDevicePixelRatio();
        var designSizeWidth = designSize.width, designSizeHeight = designSize.height;
        var paddingLeft = parseInt(cc.container.style.paddingLeft),
            paddingBottom = parseInt(cc.container.style.paddingBottom);
        if((designSize.width === 0) && (designSize.height === 0)){
            designSizeWidth = screenSize.width;
            designSizeHeight = screenSize.height;
        }
        var viewPortWidth = viewPortRect.width/pixelRatio;
        if((viewPortRect.width === 0) && (viewPortRect.height === 0)){
            viewPortWidth = screenSize.width;
        }
        div.style.position = 'absolute';
        div.style.width = designSizeWidth + "px";
        div.style.maxHeight = designSizeHeight + "px";
        div.style.margin = 0;
        div.resize(view.getScaleX()/pixelRatio, view.getScaleY()/pixelRatio);
        div.translates(paddingLeft, -paddingBottom);
        if (view.getResolutionPolicy() === view._rpNoBorder) {
            div.style.left = (view.getFrameSize().width - designSizeWidth)/2 + "px";
            div.style.bottom = (view.getFrameSize().height - designSizeHeight*view.getScaleY()/pixelRatio)/2 + "px";
        }
        else {
            div.style.left = (designSizeWidth*view.getScaleX()/pixelRatio - designSizeWidth) / 2 + "px";
            div.style.bottom = "0px";
        }
    }
};
cc.DOM.parentDOM = function (x) {
    var p = x.getParent();
    if (!p || !x.dom)
        return false;
    if (!p.dom) {
        cc.DOM.placeHolder(p);
        p.setParent = cc.DOM.methods.setParent;
    }
    x.dom.appendTo(p.dom);
    p.setAnchorPoint(p.getAnchorPoint());
    if (p.getParent()) {
        cc.DOM.parentDOM(p);
    } else {
        if (p.isRunning()) {
            var eglViewDiv = cc.$("#EGLViewDiv");
            if (eglViewDiv) {
                p.dom.appendTo(eglViewDiv);
            } else {
                cc.DOM._createEGLViewDiv(p);
            }
        }
    }
    return true;
};
cc.DOM._createEGLViewDiv = function(p){
    var div = cc.$("#EGLViewDiv");
    if(!div){
        div = cc.$new("div");
        div.id = "EGLViewDiv";
    }
    var view = cc.view;
    var designSize = view.getDesignResolutionSize();
    var viewPortRect = view.getViewPortRect();
    var screenSize = view.getFrameSize();
    var pixelRatio = view.getDevicePixelRatio();
    var designSizeWidth = designSize.width, designSizeHeight = designSize.height;
    var paddingLeft = parseInt(cc.container.style.paddingLeft),
        paddingBottom = parseInt(cc.container.style.paddingBottom);
    if ((designSize.width === 0) && (designSize.height === 0)) {
        designSizeWidth = screenSize.width;
        designSizeHeight = screenSize.height;
    }
    var viewPortWidth = viewPortRect.width/pixelRatio;
    if ((viewPortRect.width === 0) && (viewPortRect.height === 0)) {
        viewPortWidth = screenSize.width;
    }
    div.style.position = 'absolute';
    div.style.width = designSizeWidth + "px";
    div.style.maxHeight = designSizeHeight + "px";
    div.style.margin = 0;
    div.resize(view.getScaleX()/pixelRatio, view.getScaleY()/pixelRatio);
    div.translates(paddingLeft, -paddingBottom);
    if (view.getResolutionPolicy() === view._rpNoBorder) {
        div.style.left = (screenSize.width - designSizeWidth)/2 + "px";
        div.style.bottom = (screenSize.height - designSizeHeight*view.getScaleY()/pixelRatio)/2 + "px";
    }
    else {
        div.style.left = (designSizeWidth*view.getScaleX()/pixelRatio - designSizeWidth) / 2 + "px";
        div.style.bottom = "0px";
    }
    p.dom.appendTo(div);
    div.appendTo(cc.container);
};
cc.DOM.setTransform = function (x) {
    if (x.ctx) {
        x.ctx.translate(x.getAnchorPointInPoints().x, x.getAnchorPointInPoints().y);
        if (x.isSprite) {
            var tmp = x._children;
            x._children = [];
            cc.Sprite.prototype.visit.call(x);
            x._children = tmp;
        }
        else {
            cc.Sprite.prototype.visit.call(x);
        }
    }
    if (x.dom) {
        x.dom.position.x = x.getPositionX();
        x.dom.position.y = -x.getPositionY();
        x.dom.rotation = x.getRotation();
        x.dom.scale = {x:x.getScaleX(), y:x.getScaleY()};
        x.dom.skew = {x:x.getSkewX(), y:x.getSkewY()};
        if (x.setAnchorPoint)
            x.setAnchorPoint(x.getAnchorPoint());
        x.dom.transforms();
    }
};
cc.DOM.forSprite = function (x) {
    x.dom = cc.$new('div');
    x.canvas = cc.$new('canvas');
    var locContentSize = x.getContentSize();
    x.canvas.width = locContentSize.width;
    x.canvas.height = locContentSize.height;
    x.dom.style.position = 'absolute';
    x.dom.style.bottom = 0;
    x.ctx = x.canvas.getContext('2d');
    x.dom.appendChild(x.canvas);
    if (x.getParent()) {
        cc.DOM.parentDOM(x);
    }
    x.isSprite = true;
};
cc.DOM.placeHolder = function (x) {
    x.dom = cc.$new('div');
    x.placeholder = true;
    x.dom.style.position = 'absolute';
    x.dom.style.bottom = 0;
    x.dom.style.width = (x.getContentSize().width || cc.director.getWinSize().width) + "px";
    x.dom.style.maxHeight = (x.getContentSize().height || cc.director.getWinSize().height) + "px";
    x.dom.style.margin = 0;
    cc.DOM.setTransform(x);
    x.dom.transforms();
    cc.DOM._addMethods(x);
};
cc.DOM.convert = function (nodeObject) {
    if (arguments.length > 1) {
        cc.DOM.convert(arguments);
        return;
    } else if (arguments.length === 1 && !arguments[0].length) {
        cc.DOM.convert([arguments[0]]);
        return;
    }
    var args = arguments[0];
    for (var i = 0; i < args.length; i++) {
        if (args[i] instanceof cc.Sprite) {
            if (!args[i].dom)
                cc.DOM.forSprite(args[i]);
        } else {
            cc.log('DOM converter only supports sprite and menuitems yet');
        }
        cc.DOM._addMethods(args[i]);
        args[i].visit = function () {
        };
        args[i].transform = function () {
        };
        cc.DOM.setTransform(args[i]);
        args[i].setVisible(args[i].isVisible());
    }
};
cc.KEYBOARD_RETURNTYPE_DEFAULT = 0;
cc.KEYBOARD_RETURNTYPE_DONE = 1;
cc.KEYBOARD_RETURNTYPE_SEND = 2;
cc.KEYBOARD_RETURNTYPE_SEARCH = 3;
cc.KEYBOARD_RETURNTYPE_GO = 4;
cc.EDITBOX_INPUT_MODE_ANY = 0;
cc.EDITBOX_INPUT_MODE_EMAILADDR = 1;
cc.EDITBOX_INPUT_MODE_NUMERIC = 2;
cc.EDITBOX_INPUT_MODE_PHONENUMBER = 3;
cc.EDITBOX_INPUT_MODE_URL = 4;
cc.EDITBOX_INPUT_MODE_DECIMAL = 5;
cc.EDITBOX_INPUT_MODE_SINGLELINE = 6;
cc.EDITBOX_INPUT_FLAG_PASSWORD = 0;
cc.EDITBOX_INPUT_FLAG_SENSITIVE = 1;
cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD = 2;
cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE = 3;
cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS = 4;
cc.EditBoxDelegate = cc.Class.extend({
    editBoxEditingDidBegin: function (sender) {
    },
    editBoxEditingDidEnd: function (sender) {
    },
    editBoxTextChanged: function (sender, text) {
    },
    editBoxReturn: function (sender) {
    }
});
cc.EditBox = cc.ControlButton.extend({
    _domInputSprite: null,
    _delegate: null,
    _editBoxInputMode: cc.EDITBOX_INPUT_MODE_ANY,
    _editBoxInputFlag: cc.EDITBOX_INPUT_FLAG_SENSITIVE,
    _keyboardReturnType: cc.KEYBOARD_RETURNTYPE_DEFAULT,
    _text: "",
    _placeholderText: "",
    _textColor: null,
    _placeholderColor: null,
    _maxLength: 50,
    _adjustHeight: 18,
    _edTxt: null,
    _edFontSize: 14,
    _edFontName: "Arial",
    _placeholderFontName: "",
    _placeholderFontSize: 14,
    _tooltip: false,
    _className: "EditBox",
    _onCanvasClick : null,
    _inputEvent : null,
    _keyPressEvent : null,
    _focusEvent : null,
    _blurEvent : null,
    ctor: function (size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) {
        cc.ControlButton.prototype.ctor.call(this);
        this._textColor = cc.color.WHITE;
        this._placeholderColor = cc.color.GRAY;
        this.setContentSize(size);
        var tmpDOMSprite = this._domInputSprite = new cc.Sprite();
        tmpDOMSprite.draw = function () {};
        this.addChild(tmpDOMSprite);
        var tmpEdTxt = this._edTxt = document.createElement("input");
        tmpEdTxt.type = "text";
        tmpEdTxt.style.fontSize = this._edFontSize + "px";
        tmpEdTxt.style.color = "#000000";
        tmpEdTxt.style.border = 0;
        tmpEdTxt.style.background = "transparent";
        tmpEdTxt.style.width = "100%";
        tmpEdTxt.style.height = "100%";
        tmpEdTxt.style.active = 0;
        tmpEdTxt.style.outline = "medium";
        tmpEdTxt.style.padding = "0";
        var onCanvasClick = function() { this._edTxt.blur();};
        this._onCanvasClick = onCanvasClick.bind(this);
        var inputEvent = function () {
            if (this._delegate && this._delegate.editBoxTextChanged)
                this._delegate.editBoxTextChanged(this, this._edTxt.value);
        };
        this._inputEvent = inputEvent.bind(this);
        var keypressEvent = function ( e ) {
            if (e.keyCode === cc.KEY.enter) {
                e.stopPropagation();
                e.preventDefault();
                if (this._delegate && this._delegate.editBoxReturn)
                    this._delegate.editBoxReturn(this);
                cc._canvas.focus();
            }
        };
        this._keyPressEvent = keypressEvent.bind(this);
        var focusEvent = function () {
            if (this._edTxt.value === this._placeholderText) {
                this._edTxt.value = "";
                this._edTxt.style.fontSize = this._edFontSize + "px";
                this._edTxt.style.color = cc.colorToHex(this._textColor);
                if (this._editBoxInputFlag === cc.EDITBOX_INPUT_FLAG_PASSWORD)
                    this._edTxt.type = "password";
                else
                    this._edTxt.type = "text";
            }
            if (this._delegate && this._delegate.editBoxEditingDidBegin)
                this._delegate.editBoxEditingDidBegin(this);
            cc._canvas.addEventListener("click", this._onCanvasClick);
        };
        this._focusEvent = focusEvent.bind(this);
        var blurEvent = function () {
            if (this._edTxt.value === "") {
                this._edTxt.value = this._placeholderText;
                this._edTxt.style.fontSize = this._placeholderFontSize + "px";
                this._edTxt.style.color = cc.colorToHex(this._placeholderColor);
                this._edTxt.type = "text";
            }
            if (this._delegate && this._delegate.editBoxEditingDidEnd)
                this._delegate.editBoxEditingDidEnd(this);
            cc._canvas.removeEventListener('click', this._onCanvasClick);
        };
        this._blurEvent = blurEvent.bind(this);
        tmpEdTxt.addEventListener("input", this._inputEvent);
        tmpEdTxt.addEventListener("keypress", this._keyPressEvent);
        tmpEdTxt.addEventListener("focus", this._focusEvent);
        tmpEdTxt.addEventListener("blur", this._blurEvent);
        cc.DOM.convert(tmpDOMSprite);
        tmpDOMSprite.dom.appendChild(tmpEdTxt);
        tmpDOMSprite.dom.showTooltipDiv = false;
        tmpDOMSprite.dom.style.width = (size.width - 6) + "px";
        tmpDOMSprite.dom.style.height = (size.height - 6) + "px";
        tmpDOMSprite.canvas.remove();
        if (this.initWithSizeAndBackgroundSprite(size, normal9SpriteBg)) {
            if (press9SpriteBg)
                this.setBackgroundSpriteForState(press9SpriteBg, cc.CONTROL_STATE_HIGHLIGHTED);
            if (disabled9SpriteBg)
                this.setBackgroundSpriteForState(disabled9SpriteBg, cc.CONTROL_STATE_DISABLED);
        }
    },
    setFont: function (fontName, fontSize) {
        this._edFontSize = fontSize;
        this._edFontName = fontName;
        this._setFontToEditBox();
    },
    _setFont: function (fontStyle) {
        var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
        if (res) {
            this._edFontSize = parseInt(res[1]);
            this._edFontName = res[2];
            this._setFontToEditBox();
        }
    },
    setFontName: function (fontName) {
        this._edFontName = fontName;
        this._setFontToEditBox();
    },
    setFontSize: function (fontSize) {
        this._edFontSize = fontSize;
        this._setFontToEditBox();
    },
    _setFontToEditBox: function () {
        if (this._edTxt.value !== this._placeholderText) {
            this._edTxt.style.fontFamily = this._edFontName;
            this._edTxt.style.fontSize = this._edFontSize + "px";
            if (this._editBoxInputFlag === cc.EDITBOX_INPUT_FLAG_PASSWORD)
                this._edTxt.type = "password";
            else
                this._edTxt.type = "text";
        }
    },
    setText: function (text) {
        cc.log("Please use the setString");
        this.setString(text);
    },
    setString: function (text) {
        if (text != null) {
            if (text === "") {
                this._edTxt.value = this._placeholderText;
                this._edTxt.style.color = cc.colorToHex(this._placeholderColor);
                this._edTxt.type = "text";
            } else {
                this._edTxt.value = text;
                this._edTxt.style.color = cc.colorToHex(this._textColor);
                if (this._editBoxInputFlag === cc.EDITBOX_INPUT_FLAG_PASSWORD)
                    this._edTxt.type = "password";
                else
                    this._edTxt.type = "text";
            }
        }
    },
    setFontColor: function (color) {
        this._textColor = color;
        if (this._edTxt.value !== this._placeholderText) {
            this._edTxt.style.color = cc.colorToHex(color);
        }
    },
    setMaxLength: function (maxLength) {
        if (!isNaN(maxLength) && maxLength > 0) {
            this._maxLength = maxLength;
            this._edTxt.maxLength = maxLength;
        }
    },
    getMaxLength: function () {
        return this._maxLength;
    },
    setPlaceHolder: function (text) {
        if (text != null) {
            var oldPlaceholderText = this._placeholderText;
            this._placeholderText = text;
            if (this._edTxt.value === oldPlaceholderText) {
                this._edTxt.value = text;
                this._edTxt.style.color = cc.colorToHex(this._placeholderColor);
                this._setPlaceholderFontToEditText();
            }
        }
    },
    setPlaceholderFont: function (fontName, fontSize) {
        this._placeholderFontName = fontName;
        this._placeholderFontSize = fontSize;
        this._setPlaceholderFontToEditText();
    },
    _setPlaceholderFont: function (fontStyle) {
        var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
        if (res) {
            this._placeholderFontName = res[2];
            this._placeholderFontSize = parseInt(res[1]);
            this._setPlaceholderFontToEditText();
        }
    },
    setPlaceholderFontName: function (fontName) {
        this._placeholderFontName = fontName;
        this._setPlaceholderFontToEditText();
    },
    setPlaceholderFontSize: function (fontSize) {
        this._placeholderFontSize = fontSize;
        this._setPlaceholderFontToEditText();
    },
    _setPlaceholderFontToEditText: function () {
        if (this._edTxt.value === this._placeholderText) {
            this._edTxt.style.fontFamily = this._placeholderFontName;
            this._edTxt.style.fontSize = this._placeholderFontSize + "px";
            this._edTxt.type = "text";
        }
    },
    setPlaceholderFontColor: function (color) {
        this._placeholderColor = color;
        if (this._edTxt.value === this._placeholderText) {
            this._edTxt.style.color = cc.colorToHex(color);
        }
    },
    setInputFlag: function (inputFlag) {
        this._editBoxInputFlag = inputFlag;
        if ((this._edTxt.value !== this._placeholderText) && (inputFlag === cc.EDITBOX_INPUT_FLAG_PASSWORD))
            this._edTxt.type = "password";
        else
            this._edTxt.type = "text";
    },
    getText: function () {
        cc.log("Please use the getString");
        return this._edTxt.value;
    },
    getString: function () {
        if(this._edTxt.value === this._placeholderText)
            return "";
        return this._edTxt.value;
    },
    initWithSizeAndBackgroundSprite: function (size, normal9SpriteBg) {
        if (this.initWithBackgroundSprite(normal9SpriteBg)) {
            this._domInputSprite.x = 3;
            this._domInputSprite.y = 3;
            this.setZoomOnTouchDown(false);
            this.setPreferredSize(size);
            this.x = 0;
            this.y = 0;
            this._addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE);
            return true;
        }
        return false;
    },
    setDelegate: function (delegate) {
        this._delegate = delegate;
    },
    getPlaceHolder: function () {
        return this._placeholderText;
    },
    setInputMode: function (inputMode) {
        this._editBoxInputMode = inputMode;
    },
    setReturnType: function (returnType) {
        this._keyboardReturnType = returnType;
    },
    keyboardWillShow: function (info) {
        var rectTracked = cc.EditBox.getRect(this);
        rectTracked.y -= 4;
        if (!rectTracked.intersectsRect(info.end)) {
            cc.log("needn't to adjust view layout.");
            return;
        }
        this._adjustHeight = info.end.getMaxY() - rectTracked.getMinY();
    },
    keyboardDidShow: function (info) {
    },
    keyboardWillHide: function (info) {
    },
    keyboardDidHide: function (info) {
    },
    touchDownAction: function (sender, controlEvent) {
    },
    initWithBackgroundColor: function (size, bgColor) {
        this._edWidth = size.width;
        this.dom.style.width = this._edWidth.toString() + "px";
        this._edHeight = size.height;
        this.dom.style.height = this._edHeight.toString() + "px";
        this.dom.style.backgroundColor = cc.colorToHex(bgColor);
    },
    cleanup : function () {
        this._edTxt.removeEventListener("input", this._inputEvent);
        this._edTxt.removeEventListener("keypress", this._keyPressEvent);
        this._edTxt.removeEventListener("focus", this._focusEvent);
        this._edTxt.removeEventListener("blur", this._blurEvent);
        cc._canvas.removeEventListener('click', this._onCanvasClick);
        this._super();
    }
});
var _p = cc.EditBox.prototype;
_p.font;
cc.defineGetterSetter(_p, "font", null, _p._setFont);
_p.fontName;
cc.defineGetterSetter(_p, "fontName", null, _p.setFontName);
_p.fontSize;
cc.defineGetterSetter(_p, "fontSize", null, _p.setFontSize);
_p.fontColor;
cc.defineGetterSetter(_p, "fontColor", null, _p.setFontColor);
_p.string;
cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
_p.maxLength;
cc.defineGetterSetter(_p, "maxLength", _p.getMaxLength, _p.setMaxLength);
_p.placeHolder;
cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
_p.placeHolderFont;
cc.defineGetterSetter(_p, "placeHolderFont", null, _p._setPlaceholderFont);
_p.placeHolderFontName;
cc.defineGetterSetter(_p, "placeHolderFontName", null, _p.setPlaceholderFontName);
_p.placeHolderFontSize;
cc.defineGetterSetter(_p, "placeHolderFontSize", null, _p.setPlaceholderFontSize);
_p.placeHolderFontColor;
cc.defineGetterSetter(_p, "placeHolderFontColor", null, _p.setPlaceholderFontColor);
_p.inputFlag;
cc.defineGetterSetter(_p, "inputFlag", null, _p.setInputFlag);
_p.delegate;
cc.defineGetterSetter(_p, "delegate", null, _p.setDelegate);
_p.inputMode;
cc.defineGetterSetter(_p, "inputMode", null, _p.setInputMode);
_p.returnType;
cc.defineGetterSetter(_p, "returnType", null, _p.setReturnType);
_p = null;
cc.EditBox.getRect = function (node) {
    var contentSize = node.getContentSize();
    var rect = cc.rect(0, 0, contentSize.width, contentSize.height);
    return cc.rectApplyAffineTransform(rect, node.getNodeToWorldTransform());
};
cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) {
    return new cc.EditBox(size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg);
};
cc.ProtectedNode = cc.Node.extend({
    _protectedChildren: null,
    _reorderProtectedChildDirty: false,
    _insertProtectedChild: function(child, z){
        this._reorderProtectedChildDirty = true;
        this._protectedChildren.push(child);
        child._setLocalZOrder(z);
    },
    ctor: function(){
        cc.Node.prototype.ctor.call(this);
        this._protectedChildren = [];
    },
    addProtectedChild: function(child, localZOrder, tag){
         cc.assert(child != null, "child must be non-nil");
         cc.assert(!child.parent, "child already added. It can't be added again");
        localZOrder = localZOrder || child.getLocalZOrder();
        if(tag)
            child.setTag(tag);
        this._insertProtectedChild(child, localZOrder);
        child.setParent(this);
        child.setOrderOfArrival(cc.s_globalOrderOfArrival);
        if(this._running){
            child.onEnter();
            if(this._isTransitionFinished)
                child.onEnterTransitionDidFinish();
        }
        if(this._cascadeColorEnabled)
            this._renderCmd.setCascadeColorEnabledDirty();
        if (this._cascadeOpacityEnabled)
            this._renderCmd.setCascadeOpacityEnabledDirty();
    },
    getProtectedChildByTag: function(tag){
        cc.assert(tag !== cc.NODE_TAG_INVALID, "Invalid tag");
        var locChildren = this._protectedChildren;
        for(var i = 0, len = locChildren.length; i < len; i++)
            if(locChildren.getTag() === tag)
                return locChildren[i];
        return null;
    },
    removeProtectedChild: function(child,  cleanup){
        if(cleanup == null)
            cleanup = true;
         var locChildren = this._protectedChildren;
        if(locChildren.length === 0)
            return;
        var idx = locChildren.indexOf(child);
        if(idx > -1){
             if(this._running){
                 child.onExitTransitionDidStart();
                 child.onExit();
             }
            if (cleanup)
                child.cleanup();
            child.setParent(null);
            locChildren.splice(idx, 1);
        }
    },
    removeProtectedChildByTag: function(tag, cleanup){
        cc.assert( tag !== cc.NODE_TAG_INVALID, "Invalid tag");
        if(cleanup == null)
            cleanup = true;
        var child = this.getProtectedChildByTag(tag);
        if (child == null)
            cc.log("cocos2d: removeChildByTag(tag = %d): child not found!", tag);
        else
            this.removeProtectedChild(child, cleanup);
    },
    removeAllProtectedChildren: function(){
        this.removeAllProtectedChildrenWithCleanup(true);
    },
    removeAllProtectedChildrenWithCleanup: function(cleanup){
        if(cleanup == null)
            cleanup = true;
        var locChildren = this._protectedChildren;
        for (var i = 0, len = locChildren.length; i< len; i++) {
            var child = locChildren[i];
            if(this._running){
                child.onExitTransitionDidStart();
                child.onExit();
            }
            if (cleanup)
                child.cleanup();
            child.setParent(null);
        }
        locChildren.length = 0;
    },
    reorderProtectedChild: function(child, localZOrder){
        cc.assert( child != null, "Child must be non-nil");
        this._reorderProtectedChildDirty = true;
        child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
        child._setLocalZOrder(localZOrder);
    },
    sortAllProtectedChildren: function(){
        if (this._reorderProtectedChildDirty) {
            var _children = this._protectedChildren;
            var len = _children.length, i, j, tmp;
            for(i=1; i<len; i++){
                tmp = _children[i];
                j = i - 1;
                while(j >= 0){
                    if(tmp._localZOrder < _children[j]._localZOrder){
                        _children[j+1] = _children[j];
                    }else if(tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder){
                        _children[j+1] = _children[j];
                    }else
                        break;
                    j--;
                }
                _children[j+1] = tmp;
            }
            this._reorderProtectedChildDirty = false;
        }
    },
    _changePosition: function(){},
    cleanup: function(){
        cc.Node.prototype.cleanup.call(this);
        var locChildren = this._protectedChildren;
        for(var i = 0 , len = locChildren.length; i  < len; i++)
            locChildren[i].cleanup();
    },
    onEnter: function(){
        cc.Node.prototype.onEnter.call(this);
        var locChildren = this._protectedChildren;
        for(var i = 0, len = locChildren.length;i< len;i++)
            locChildren[i].onEnter();
    },
    onEnterTransitionDidFinish: function(){
        cc.Node.prototype.onEnterTransitionDidFinish.call(this);
        var locChildren = this._protectedChildren;
        for(var i = 0, len = locChildren.length;i< len;i++)
            locChildren[i].onEnterTransitionDidFinish();
    },
    onExit:function(){
        cc.Node.prototype.onExit.call(this);
        var locChildren = this._protectedChildren;
        for(var i = 0, len = locChildren.length;i< len;i++)
            locChildren[i].onExit();
    },
    onExitTransitionDidStart: function(){
        cc.Node.prototype.onExitTransitionDidStart.call(this);
        var locChildren = this._protectedChildren;
        for(var i = 0, len = locChildren.length;i< len;i++)
            locChildren[i].onExitTransitionDidStart();
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.ProtectedNode.CanvasRenderCmd(this);
        else
            return new cc.ProtectedNode.WebGLRenderCmd(this);
    }
});
cc.ProtectedNode.create = function(){
    return new cc.ProtectedNode();
};
(function(){
    cc.ProtectedNode.RenderCmd = {
        _updateDisplayColor: function (parentColor) {
            var node = this._node;
            var locDispColor = this._displayedColor, locRealColor = node._realColor;
            var i, len, selChildren, item;
            if (this._cascadeColorEnabledDirty && !node._cascadeColorEnabled) {
                locDispColor.r = locRealColor.r;
                locDispColor.g = locRealColor.g;
                locDispColor.b = locRealColor.b;
                var whiteColor = new cc.Color(255, 255, 255, 255);
                selChildren = node._children;
                for (i = 0, len = selChildren.length; i < len; i++) {
                    item = selChildren[i];
                    if (item && item._renderCmd)
                        item._renderCmd._updateDisplayColor(whiteColor);
                }
                this._cascadeColorEnabledDirty = false;
            } else {
                if (parentColor === undefined) {
                    var locParent = node._parent;
                    if (locParent && locParent._cascadeColorEnabled)
                        parentColor = locParent.getDisplayedColor();
                    else
                        parentColor = cc.color.WHITE;
                }
                locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
                locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
                locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
                if (node._cascadeColorEnabled) {
                    selChildren = node._children;
                    for (i = 0, len = selChildren.length; i < len; i++) {
                        item = selChildren[i];
                        if (item && item._renderCmd){
                            item._renderCmd._updateDisplayColor(locDispColor);
                            item._renderCmd._updateColor();
                        }
                    }
                }
                selChildren = node._protectedChildren;
                for(i = 0, len = selChildren.length;i < len; i++){
                    item = selChildren[i];
                    if(item && item._renderCmd){
                        item._renderCmd._updateDisplayColor(locDispColor);
                        item._renderCmd._updateColor();
                    }
                }
            }
            this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.colorDirty ^ this._dirtyFlag;
        },
        _updateDisplayOpacity: function (parentOpacity) {
            var node = this._node;
            var i, len, selChildren, item;
            if (this._cascadeOpacityEnabledDirty && !node._cascadeOpacityEnabled) {
                this._displayedOpacity = node._realOpacity;
                selChildren = node._children;
                for (i = 0, len = selChildren.length; i < len; i++) {
                    item = selChildren[i];
                    if (item && item._renderCmd)
                        item._renderCmd._updateDisplayOpacity(255);
                }
                this._cascadeOpacityEnabledDirty = false;
            } else {
                if (parentOpacity === undefined) {
                    var locParent = node._parent;
                    parentOpacity = 255;
                    if (locParent && locParent._cascadeOpacityEnabled)
                        parentOpacity = locParent.getDisplayedOpacity();
                }
                this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
                if (node._cascadeOpacityEnabled) {
                    selChildren = node._children;
                    for (i = 0, len = selChildren.length; i < len; i++) {
                        item = selChildren[i];
                        if (item && item._renderCmd){
                            item._renderCmd._updateDisplayOpacity(this._displayedOpacity);
                            item._renderCmd._updateColor();
                        }
                    }
                }
                selChildren = node._protectedChildren;
                for(i = 0, len = selChildren.length;i < len; i++){
                    item = selChildren[i];
                    if(item && item._renderCmd){
                        item._renderCmd._updateDisplayOpacity(this._displayedOpacity);
                        item._renderCmd._updateColor();
                    }
                }
            }
            this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.opacityDirty ^ this._dirtyFlag;
        },
        _changeProtectedChild: function (child) {
            var cmd = child._renderCmd,
                dirty = cmd._dirtyFlag,
                flags = cc.Node._dirtyFlags;
            if (this._dirtyFlag & flags.colorDirty)
                dirty |= flags.colorDirty;
            if (this._dirtyFlag & flags.opacityDirty)
                dirty |= flags.opacityDirty;
            var colorDirty = dirty & flags.colorDirty,
                opacityDirty = dirty & flags.opacityDirty;
            if (colorDirty)
                cmd._updateDisplayColor(this._displayedColor);
            if (opacityDirty)
                cmd._updateDisplayOpacity(this._displayedOpacity);
            if (colorDirty || opacityDirty)
                cmd._updateColor();
        }
    };
    cc.ProtectedNode.CanvasRenderCmd = function (renderable) {
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._cachedParent = null;
        this._cacheDirty = false;
    };
    var proto = cc.ProtectedNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    cc.inject(cc.ProtectedNode.RenderCmd, proto);
    proto.constructor = cc.ProtectedNode.CanvasRenderCmd;
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        var i, j;
        var children = node._children, child;
        var locChildren = node._children, locProtectedChildren = node._protectedChildren;
        var childLen = locChildren.length, pLen = locProtectedChildren.length;
        this._syncStatus(parentCmd);
        node.sortAllChildren();
        node.sortAllProtectedChildren();
        var pChild;
        for (i = 0; i < childLen; i++) {
            child = children[i];
            if (child._localZOrder < 0)
                child.visit(this);
            else
                break;
        }
        for (j = 0; j < pLen; j++) {
            pChild = locProtectedChildren[j];
            if (pChild && pChild._localZOrder < 0){
                this._changeProtectedChild(pChild);
                pChild.visit(this);
            }
            else
                break;
        }
        cc.renderer.pushRenderCommand(this);
        for (; i < childLen; i++)
            children[i] && children[i].visit(this);
        for (; j < pLen; j++){
            pChild = locProtectedChildren[j];
            if(!pChild) continue;
            this._changeProtectedChild(pChild);
            pChild.visit(this);
        }
        this._dirtyFlag = 0;
        this._cacheDirty = false;
    };
    proto.transform = function(parentCmd, recursive){
        var node = this._node;
        if(node._changePosition)
            node._changePosition();
        this.originTransform(parentCmd, recursive);
        var i, len, locChildren = node._protectedChildren;
        if(recursive && locChildren && locChildren.length !== 0){
            for(i = 0, len = locChildren.length; i< len; i++){
                locChildren[i]._renderCmd.transform(this, recursive);
            }
        }
    };
    proto.pNodeVisit = proto.visit;
    proto.pNodeTransform = proto.transform;
})();
(function(){
    if(!cc.Node.WebGLRenderCmd)
        return;
    cc.ProtectedNode.WebGLRenderCmd = function (renderable) {
        cc.Node.WebGLRenderCmd.call(this, renderable);
    };
    var proto = cc.ProtectedNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    cc.inject(cc.ProtectedNode.RenderCmd, proto);
    proto.constructor = cc.ProtectedNode.WebGLRenderCmd;
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        var  i, j;
        this._syncStatus(parentCmd);
        var locGrid = node.grid;
        if (locGrid && locGrid._active)
            locGrid.beforeDraw();
        var locChildren = node._children, locProtectedChildren = node._protectedChildren;
        var childLen = locChildren.length, pLen = locProtectedChildren.length;
        node.sortAllChildren();
        node.sortAllProtectedChildren();
        var pChild;
        for (i = 0; i < childLen; i++) {
            if (locChildren[i] && locChildren[i]._localZOrder < 0)
                locChildren[i].visit(this);
            else
                break;
        }
        for(j = 0; j < pLen; j++){
            pChild = locProtectedChildren[j];
            if (pChild && pChild._localZOrder < 0){
                this._changeProtectedChild(pChild);
                pChild.visit(this);
            }else
                break;
        }
        cc.renderer.pushRenderCommand(this);
        for (; i < childLen; i++) {
            locChildren[i] && locChildren[i].visit(this);
        }
        for (; j < pLen; j++) {
            pChild = locProtectedChildren[j];
            if(!pChild) continue;
            this._changeProtectedChild(pChild);
            pChild.visit(this);
        }
        if (locGrid && locGrid._active)
            locGrid.afterDraw(node);
        this._dirtyFlag = 0;
    };
    proto.transform = function(parentCmd, recursive){
        this.originTransform(parentCmd, recursive);
        var i, len,
            locChildren = this._node._protectedChildren;
        if(recursive && locChildren && locChildren.length !== 0){
            for(i = 0, len = locChildren.length; i< len; i++){
                locChildren[i]._renderCmd.transform(this, recursive);
            }
        }
    };
    proto.pNodeVisit = proto.visit;
    proto.pNodeTransform = proto.transform;
})();
var ccui = ccui || {};
ccui.Class = ccui.Class || cc.Class;
ccui.Class.extend = ccui.Class.extend || cc.Class.extend;
ccui.Node = ccui.Node || cc.Node;
ccui.Node.extend = ccui.Node.extend || cc.Node.extend;
ccui.ProtectedNode = ccui.ProtectedNode || cc.ProtectedNode;
ccui.ProtectedNode.extend = ccui.ProtectedNode.extend || cc.ProtectedNode.extend;
ccui.cocosGUIVersion = "CocosGUI v1.0.0.0";
ccui._FocusNavigationController = cc.Class.extend({
    _keyboardListener: null,
    _firstFocusedWidget: null,
    _enableFocusNavigation: false,
    _keyboardEventPriority: 1,
    enableFocusNavigation: function(flag){
        if (this._enableFocusNavigation === flag)
            return;
        this._enableFocusNavigation = flag;
        if (flag)
            this._addKeyboardEventListener();
        else
            this._removeKeyboardEventListener();
    },
    _setFirstFocsuedWidget: function(widget){
        this._firstFocusedWidget = widget;
    },
    _onKeyPressed: function(keyCode, event){
        if (this._enableFocusNavigation && this._firstFocusedWidget) {
            if (keyCode === cc.KEY.dpadDown) {
                this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.DOWN, this._firstFocusedWidget);
            }
            if (keyCode === cc.KEY.dpadUp){
                this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.UP, this._firstFocusedWidget);
            }
            if (keyCode === cc.KEY.dpadLeft) {
                this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.LEFT, this._firstFocusedWidget);
            }
            if (keyCode === cc.KEY.dpadRight) {
                this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.RIGHT, this._firstFocusedWidget);
            }
        }
    },
    _addKeyboardEventListener: function(){
        if (!this._keyboardListener) {
            this._keyboardListener = cc.EventListener.create({
                event: cc.EventListener.KEYBOARD,
                onKeyReleased: this._onKeyPressed.bind(this)
            });
            cc.eventManager.addListener(this._keyboardListener, this._keyboardEventPriority);
        }
    },
    _removeKeyboardEventListener: function(){
        if (this._keyboardListener) {
            cc.eventManager.removeEventListener(this._keyboardListener);
            this._keyboardListener = null;
        }
    }
});
ccui.__LAYOUT_COMPONENT_NAME = "__ui_layout";
ccui.Widget = ccui.ProtectedNode.extend({
    _enabled: true,
    _bright: true,
    _touchEnabled: false,
    _brightStyle: null,
    _touchBeganPosition: null,
    _touchMovePosition: null,
    _touchEndPosition: null,
    _touchEventListener: null,
    _touchEventSelector: null,
    _name: "default",
    _widgetType: null,
    _actionTag: 0,
    _customSize: null,
    _layoutParameterDictionary: null,
    _layoutParameterType:0,
    _focused: false,
    _focusEnabled: true,
    _ignoreSize: false,
    _affectByClipping: false,
    _sizeType: null,
    _sizePercent: null,
    _positionType: null,
    _positionPercent: null,
    _hit: false,
    _nodes: null,
    _touchListener: null,
    _className: "Widget",
    _flippedX: false,
    _flippedY: false,
    _opacity: 255,
    _highlight: false,
    _touchEventCallback: null,
    _clickEventListener: null,
    _propagateTouchEvents: true,
    _unifySize: false,
    _callbackName: null,
    _callbackType: null,
    _usingLayoutComponent: false,
    _inViewRect: true,
    ctor: function () {
        cc.ProtectedNode.prototype.ctor.call(this);
        this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
        this._touchBeganPosition = cc.p(0, 0);
        this._touchMovePosition = cc.p(0, 0);
        this._touchEndPosition = cc.p(0, 0);
        this._widgetType = ccui.Widget.TYPE_WIDGET;
        this._customSize = cc.size(0, 0);
        this._layoutParameterDictionary = {};
        this._sizeType = ccui.Widget.SIZE_ABSOLUTE;
        this._sizePercent = cc.p(0, 0);
        this._positionType = ccui.Widget.POSITION_ABSOLUTE;
        this._positionPercent = cc.p(0, 0);
        this._nodes = [];
        this._layoutParameterType = ccui.LayoutParameter.NONE;
        ccui.Widget.prototype.init.call(this);
    },
    /**
     * initializes state of widget. please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
     * @returns {boolean}
     */
    init: function () {
        if (cc.ProtectedNode.prototype.init.call(this)) {
            this._layoutParameterDictionary = {};
            this._initRenderer();
            this.setBright(true);
            this.onFocusChanged = this.onFocusChange;
            this.onNextFocusedWidget = null;
            this.setAnchorPoint(cc.p(0.5, 0.5));
            this.ignoreContentAdaptWithSize(true);
            return true;
        }
        return false;
    },
    onEnter: function () {
        var locListener = this._touchListener;
        if (locListener && !locListener._isRegistered() && this._touchEnabled)
            cc.eventManager.addListener(locListener, this);
        if(!this._usingLayoutComponent)
            this.updateSizeAndPosition();
        cc.ProtectedNode.prototype.onEnter.call(this);
    },
    onExit: function(){
        this.unscheduleUpdate();
        cc.ProtectedNode.prototype.onExit.call(this);
    },
    _getOrCreateLayoutComponent: function(){
        var layoutComponent = this.getComponent(ccui.__LAYOUT_COMPONENT_NAME);
        if (null == layoutComponent){
            layoutComponent = new ccui.LayoutComponent();
            this.addComponent(layoutComponent);
        }
        return layoutComponent;
    },
    getWidgetParent: function () {
        var widget = this.getParent();
        if (widget instanceof ccui.Widget)
            return widget;
        return null;
    },
    _updateContentSizeWithTextureSize: function(size){
        if(this._unifySize){
            this.setContentSize(size);
            return;
        }
        this.setContentSize(this._ignoreSize ? size : this._customSize);
    },
    _isAncestorsEnabled: function(){
        var parentWidget = this._getAncensterWidget(this);
        if (parentWidget == null)
            return true;
        if (parentWidget && !parentWidget.isEnabled())
            return false;
        return parentWidget._isAncestorsEnabled();
    },
    setPropagateTouchEvents: function(isPropagate){
        this._propagateTouchEvents = isPropagate;
    },
    isPropagateTouchEvents: function(){
        return this._propagateTouchEvents;
    },
    setSwallowTouches: function(swallow){
        if (this._touchListener)
            this._touchListener.setSwallowTouches(swallow);
    },
    isSwallowTouches: function(){
        if (this._touchListener){
            return this._touchListener.isSwallowTouches();
        }
        return false;
    },
    _getAncensterWidget: function(node){
        if (null == node)
            return null;
        var parent = node.getParent();
        if (null == parent)
            return null;
        if (parent instanceof ccui.Widget)
            return parent;
        else
            return this._getAncensterWidget(parent.getParent());
    },
    _isAncestorsVisible: function(node){
        if (null == node)
            return true;
        var parent = node.getParent();
        if (parent && !parent.isVisible())
            return false;
        return this._isAncestorsVisible(parent);
    },
    _cleanupWidget: function(){
        this._eventDispatcher.removeEventListener(this._touchListener);
        this._touchEnabled = false;
        this._touchListener = null;
        if (ccui.Widget._focusedWidget === this){
            ccui.Widget._focusedWidget = null;
            ccui.Widget._focusNavigationController = null;
        }
    },
    setEnabled: function (enabled) {
        this._enabled = enabled;
    },
    _initRenderer: function () {},
    setContentSize: function(contentSize, height){
        var locWidth = (height === undefined) ? contentSize.width : contentSize;
        var locHeight = (height === undefined) ? contentSize.height : height;
        cc.Node.prototype.setContentSize.call(this, locWidth, locHeight);
        this._customSize.width = locWidth;
        this._customSize.height = locHeight;
        if(this._unifySize){
        } else if (this._ignoreSize){
            this._contentSize = this.getVirtualRendererSize();
        }
        if (!this._usingLayoutComponent && this._running) {
            var widgetParent = this.getWidgetParent();
            var pSize = widgetParent ? widgetParent.getContentSize() : this._parent.getContentSize();
            this._sizePercent.x = (pSize.width > 0.0) ? locWidth / pSize.width : 0.0;
            this._sizePercent.y = (pSize.height > 0.0) ? locHeight / pSize.height : 0.0;
        }
        this._onSizeChanged();
    },
    _setWidth: function (w) {
        cc.Node.prototype._setWidth.call(this, w);
        this._customSize.width = w;
        if(this._unifySize){
        } else if (this._ignoreSize){
            this._contentSize = this.getVirtualRendererSize();
        }
        if (!this._usingLayoutComponent && this._running) {
            var widgetParent = this.getWidgetParent();
            var locWidth = widgetParent ? widgetParent.width : this._parent.width;
            this._sizePercent.x = locWidth > 0 ? this._customSize.width / locWidth : 0;
        }
        this._onSizeChanged();
    },
    _setHeight: function (h) {
        cc.Node.prototype._setHeight.call(this, h);
        this._customSize.height = h;
        if(this._unifySize){
        } else if (this._ignoreSize){
            this._contentSize = this.getVirtualRendererSize();
        }
        if (!this._usingLayoutComponent && this._running) {
            var widgetParent = this.getWidgetParent();
            var locH = widgetParent ? widgetParent.height : this._parent.height;
            this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0;
        }
        this._onSizeChanged();
    },
    setSizePercent: function (percent) {
        if(this._usingLayoutComponent){
            var component = this._getOrCreateLayoutComponent();
            component.setUsingPercentContentSize(true);
            component.setPercentContentSize(percent);
            component.refreshLayout();
            return;
        }
        this._sizePercent.x = percent.x;
        this._sizePercent.y = percent.y;
        var width = this._customSize.width, height = this._customSize.height;
        if (this._running) {
            var widgetParent = this.getWidgetParent();
            if (widgetParent) {
                width = widgetParent.width * percent.x;
                height = widgetParent.height * percent.y;
            } else {
                width = this._parent.width * percent.x;
                height = this._parent.height * percent.y;
            }
        }
        if (this._ignoreSize)
            this.setContentSize(this.getVirtualRendererSize());
        else
            this.setContentSize(width, height);
        this._customSize.width = width;
        this._customSize.height = height;
    },
    _setWidthPercent: function (percent) {
        this._sizePercent.x = percent;
        var width = this._customSize.width;
        if (this._running) {
            var widgetParent = this.getWidgetParent();
            width = (widgetParent ? widgetParent.width : this._parent.width) * percent;
        }
        if (this._ignoreSize)
            this._setWidth(this.getVirtualRendererSize().width);
        else
            this._setWidth(width);
        this._customSize.width = width;
    },
    _setHeightPercent: function (percent) {
        this._sizePercent.y = percent;
        var height = this._customSize.height;
        if (this._running) {
            var widgetParent = this.getWidgetParent();
            height = (widgetParent ? widgetParent.height : this._parent.height) * percent;
        }
        if (this._ignoreSize)
            this._setHeight(this.getVirtualRendererSize().height);
        else
            this._setHeight(height);
        this._customSize.height = height;
    },
    updateSizeAndPosition: function (parentSize) {
        if(!parentSize){
            var widgetParent = this.getWidgetParent();
            if(widgetParent)
                parentSize = widgetParent.getLayoutSize();
            else
                parentSize = this._parent.getContentSize();
        }
        switch (this._sizeType) {
            case ccui.Widget.SIZE_ABSOLUTE:
                if(this._ignoreSize)
                    this.setContentSize(this.getVirtualRendererSize());
                else
                    this.setContentSize(this._customSize);
                this._sizePercent.x = (parentSize.width > 0) ? this._customSize.width / parentSize.width : 0;
                this._sizePercent.y = (parentSize.height > 0) ? this._customSize.height / parentSize.height : 0;
                break;
            case ccui.Widget.SIZE_PERCENT:
                var cSize = cc.size(parentSize.width * this._sizePercent.x , parentSize.height * this._sizePercent.y);
                if(this._ignoreSize)
                    this.setContentSize(this.getVirtualRendererSize());
                else
                    this.setContentSize(cSize);
                this._customSize.width = cSize.width;
                this._customSize.height = cSize.height;
                break;
            default:
                break;
        }
        this._onSizeChanged();
        var absPos = this.getPosition();
        switch (this._positionType) {
            case ccui.Widget.POSITION_ABSOLUTE:
                if (parentSize.width <= 0 || parentSize.height <= 0) {
                    this._positionPercent.x = this._positionPercent.y = 0;
                } else {
                    this._positionPercent.x = absPos.x / parentSize.width;
                    this._positionPercent.y = absPos.y / parentSize.height;
                }
                break;
            case ccui.Widget.POSITION_PERCENT:
                absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y);
                break;
            default:
                break;
        }
        if(this._parent instanceof ccui.ImageView){
            var renderer = this._parent._imageRenderer;
            if(renderer && !renderer._textureLoaded)
                return;
        }
        this.setPosition(absPos);
    },
    setSizeType: function (type) {
        this._sizeType = type;
        if (this._usingLayoutComponent) {
            var component = this._getOrCreateLayoutComponent();
            component.setUsingPercentContentSize(this._sizeType === ccui.SIZE_PERCENT);
        }
    },
    getSizeType: function () {
        return this._sizeType;
    },
    ignoreContentAdaptWithSize: function (ignore) {
        if(this._unifySize){
            this.setContentSize(this._customSize);
            return;
        }
        if(this._ignoreSize === ignore)
            return;
        this._ignoreSize = ignore;
        this.setContentSize( ignore ? this.getVirtualRendererSize() : this._customSize );
    },
    isIgnoreContentAdaptWithSize: function () {
        return this._ignoreSize;
    },
    getCustomSize: function () {
        return cc.size(this._customSize);
    },
    getLayoutSize: function(){
        return cc.size(this._contentSize);
    },
    getSizePercent: function () {
        if(this._usingLayoutComponent){
            var component = this._getOrCreateLayoutComponent();
            this._sizePercent = component.getPercentContentSize();
        }
        return this._sizePercent;
    },
    _getWidthPercent: function () {
        return this._sizePercent.x;
    },
    _getHeightPercent: function () {
        return this._sizePercent.y;
    },
    getWorldPosition: function () {
        return this.convertToWorldSpace(cc.p(this._anchorPoint.x * this._contentSize.width, this._anchorPoint.y * this._contentSize.height));
    },
    getVirtualRenderer: function () {
        return this;
    },
    getVirtualRendererSize:function(){
        return cc.size(this._contentSize);
    },
    _onSizeChanged: function () {
        if(!this._usingLayoutComponent){
            var locChildren =  this.getChildren();
            for (var i = 0, len = locChildren.length; i < len; i++) {
                var child = locChildren[i];
                if(child instanceof ccui.Widget)
                    child.updateSizeAndPosition();
            }
        }
    },
    setTouchEnabled: function (enable) {
        if (this._touchEnabled === enable)
            return;
        this._touchEnabled = enable;
        if (this._touchEnabled) {
            if(!this._touchListener)
                this._touchListener = cc.EventListener.create({
                    event: cc.EventListener.TOUCH_ONE_BY_ONE,
                    swallowTouches: true,
                    onTouchBegan: this.onTouchBegan.bind(this),
                    onTouchMoved: this.onTouchMoved.bind(this),
                    onTouchEnded: this.onTouchEnded.bind(this)
                });
            cc.eventManager.addListener(this._touchListener, this);
        } else {
            cc.eventManager.removeListener(this._touchListener);
        }
    },
    isTouchEnabled: function () {
        return this._touchEnabled;
    },
    isHighlighted: function(){
        return this._highlight;
    },
    setHighlighted:function(highlight){
        if (highlight === this._highlight)
            return;
        this._highlight = highlight;
        if (this._bright) {
            if (this._highlight)
                this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT);
            else
                this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL);
        } else
            this._onPressStateChangedToDisabled();
    },
    isFocused: function () {
        return this._focused;
    },
    setFocused: function (focus) {
        this._focused = focus;
        if (focus){
            ccui.Widget._focusedWidget = this;
            if(ccui.Widget._focusNavigationController)
                ccui.Widget._focusNavigationController._setFirstFocsuedWidget(this);
        }
    },
    isFocusEnabled: function(){
        return this._focusEnabled;
    },
    setFocusEnabled: function(enable){
        this._focusEnabled = enable;
    },
    findNextFocusedWidget: function( direction, current){
        if (null === this.onNextFocusedWidget || null == this.onNextFocusedWidget(direction) ) {
            var isLayout = current instanceof ccui.Layout;
            if (this.isFocused() || isLayout) {
                var layout = this.getParent();
                if (null === layout || !(layout instanceof ccui.Layout)){
                    if (isLayout)
                        return current.findNextFocusedWidget(direction, current);
                    return current;
                } else
                    return layout.findNextFocusedWidget(direction, current);
            } else
                return current;
        } else {
            var getFocusWidget = this.onNextFocusedWidget(direction);
            this.dispatchFocusEvent(this, getFocusWidget);
            return getFocusWidget;
        }
    },
    requestFocus: function(){
        if (this === ccui.Widget._focusedWidget)
            return;
        this.dispatchFocusEvent(ccui.Widget._focusedWidget, this);
    },
    getCurrentFocusedWidget: function(){
        return ccui.Widget._focusedWidget;
    },
    onFocusChanged: null,
    onNextFocusedWidget: null,
    interceptTouchEvent: function(eventType, sender, touch){
        var widgetParent = this.getWidgetParent();
        if (widgetParent)
            widgetParent.interceptTouchEvent(eventType,sender,touch);
    },
    onFocusChange: function(widgetLostFocus, widgetGetFocus){
        if (widgetLostFocus)
            widgetLostFocus.setFocused(false);
        if (widgetGetFocus)
            widgetGetFocus.setFocused(true);
    },
    dispatchFocusEvent: function(widgetLostFocus, widgetGetFocus){
        if (widgetLostFocus && !widgetLostFocus.isFocused())
            widgetLostFocus = ccui.Widget._focusedWidget;
        if (widgetGetFocus !== widgetLostFocus){
            if (widgetGetFocus && widgetGetFocus.onFocusChanged)
                widgetGetFocus.onFocusChanged(widgetLostFocus, widgetGetFocus);
            if (widgetLostFocus && widgetGetFocus.onFocusChanged)
                widgetLostFocus.onFocusChanged(widgetLostFocus, widgetGetFocus);
            cc.eventManager.dispatchEvent(new cc.EventFocus(widgetLostFocus, widgetGetFocus));
        }
    },
    setBright: function (bright) {
        this._bright = bright;
        if (this._bright) {
            this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
            this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL);
        } else
            this._onPressStateChangedToDisabled();
    },
    setBrightStyle: function (style) {
        if (this._brightStyle === style)
            return;
        style = style || ccui.Widget.BRIGHT_STYLE_NORMAL;
        this._brightStyle = style;
        switch (this._brightStyle) {
            case ccui.Widget.BRIGHT_STYLE_NORMAL:
                this._onPressStateChangedToNormal();
                break;
            case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
                this._onPressStateChangedToPressed();
                break;
            default:
                break;
        }
    },
    _onPressStateChangedToNormal: function () {},
    _onPressStateChangedToPressed: function () {},
    _onPressStateChangedToDisabled: function () {},
    _updateChildrenDisplayedRGBA: function(){
        this.setColor(this.getColor());
        this.setOpacity(this.getOpacity());
    },
    didNotSelectSelf: function () {},
    onTouchBegan: function (touch, event) {
        this._hit = false;
        if (this.isVisible() && this.isEnabled() && this._isAncestorsEnabled() && this._isAncestorsVisible(this) ){
            var touchPoint = touch.getLocation();
            this._touchBeganPosition.x = touchPoint.x;
            this._touchBeganPosition.y = touchPoint.y;
            if(this.hitTest(this._touchBeganPosition) && this.isClippingParentContainsPoint(this._touchBeganPosition))
                this._hit = true;
        }
        if (!this._hit) {
            return false;
        }
        this.setHighlighted(true);
        if (this._propagateTouchEvents) {
            this.propagateTouchEvent(ccui.Widget.TOUCH_BEGAN, this, touch);
        }
        this._pushDownEvent();
        return true;
    },
    propagateTouchEvent: function(event, sender, touch){
        var widgetParent = this.getWidgetParent();
        if (widgetParent){
            widgetParent.interceptTouchEvent(event, sender, touch);
        }
    },
    onTouchMoved: function (touch, event) {
        var touchPoint = touch.getLocation();
        this._touchMovePosition.x = touchPoint.x;
        this._touchMovePosition.y = touchPoint.y;
        this.setHighlighted(this.hitTest(touchPoint));
        if (this._propagateTouchEvents)
            this.propagateTouchEvent(ccui.Widget.TOUCH_MOVED, this, touch);
        this._moveEvent();
    },
    onTouchEnded: function (touch, event) {
        var touchPoint = touch.getLocation();
        this._touchEndPosition.x = touchPoint.x;
        this._touchEndPosition.y = touchPoint.y;
        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();
    },
    onTouchCancelled: function (touchPoint) {
        this.setHighlighted(false);
        this._cancelUpEvent();
    },
    onTouchLongClicked: function (touchPoint) {
        this.longClickEvent();
    },
    _pushDownEvent: function () {
        if (this._touchEventCallback)
            this._touchEventCallback(this, ccui.Widget.TOUCH_BEGAN);
        if (this._touchEventListener && this._touchEventSelector)
            this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_BEGAN);
    },
    _moveEvent: function () {
        if (this._touchEventCallback)
            this._touchEventCallback(this, ccui.Widget.TOUCH_MOVED);
        if (this._touchEventListener && this._touchEventSelector)
            this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_MOVED);
    },
    _releaseUpEvent: function () {
        if (this._touchEventCallback)
            this._touchEventCallback(this, ccui.Widget.TOUCH_ENDED);
        if (this._touchEventListener && this._touchEventSelector)
            this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_ENDED);
        if (this._clickEventListener)
            this._clickEventListener(this);
    },
    _cancelUpEvent: function () {
        if (this._touchEventCallback)
            this._touchEventCallback(this, ccui.Widget.TOUCH_CANCELED);
        if (this._touchEventListener && this._touchEventSelector)
            this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_CANCELED);
    },
    longClickEvent: function () {
    },
    addTouchEventListener: function (selector, target) {
        if(target === undefined)
            this._touchEventCallback = selector;
        else {
            this._touchEventSelector = selector;
            this._touchEventListener = target;
        }
    },
    addClickEventListener: function(callback){
        this._clickEventListener = callback;
    },
    hitTest: function (pt) {
        var bb = cc.rect(0,0, this._contentSize.width, this._contentSize.height);
        return cc.rectContainsPoint(bb, this.convertToNodeSpace(pt));
    },
    isClippingParentContainsPoint: function(pt){
        this._affectByClipping = false;
        var parent = this.getParent();
        var clippingParent = null;
        while (parent) {
            if (parent instanceof ccui.Layout) {
                if (parent.isClippingEnabled()) {
                    this._affectByClipping = true;
                    clippingParent = parent;
                    break;
                }
            }
            parent = parent.getParent();
        }
        if (!this._affectByClipping)
            return true;
        if (clippingParent) {
            if (clippingParent.hitTest(pt))
                return clippingParent.isClippingParentContainsPoint(pt);
            return false;
        }
        return true;
    },
    checkChildInfo: function (handleState, sender, touchPoint) {
        var widgetParent = this.getWidgetParent();
        if (widgetParent)
            widgetParent.checkChildInfo(handleState, sender, touchPoint);
    },
    setPosition: function (pos, posY) {
        if (!this._usingLayoutComponent && this._running) {
            var widgetParent = this.getWidgetParent();
            if (widgetParent) {
                var pSize = widgetParent.getContentSize();
                if (pSize.width <= 0 || pSize.height <= 0) {
                    this._positionPercent.x = 0;
                    this._positionPercent.y = 0;
                } else {
                    if (posY === undefined) {
                        this._positionPercent.x = pos.x / pSize.width;
                        this._positionPercent.y = pos.y / pSize.height;
                    } else {
                        this._positionPercent.x = pos / pSize.width;
                        this._positionPercent.y = posY / pSize.height;
                    }
                }
            }
        }
        cc.Node.prototype.setPosition.call(this, pos, posY);
    },
    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);
    },
    setPositionPercent: function (percent) {
        if (this._usingLayoutComponent){
            var component = this._getOrCreateLayoutComponent();
            component.setPositionPercentX(percent.x);
            component.setPositionPercentY(percent.y);
            component.refreshLayout();
            return;
        }else{
            this._setXPercent(percent.x);
            this._setYPercent(percent.y);
        }
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    _setXPercent: function (percent) {
        if (this._usingLayoutComponent){
            var component = this._getOrCreateLayoutComponent();
            component.setPositionPercentX(percent.x);
            component.refreshLayout();
            return;
        }
        this._positionPercent.x = percent;
    },
    _setYPercent: function (percent) {
        if (this._usingLayoutComponent){
            var component = this._getOrCreateLayoutComponent();
            component.setPositionPercentY(percent.x);
            component.refreshLayout();
            return;
        }
        this._positionPercent.y = percent;
    },
    getPositionPercent: function () {
        if (this._usingLayoutComponent) {
            var component = this._getOrCreateLayoutComponent();
            this._positionPercent.x = component.getPositionPercentX();
            this._positionPercent.y = component.getPositionPercentY();
        }
        return cc.p(this._positionPercent);
    },
    _getXPercent: function () {
        if (this._usingLayoutComponent) {
            var component = this._getOrCreateLayoutComponent();
            this._positionPercent.x = component.getPositionPercentX();
            this._positionPercent.y = component.getPositionPercentY();
        }
        return this._positionPercent.x;
    },
    _getYPercent: function () {
        if (this._usingLayoutComponent) {
            var component = this._getOrCreateLayoutComponent();
            this._positionPercent.x = component.getPositionPercentX();
            this._positionPercent.y = component.getPositionPercentY();
        }
        return this._positionPercent.y;
    },
    setPositionType: function (type) {
        this._positionType = type;
        if(this._usingLayoutComponent){
            var component = this._getOrCreateLayoutComponent();
            if (type === ccui.POSITION_ABSOLUTE){
                component.setPositionPercentXEnabled(false);
                component.setPositionPercentYEnabled(false);
            } else {
                component.setPositionPercentXEnabled(true);
                component.setPositionPercentYEnabled(true);
            }
        }
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    },
    getPositionType: function () {
        return this._positionType;
    },
    setFlippedX: function (flipX) {
        var realScale = this.getScaleX();
        this._flippedX = flipX;
        this.setScaleX(realScale);
    },
    isFlippedX: function () {
        return this._flippedX;
    },
    setFlippedY: function (flipY) {
        var realScale = this.getScaleY();
        this._flippedY = flipY;
        this.setScaleY(realScale);
    },
    isFlippedY: function () {
        return this._flippedY;
    },
    _adaptRenderers: function(){},
    isBright: function () {
        return this._bright;
    },
    isEnabled: function () {
        return this._enabled;
    },
    getLeftBoundary: function () {
        return this.getPositionX() - this._getAnchorX() * this._contentSize.width;
    },
    getBottomBoundary: function () {
        return this.getPositionY() - this._getAnchorY() * this._contentSize.height;
    },
    getRightBoundary: function () {
        return this.getLeftBoundary() + this._contentSize.width;
    },
    getTopBoundary: function () {
        return this.getBottomBoundary() + this._contentSize.height;
    },
    getTouchBeganPosition: function(){
         return cc.p(this._touchBeganPosition);
    },
    getTouchMovePosition: function(){
        return cc.p(this._touchMovePosition);
    },
    getTouchEndPosition:function(){
        return cc.p(this._touchEndPosition);
    },
    getWidgetType: function () {
        return this._widgetType;
    },
    setLayoutParameter: function (parameter) {
        if(!parameter)
            return;
        this._layoutParameterDictionary[parameter.getLayoutType()] = parameter;
        this._layoutParameterType = parameter.getLayoutType();
    },
    getLayoutParameter: function (type) {
        type = type || this._layoutParameterType;
        return this._layoutParameterDictionary[type];
    },
    getDescription: function () {
        return "Widget";
    },
    clone: function () {
        var clonedWidget = this._createCloneInstance();
        clonedWidget._copyProperties(this);
        clonedWidget._copyClonedWidgetChildren(this);
        return clonedWidget;
    },
    _createCloneInstance: function () {
        return new ccui.Widget();
    },
    _copyClonedWidgetChildren: function (model) {
        var widgetChildren = model.getChildren();
        for (var i = 0; i < widgetChildren.length; i++) {
            var locChild = widgetChildren[i];
            if (locChild instanceof ccui.Widget)
                this.addChild(locChild.clone());
        }
    },
    _copySpecialProperties: function (model) {},
    _copyProperties: function (widget) {
        this.setEnabled(widget.isEnabled());
        this.setVisible(widget.isVisible());
        this.setBright(widget.isBright());
        this.setTouchEnabled(widget.isTouchEnabled());
        this.setLocalZOrder(widget.getLocalZOrder());
        this.setTag(widget.getTag());
        this.setName(widget.getName());
        this.setActionTag(widget.getActionTag());
        this._ignoreSize = widget._ignoreSize;
        this.setContentSize(widget._contentSize);
        this._customSize.width = widget._customSize.width;
        this._customSize.height = widget._customSize.height;
        this._copySpecialProperties(widget);
        this._sizeType = widget.getSizeType();
        this._sizePercent.x = widget._sizePercent.x;
        this._sizePercent.y = widget._sizePercent.y;
        this._positionType = widget._positionType;
        this._positionPercent.x = widget._positionPercent.x;
        this._positionPercent.y = widget._positionPercent.y;
        this.setPosition(widget.getPosition());
        this.setAnchorPoint(widget.getAnchorPoint());
        this.setScaleX(widget.getScaleX());
        this.setScaleY(widget.getScaleY());
        this.setRotation(widget.getRotation());
        this.setRotationX(widget.getRotationX());
        this.setRotationY(widget.getRotationY());
        this.setFlippedX(widget.isFlippedX());
        this.setFlippedY(widget.isFlippedY());
        this.setColor(widget.getColor());
        this.setOpacity(widget.getOpacity());
        this._touchEventCallback = widget._touchEventCallback;
        this._touchEventListener = widget._touchEventListener;
        this._touchEventSelector = widget._touchEventSelector;
        this._clickEventListener = widget._clickEventListener;
        this._focused = widget._focused;
        this._focusEnabled = widget._focusEnabled;
        this._propagateTouchEvents = widget._propagateTouchEvents;
        for (var key in widget._layoutParameterDictionary) {
            var parameter = widget._layoutParameterDictionary[key];
            if (parameter)
                this.setLayoutParameter(parameter.clone());
        }
        this._onSizeChanged();
    },
    setActionTag: function (tag) {
        this._actionTag = tag;
    },
    getActionTag: function () {
        return this._actionTag;
    },
    getLeftInParent: function(){
        cc.log("getLeftInParent is deprecated. Please use getLeftBoundary instead.");
        return this.getLeftBoundary();
    },
    getBottomInParent: function(){
        cc.log("getBottomInParent is deprecated. Please use getBottomBoundary instead.");
        return this.getBottomBoundary();
    },
    getRightInParent: function(){
        cc.log("getRightInParent is deprecated. Please use getRightBoundary instead.");
        return this.getRightBoundary();
    },
    getTopInParent: function(){
        cc.log("getTopInParent is deprecated. Please use getTopBoundary instead.");
        return this.getTopBoundary();
    },
    getTouchEndPos: function () {
        cc.log("getTouchEndPos is deprecated. Please use getTouchEndPosition instead.");
        return this.getTouchEndPosition();
    },
    getTouchMovePos: function () {
        cc.log("getTouchMovePos is deprecated. Please use getTouchMovePosition instead.");
        return this.getTouchMovePosition();
    },
    clippingParentAreaContainPoint: function (pt) {
        cc.log("clippingParentAreaContainPoint is deprecated. Please use isClippingParentContainsPoint instead.");
        this.isClippingParentContainsPoint(pt);
    },
    getTouchStartPos: function () {
        cc.log("getTouchStartPos is deprecated. Please use getTouchBeganPosition instead.");
        return this.getTouchBeganPosition();
    },
    setSize: function (size) {
        this.setContentSize(size);
    },
    getSize: function () {
        return this.getContentSize();
    },
    addNode: function (node, zOrder, tag) {
        if (node instanceof ccui.Widget) {
            cc.log("Please use addChild to add a Widget.");
            return;
        }
        cc.Node.prototype.addChild.call(this, node, zOrder, tag);
        this._nodes.push(node);
    },
    getNodeByTag: function (tag) {
        var _nodes = this._nodes;
        for (var i = 0; i < _nodes.length; i++) {
            var node = _nodes[i];
            if (node && node.getTag() === tag) {
                return node;
            }
        }
        return null;
    },
    getNodes: function () {
        return this._nodes;
    },
    removeNode: function (node, cleanup) {
        cc.Node.prototype.removeChild.call(this, node, cleanup);
        cc.arrayRemoveObject(this._nodes, node);
    },
    removeNodeByTag: function (tag, cleanup) {
        var node = this.getChildByTag(tag);
        if (!node)
            cc.log("cocos2d: removeNodeByTag(tag = %d): child not found!", tag);
        else
            this.removeChild(node, cleanup);
    },
    removeAllNodes: function () {
        for (var i = 0; i < this._nodes.length; i++) {
            var node = this._nodes[i];
            cc.Node.prototype.removeChild.call(this, node);
        }
        this._nodes.length = 0;
    },
    _findLayout: function(){
        cc.renderer.childrenOrderDirty = true;
        var layout = this._parent;
        while(layout){
            if(layout._doLayout){
                layout._doLayoutDirty = true;
                break;
            }else
                layout = layout._parent;
        }
    },
    isUnifySizeEnabled: function(){
        return this._unifySize;
    },
    setUnifySizeEnabled: function(enable){
        this._unifySize = enable;
    },
    _ccEventCallback: null,
    addCCSEventListener: function(callback){
        this._ccEventCallback = callback;
    },
    setScaleX: function(scaleX){
        if (this._flippedX)
            scaleX = scaleX * -1;
        cc.Node.prototype.setScaleX.call(this, scaleX);
    },
    setScaleY: function(scaleY){
        if (this._flippedY)
            scaleY = scaleY * -1;
        cc.Node.prototype.setScaleY.call(this, scaleY);
    },
    setScale: function(scaleX, scaleY){
        if(scaleY === undefined)
            scaleY = scaleX;
        this.setScaleX(scaleX);
        this.setScaleY(scaleY);
    },
    getScaleX: function(){
        var originalScale = cc.Node.prototype.getScaleX.call(this);
        if (this._flippedX)
            originalScale = originalScale * -1.0;
        return originalScale;
    },
    getScaleY: function(){
        var originalScale = cc.Node.prototype.getScaleY.call(this);
        if (this._flippedY)
            originalScale = originalScale * -1.0;
        return originalScale;
    },
    getScale: function(){
        if(this.getScaleX() !== this.getScaleY())
            cc.log("Widget#scale. ScaleX != ScaleY. Don't know which one to return");
        return this.getScaleX();
    },
    setCallbackName: function(callbackName){
        this._callbackName = callbackName;
    },
    getCallbackName: function(){
        return this._callbackName;
    },
    setCallbackType: function(callbackType){
        this._callbackType = callbackType;
    },
    getCallbackType: function(){
        return this._callbackType;
    },
    setLayoutComponentEnabled: function(enable){
        this._usingLayoutComponent = enable;
    },
    isLayoutComponentEnabled: function(){
        return this._usingLayoutComponent;
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new ccui.Widget.WebGLRenderCmd(this);
        else
            return new ccui.Widget.CanvasRenderCmd(this);
    }
});
var _p = ccui.Widget.prototype;
_p.xPercent;
cc.defineGetterSetter(_p, "xPercent", _p._getXPercent, _p._setXPercent);
_p.yPercent;
cc.defineGetterSetter(_p, "yPercent", _p._getYPercent, _p._setYPercent);
_p.widthPercent;
cc.defineGetterSetter(_p, "widthPercent", _p._getWidthPercent, _p._setWidthPercent);
_p.heightPercent;
cc.defineGetterSetter(_p, "heightPercent", _p._getHeightPercent, _p._setHeightPercent);
_p.widgetParent;
cc.defineGetterSetter(_p, "widgetParent", _p.getWidgetParent);
_p.enabled;
cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
_p.focused;
cc.defineGetterSetter(_p, "focused", _p.isFocused, _p.setFocused);
_p.sizeType;
cc.defineGetterSetter(_p, "sizeType", _p.getSizeType, _p.setSizeType);
_p.widgetType;
cc.defineGetterSetter(_p, "widgetType", _p.getWidgetType);
_p.touchEnabled;
cc.defineGetterSetter(_p, "touchEnabled", _p.isTouchEnabled, _p.setTouchEnabled);
_p.updateEnabled;
cc.defineGetterSetter(_p, "updateEnabled", _p.isUpdateEnabled, _p.setUpdateEnabled);
_p.bright;
cc.defineGetterSetter(_p, "bright", _p.isBright, _p.setBright);
_p.name;
cc.defineGetterSetter(_p, "name", _p.getName, _p.setName);
_p.actionTag;
cc.defineGetterSetter(_p, "actionTag", _p.getActionTag, _p.setActionTag);
_p.opacity;
cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
_p = null;
ccui.Widget.create = function () {
    return new ccui.Widget();
};
ccui.Widget._focusedWidget = null;
ccui.Widget._focusNavigationController = null;
ccui.Widget.enableDpadNavigation = function(enable){
    if (enable){
        if (null == ccui.Widget._focusNavigationController) {
            ccui.Widget._focusNavigationController = new ccui._FocusNavigationController();
            if (ccui.Widget._focusedWidget) {
                ccui.Widget._focusNavigationController._setFirstFocsuedWidget(ccui.Widget._focusedWidget);
            }
        }
        ccui.Widget._focusNavigationController.enableFocusNavigation(true);
    } else {
        if(ccui.Widget._focusNavigationController){
            ccui.Widget._focusNavigationController.enableFocusNavigation(false);
            ccui.Widget._focusNavigationController = null;
        }
    }
};
ccui.Widget.getCurrentFocusedWidget = function(){
    return ccui.Widget._focusedWidget;
};
ccui.Widget.BRIGHT_STYLE_NONE = -1;
ccui.Widget.BRIGHT_STYLE_NORMAL = 0;
ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT = 1;
ccui.Widget.TYPE_WIDGET = 0;
ccui.Widget.TYPE_CONTAINER = 1;
ccui.Widget.LEFT = 0;
ccui.Widget.RIGHT = 1;
ccui.Widget.UP = 2;
ccui.Widget.DOWN = 3;
ccui.Widget.LOCAL_TEXTURE = 0;
ccui.Widget.PLIST_TEXTURE = 1;
ccui.Widget.TOUCH_BEGAN = 0;
ccui.Widget.TOUCH_MOVED = 1;
ccui.Widget.TOUCH_ENDED = 2;
ccui.Widget.TOUCH_CANCELED = 3;
ccui.Widget.SIZE_ABSOLUTE = 0;
ccui.Widget.SIZE_PERCENT = 1;
ccui.Widget.POSITION_ABSOLUTE = 0;
ccui.Widget.POSITION_PERCENT = 1;
cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
    if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
        ccui.Widget.CanvasRenderCmd = function (renderable) {
            cc.ProtectedNode.CanvasRenderCmd.call(this, renderable);
            this._needDraw = false;
        };
        var proto = ccui.Widget.CanvasRenderCmd.prototype = Object.create(cc.ProtectedNode.CanvasRenderCmd.prototype);
        proto.constructor = ccui.Widget.CanvasRenderCmd;
        proto.visit = function (parentCmd) {
            var node = this._node;
            if (node._visible) {
                node._adaptRenderers();
                this.pNodeVisit(parentCmd);
            }
        };
        proto.transform = function (parentCmd, recursive) {
            var node = this._node;
            if (node._visible && node._running) {
                node._adaptRenderers();
                if(!this._usingLayoutComponent){
                    var widgetParent = node.getWidgetParent();
                    if (widgetParent) {
                        var parentSize = widgetParent.getContentSize();
                        if (parentSize.width !== 0 && parentSize.height !== 0) {
                            node._position.x = parentSize.width * node._positionPercent.x;
                            node._position.y = parentSize.height * node._positionPercent.y;
                        }
                    }
                }
                this.pNodeTransform(parentCmd, recursive);
            }
        };
        proto.widgetVisit = proto.visit;
        proto.widgetTransform = proto.transform;
    } else {
        ccui.Widget.WebGLRenderCmd = function (renderable) {
            cc.ProtectedNode.WebGLRenderCmd.call(this, renderable);
            this._needDraw = false;
        };
        var proto = ccui.Widget.WebGLRenderCmd.prototype = Object.create(cc.ProtectedNode.WebGLRenderCmd.prototype);
        proto.constructor = ccui.Widget.WebGLRenderCmd;
        proto.visit = function (parentCmd) {
            var node = this._node;
            if (node._visible) {
                node._adaptRenderers();
                this.pNodeVisit(parentCmd);
            }
        };
        proto.transform = function(parentCmd, recursive){
            var node = this._node;
            if (node._visible && node._running) {
                node._adaptRenderers();
                if(!this._usingLayoutComponent) {
                    var widgetParent = node.getWidgetParent();
                    if (widgetParent) {
                        var parentSize = widgetParent.getContentSize();
                        if (parentSize.width !== 0 && parentSize.height !== 0) {
                            node._position.x = parentSize.width * node._positionPercent.x;
                            node._position.y = parentSize.height * node._positionPercent.y;
                        }
                    }
                }
                this.pNodeTransform(parentCmd, recursive);
            }
        };
        proto.widgetVisit = proto.visit;
        proto.widgetTransform = proto.transform;
    }
});
ccui.Scale9Sprite = cc.Scale9Sprite = cc.Node.extend({
    _spriteRect: null,
    _capInsetsInternal: null,
    _positionsAreDirty: false,
    _scale9Image: null,
    _topLeft: null,
    _top: null,
    _topRight: null,
    _left: null,
    _centre: null,
    _right: null,
    _bottomLeft: null,
    _bottom: null,
    _bottomRight: null,
    _scale9Enabled: true,
    _brightState: 0,
    _renderers: null,
    _opacityModifyRGB: false,
    _originalSize: null,
    _preferredSize: null,
    _opacity: 0,
    _color: null,
    _capInsets: null,
    _insetLeft: 0,
    _insetTop: 0,
    _insetRight: 0,
    _insetBottom: 0,
    _spriteFrameRotated: false,
    _textureLoaded:false,
    _className:"Scale9Sprite",
    _flippedX: false,
    _flippedY: false,
    textureLoaded:function(){
        return this._textureLoaded;
    },
    addLoadedEventListener:function(callback, target){
        this.addEventListener("load", callback, target);
    },
    _updateCapInset: function () {
        var insets, locInsetLeft = this._insetLeft, locInsetTop = this._insetTop, locInsetRight = this._insetRight;
        var locSpriteRect = this._spriteRect, locInsetBottom = this._insetBottom;
        if (locInsetLeft === 0 && locInsetTop === 0 && locInsetRight === 0 && locInsetBottom === 0) {
            insets = cc.rect(0, 0, 0, 0);
        } else {
            insets = this._spriteFrameRotated ? cc.rect(locInsetBottom, locInsetLeft,
                    locSpriteRect.width - locInsetRight - locInsetLeft,
                    locSpriteRect.height - locInsetTop - locInsetBottom) :
                cc.rect(locInsetLeft, locInsetTop,
                        locSpriteRect.width - locInsetLeft - locInsetRight,
                        locSpriteRect.height - locInsetTop - locInsetBottom);
        }
        this.setCapInsets(insets);
    },
    _updatePositions: function () {
        if (!((this._topLeft) && (this._topRight) && (this._bottomRight) &&
            (this._bottomLeft) && (this._centre))) {
            return;
        }
        var size = this._contentSize;
        var locTopLeft = this._topLeft, locTopRight = this._topRight, locBottomRight = this._bottomRight, locBottomLeft = this._bottomLeft;
        var locLeft = this._left, locRight = this._right, locTop = this._top, locBottom = this._bottom;
        var locCenter = this._centre, locCenterContentSize = this._centre.getContentSize();
        var locTopLeftContentSize = locTopLeft.getContentSize();
        var locBottomLeftContentSize = locBottomLeft.getContentSize();
        var sizableWidth = size.width - locTopLeftContentSize.width - locTopRight.getContentSize().width;
        var sizableHeight = size.height - locTopLeftContentSize.height - locBottomRight.getContentSize().height;
        var horizontalScale = sizableWidth / locCenterContentSize.width;
        var verticalScale = sizableHeight / locCenterContentSize.height;
        var rescaledWidth = locCenterContentSize.width * horizontalScale;
        var rescaledHeight = locCenterContentSize.height * verticalScale;
        var leftWidth = locBottomLeftContentSize.width;
        var bottomHeight = locBottomLeftContentSize.height;
        var centerOffset = cc.p(this._offset.x * horizontalScale, this._offset.y*verticalScale);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
            var roundedRescaledWidth = Math.round(rescaledWidth);
            if (rescaledWidth !== roundedRescaledWidth) {
                rescaledWidth = roundedRescaledWidth;
                horizontalScale = rescaledWidth / locCenterContentSize.width;
            }
            var roundedRescaledHeight = Math.round(rescaledHeight);
            if (rescaledHeight !== roundedRescaledHeight) {
                rescaledHeight = roundedRescaledHeight;
                verticalScale = rescaledHeight / locCenterContentSize.height;
            }
        }
        locCenter.setScaleX(horizontalScale);
        locCenter.setScaleY(verticalScale);
        locBottomLeft.setAnchorPoint(1, 1);
        locBottomLeft.setPosition(leftWidth,bottomHeight);
        locBottomRight.setAnchorPoint(0, 1);
        locBottomRight.setPosition(leftWidth+rescaledWidth,bottomHeight);
        locTopLeft.setAnchorPoint(1, 0);
        locTopLeft.setPosition(leftWidth, bottomHeight+rescaledHeight);
        locTopRight.setAnchorPoint(0, 0);
        locTopRight.setPosition(leftWidth+rescaledWidth, bottomHeight+rescaledHeight);
        locLeft.setAnchorPoint(1, 0.5);
        locLeft.setPosition(leftWidth, bottomHeight+rescaledHeight/2 + centerOffset.y);
        locLeft.setScaleY(verticalScale);
        locRight.setAnchorPoint(0, 0.5);
        locRight.setPosition(leftWidth+rescaledWidth,bottomHeight+rescaledHeight/2 + centerOffset.y);
        locRight.setScaleY(verticalScale);
        locTop.setAnchorPoint(0.5, 0);
        locTop.setPosition(leftWidth+rescaledWidth/2 + centerOffset.x,bottomHeight+rescaledHeight);
        locTop.setScaleX(horizontalScale);
        locBottom.setAnchorPoint(0.5, 1);
        locBottom.setPosition(leftWidth+rescaledWidth/2 + centerOffset.x,bottomHeight);
        locBottom.setScaleX(horizontalScale);
        locCenter.setAnchorPoint(0.5, 0.5);
        locCenter.setPosition(leftWidth+rescaledWidth/2 + centerOffset.x, bottomHeight+rescaledHeight/2 + centerOffset.y);
        locCenter.setScaleX(horizontalScale);
        locCenter.setScaleY(verticalScale);
    },
    ctor: function (file, rectOrCapInsets, capInsets) {
        cc.Node.prototype.ctor.call(this);
        this._loader = new cc.Sprite.LoadManager();
        this._spriteRect = cc.rect(0, 0, 0, 0);
        this._capInsetsInternal = cc.rect(0, 0, 0, 0);
        this._originalSize = cc.size(0, 0);
        this._preferredSize = cc.size(0, 0);
        this._capInsets = cc.rect(0, 0, 0, 0);
        this._renderers = [];
        if (file !== undefined) {
            if (file instanceof cc.SpriteFrame)
                this.initWithSpriteFrame(file, rectOrCapInsets);
            else {
                var frame = cc.spriteFrameCache.getSpriteFrame(file);
                if (frame)
                    this.initWithSpriteFrame(frame, rectOrCapInsets);
                else
                    this.initWithFile(file, rectOrCapInsets, capInsets);
            }
        }
        else {
            this.init();
            this.setCascadeColorEnabled(true);
            this.setCascadeOpacityEnabled(true);
            this.setAnchorPoint(0.5, 0.5);
            this._positionsAreDirty = true;
        }
    },
    getSprite: function () {
        return this._scale9Image;
    },
    getOriginalSize: function () {
        return cc.size(this._originalSize);
    },
    getPreferredSize: function () {
        return cc.size(this._preferredSize);
    },
    _getPreferredWidth: function () {
        return this._preferredSize.width;
    },
    _getPreferredHeight: function () {
        return this._preferredSize.height;
    },
    _asyncSetPreferredSize: function () {
        this.removeEventListener('load', this._asyncSetPreferredSize, this);
        this.setPreferredSize(this._cachePreferredSize);
        this._cachePreferredSize = null;
    },
    setPreferredSize: function (preferredSize) {
        if (!preferredSize) return;
        if (!this._textureLoaded) {
            this._cachePreferredSize = preferredSize;
            this.removeEventListener('load', this._asyncSetPreferredSize, this);
            this.addEventListener('load', this._asyncSetPreferredSize, this);
            return false;
        }
        this.setContentSize(preferredSize);
        this._preferredSize = preferredSize;
        if (this._positionsAreDirty) {
            this._updatePositions();
            this._positionsAreDirty = false;
            this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
        }
    },
    _setPreferredWidth: function (value) {
        this._setWidth(value);
        this._preferredSize.width = value;
    },
    _setPreferredHeight: function (value) {
        this._setHeight(value);
        this._preferredSize.height = value;
    },
    setOpacity: function (opacity) {
        cc.Node.prototype.setOpacity.call(this, opacity);
        if(this._scale9Enabled) {
            var pChildren = this._renderers;
            for(var i=0; i<pChildren.length; i++)
                pChildren[i].setOpacity(opacity);
        }
        else if(this._scale9Image)
            this._scale9Image.setOpacity(opacity);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    setColor: function (color) {
        cc.Node.prototype.setColor.call(this, color);
        if(this._scale9Enabled) {
            var scaleChildren = this._renderers;
            for (var i = 0; i < scaleChildren.length; i++) {
                var selChild = scaleChildren[i];
                if (selChild)
                    selChild.setColor(color);
            }
        }
        else if (this._scale9Image)
            this._scale9Image.setColor(color);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    getCapInsets: function () {
        return cc.rect(this._capInsets);
    },
    _asyncSetCapInsets: function () {
        this.removeEventListener('load', this._asyncSetCapInsets, this);
        this.setCapInsets(this._cacheCapInsets);
        this._cacheCapInsets = null;
    },
    setCapInsets: function (capInsets) {
        var contentSize = this._contentSize;
        var tempWidth = contentSize.width, tempHeight = contentSize.height;
        if (!this._textureLoaded) {
            this._cacheCapInsets = capInsets;
            this.removeEventListener('load', this._asyncSetCapInsets, this);
            this.addEventListener('load', this._asyncSetCapInsets, this);
            return false;
        }
        this.updateWithSprite(  this._scale9Image,
                                this._spriteRect,
                                this._spriteFrameRotated,
                                this._offset,
                                this._originalSize,
                                capInsets );
        this._insetLeft = capInsets.x;
        this._insetTop = capInsets.y;
        this._insetRight = this._originalSize.width - this._insetLeft - capInsets.width;
        this._insetBottom = this._originalSize.height - this._insetTop - capInsets.height;
        this.setContentSize(tempWidth, tempHeight);
    },
    getInsetLeft: function () {
        return this._insetLeft;
    },
    setInsetLeft: function (insetLeft) {
        this._insetLeft = insetLeft;
        this._updateCapInset();
    },
    getInsetTop: function () {
        return this._insetTop;
    },
    setInsetTop: function (insetTop) {
        this._insetTop = insetTop;
        this._updateCapInset();
    },
    getInsetRight: function () {
        return this._insetRight;
    },
    setInsetRight: function (insetRight) {
        this._insetRight = insetRight;
        this._updateCapInset();
    },
    getInsetBottom: function () {
        return this._insetBottom;
    },
    setInsetBottom: function (insetBottom) {
        this._insetBottom = insetBottom;
        this._updateCapInset();
    },
    setContentSize: function (size, height) {
        cc.Node.prototype.setContentSize.call(this, size, height);
        this._positionsAreDirty = true;
    },
    setAnchorPoint: function (point, y) {
        cc.Node.prototype.setAnchorPoint.call(this, point, y);
        if(!this._scale9Enabled) {
            if(this._scale9Image) {
                this._scale9Image.setAnchorPoint(point, y);
                this._positionsAreDirty = true;
            }
        }
    },
    _setWidth: function (value) {
        cc.Node.prototype._setWidth.call(this, value);
        this._positionsAreDirty = true;
    },
    _setHeight: function (value) {
        cc.Node.prototype._setHeight.call(this, value);
        this._positionsAreDirty = true;
    },
    init: function () {
        return this.initWithBatchNode(null, cc.rect(0, 0, 0, 0), false, cc.rect(0, 0, 0, 0));
    },
    initWithBatchNode: function (batchNode, rect, rotated, capInsets) {
        if (!batchNode)
            return false;
        if (capInsets === undefined) {
            capInsets = rotated;
            rotated = false;
        }
        this.updateWithBatchNode(batchNode, rect, rotated, capInsets);
        this.setCascadeColorEnabled(true);
        this.setCascadeOpacityEnabled(true);
        this.setAnchorPoint(0.5, 0.5);
        this._positionsAreDirty = true;
        return true;
    },
    initWithFile: function (file, rect, capInsets) {
        if (file instanceof cc.Rect) {
            file = arguments[1];
            capInsets = arguments[0];
            rect = cc.rect(0, 0, 0, 0);
        } else {
            rect = rect || cc.rect(0, 0, 0, 0);
            capInsets = capInsets || cc.rect(0, 0, 0, 0);
        }
        if(!file)
            throw new Error("ccui.Scale9Sprite.initWithFile(): file should be non-null");
        var texture = cc.textureCache.getTextureForKey(file);
        if (!texture) {
            texture = cc.textureCache.addImage(file);
        }
        var locLoaded = texture.isLoaded();
        this._textureLoaded = locLoaded;
        this._loader.clear();
        if (!locLoaded) {
            this._loader.once(texture, function () {
                this.initWithFile(file, rect, capInsets);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        return this.initWithBatchNode(new cc.SpriteBatchNode(file, 9), rect, false, capInsets);
    },
    initWithSpriteFrame: function (spriteFrame, capInsets) {
        if(!spriteFrame || !spriteFrame.getTexture())
            throw new Error("ccui.Scale9Sprite.initWithSpriteFrame(): spriteFrame should be non-null and its texture should be non-null");
        capInsets = capInsets || cc.rect(0, 0, 0, 0);
        var texture = spriteFrame.getTexture();
        var loaded = this._textureLoaded = texture.isLoaded();
        this._loader.clear();
        if (!loaded) {
            this._loader.once(texture, function () {
                this.initWithSpriteFrame(spriteFrame, capInsets);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        var batchNode = new cc.SpriteBatchNode(spriteFrame.getTexture(), 9);
        this.initWithBatchNode(batchNode, spriteFrame.getRect(), cc._renderType === cc.game.RENDER_TYPE_WEBGL && spriteFrame.isRotated(), capInsets);
        return true;
    },
    initWithSpriteFrameName: function (spriteFrameName, capInsets) {
        if(!spriteFrameName)
            throw new Error("ccui.Scale9Sprite.initWithSpriteFrameName(): spriteFrameName should be non-null");
        capInsets = capInsets || cc.rect(0, 0, 0, 0);
        var frame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
        if (frame == null) {
            cc.log("ccui.Scale9Sprite.initWithSpriteFrameName(): can't find the sprite frame by spriteFrameName");
            return false;
        }
        return this.initWithSpriteFrame(frame, capInsets);
    },
    resizableSpriteWithCapInsets: function (capInsets) {
        var pReturn = new ccui.Scale9Sprite();
        if (pReturn && pReturn.initWithBatchNode(this._scale9Image, this._spriteRect, false, capInsets))
            return pReturn;
        return null;
    },
    setOpacityModifyRGB: function (value) {
        if(!this._scale9Image)
            return;
        this._opacityModifyRGB = value;
        var scaleChildren = this._scale9Image.getChildren();
        if (scaleChildren) {
            for (var i = 0, len = scaleChildren.length; i < len; i++)
                scaleChildren[i].setOpacityModifyRGB(value);
        }
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    isOpacityModifyRGB: function () {
        return this._opacityModifyRGB;
    },
    createSlicedSprites: function() {
        var width = this._originalSize.width,
            height = this._originalSize.height;
        var originalRect = this._spriteRect;
        var offsetX = Math.floor(this._offset.x + (width - originalRect.width) / 2.0);
        var offsetY = Math.floor(this._offset.y + (height - originalRect.height) / 2.0);
        var sx = originalRect.x,
            sy = originalRect.y;
        var capInsetsInternal = this._capInsetsInternal;
        var locScale9Image = this._scale9Image;
        var selTexture = locScale9Image.getTexture();
        var rotated = this._spriteFrameRotated;
        var rect = cc.rect(originalRect.x, originalRect.y, originalRect.width, originalRect.height);
        if(cc._rectEqualToZero(capInsetsInternal))
            capInsetsInternal = cc.rect(width /3, height /3, width /3, height /3);
        if(this._spriteFrameRotated) {
            sx -= offsetY;  sy -= offsetX;
        }else{
            sx -= offsetX;  sy -= offsetY;
        }
        originalRect = cc.rect(sx, sy, width, height);
        var leftWidth = capInsetsInternal.x,
            centerWidth = capInsetsInternal.width,
            rightWidth = originalRect.width - (leftWidth + centerWidth),
            topHeight = capInsetsInternal.y,
            centerHeight = capInsetsInternal.height,
            bottomHeight = originalRect.height - (topHeight + centerHeight);
        var x = 0.0, y = 0.0;
        var leftTopBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, leftWidth + 0.5 | 0, topHeight + 0.5 | 0);
        var leftTopBounds = leftTopBoundsOriginal;
        x += leftWidth;
        var centerTopBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, centerWidth + 0.5 | 0, topHeight + 0.5 | 0);
        var centerTopBounds = centerTopBoundsOriginal;
        x += centerWidth;
        var  rightTopBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, rightWidth + 0.5 | 0, topHeight + 0.5 | 0);
        var  rightTopBounds = rightTopBoundsOriginal;
        x = 0.0;
        y = 0.0;
        y += topHeight;
        var leftCenterBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, leftWidth + 0.5 | 0, centerHeight + 0.5 | 0);
        x += leftWidth;
        var centerBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, centerWidth + 0.5 | 0, centerHeight + 0.5 | 0);
        var centerBounds = centerBoundsOriginal;
        x += centerWidth;
        var rightCenterBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, rightWidth + 0.5 | 0, centerHeight + 0.5 | 0);
        x = 0.0;
        y = 0.0;
        y += topHeight;
        y += centerHeight;
        var leftBottomBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, leftWidth + 0.5 | 0, bottomHeight + 0.5 | 0);
        x += leftWidth;
        var centerBottomBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, centerWidth + 0.5 | 0, bottomHeight + 0.5 | 0);
        x += centerWidth;
        var rightBottomBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, rightWidth + 0.5 | 0, bottomHeight + 0.5 | 0);
        var rightBottomBounds = rightBottomBoundsOriginal;
        var rotatedLeftTopBoundsOriginal = leftTopBoundsOriginal;
        var rotatedCenterBoundsOriginal = centerBoundsOriginal;
        var rotatedRightBottomBoundsOriginal = rightBottomBoundsOriginal;
        var rotatedCenterBounds = centerBounds;
        var rotatedRightBottomBounds = rightBottomBounds;
        var rotatedLeftBottomBounds = leftBottomBounds;
        var rotatedRightTopBounds = rightTopBounds;
        var rotatedLeftTopBounds = leftTopBounds;
        var rotatedRightCenterBounds = rightCenterBounds;
        var rotatedLeftCenterBounds = leftCenterBounds;
        var rotatedCenterBottomBounds = centerBottomBounds;
        var rotatedCenterTopBounds = centerTopBounds;
        var t = cc.affineTransformMakeIdentity();
        if (!rotated) {
            t = cc.affineTransformTranslate(t, rect.x, rect.y);
            rotatedLeftTopBoundsOriginal = cc.rectApplyAffineTransform(rotatedLeftTopBoundsOriginal, t);
            rotatedCenterBoundsOriginal = cc.rectApplyAffineTransform(rotatedCenterBoundsOriginal, t);
            rotatedRightBottomBoundsOriginal = cc.rectApplyAffineTransform(rotatedRightBottomBoundsOriginal, t);
            rotatedCenterBounds = cc.rectApplyAffineTransform(rotatedCenterBounds, t);
            rotatedRightBottomBounds = cc.rectApplyAffineTransform(rotatedRightBottomBounds, t);
            rotatedLeftBottomBounds = cc.rectApplyAffineTransform(rotatedLeftBottomBounds, t);
            rotatedRightTopBounds = cc.rectApplyAffineTransform(rotatedRightTopBounds, t);
            rotatedLeftTopBounds = cc.rectApplyAffineTransform(rotatedLeftTopBounds, t);
            rotatedRightCenterBounds = cc.rectApplyAffineTransform(rotatedRightCenterBounds, t);
            rotatedLeftCenterBounds = cc.rectApplyAffineTransform(rotatedLeftCenterBounds, t);
            rotatedCenterBottomBounds = cc.rectApplyAffineTransform(rotatedCenterBottomBounds, t);
            rotatedCenterTopBounds = cc.rectApplyAffineTransform(rotatedCenterTopBounds, t);
        } else {
            t = cc.affineTransformTranslate(t, rect.height + rect.x, rect.y);
            t = cc.affineTransformRotate(t, 1.57079633);
            leftTopBoundsOriginal = cc.rectApplyAffineTransform(leftTopBoundsOriginal, t);
            centerBoundsOriginal = cc.rectApplyAffineTransform(centerBoundsOriginal, t);
            rightBottomBoundsOriginal = cc.rectApplyAffineTransform(rightBottomBoundsOriginal, t);
            centerBounds = cc.rectApplyAffineTransform(centerBounds, t);
            rightBottomBounds = cc.rectApplyAffineTransform(rightBottomBounds, t);
            leftBottomBounds = cc.rectApplyAffineTransform(leftBottomBounds, t);
            rightTopBounds = cc.rectApplyAffineTransform(rightTopBounds, t);
            leftTopBounds = cc.rectApplyAffineTransform(leftTopBounds, t);
            rightCenterBounds = cc.rectApplyAffineTransform(rightCenterBounds, t);
            leftCenterBounds = cc.rectApplyAffineTransform(leftCenterBounds, t);
            centerBottomBounds = cc.rectApplyAffineTransform(centerBottomBounds, t);
            centerTopBounds = cc.rectApplyAffineTransform(centerTopBounds, t);
            rotatedLeftTopBoundsOriginal.x = leftTopBoundsOriginal.x;
            rotatedCenterBoundsOriginal.x = centerBoundsOriginal.x;
            rotatedRightBottomBoundsOriginal.x = rightBottomBoundsOriginal.x;
            rotatedCenterBounds.x = centerBounds.x;
            rotatedRightBottomBounds.x = rightBottomBounds.x;
            rotatedLeftBottomBounds.x = leftBottomBounds.x;
            rotatedRightTopBounds.x = rightTopBounds.x;
            rotatedLeftTopBounds.x = leftTopBounds.x;
            rotatedRightCenterBounds.x = rightCenterBounds.x;
            rotatedLeftCenterBounds.x = leftCenterBounds.x;
            rotatedCenterBottomBounds.x = centerBottomBounds.x;
            rotatedCenterTopBounds.x = centerTopBounds.x;
            rotatedLeftTopBoundsOriginal.y = leftTopBoundsOriginal.y;
            rotatedCenterBoundsOriginal.y = centerBoundsOriginal.y;
            rotatedRightBottomBoundsOriginal.y = rightBottomBoundsOriginal.y;
            rotatedCenterBounds.y = centerBounds.y;
            rotatedRightBottomBounds.y = rightBottomBounds.y;
            rotatedLeftBottomBounds.y = leftBottomBounds.y;
            rotatedRightTopBounds.y = rightTopBounds.y;
            rotatedLeftTopBounds.y = leftTopBounds.y;
            rotatedRightCenterBounds.y = rightCenterBounds.y;
            rotatedLeftCenterBounds.y = leftCenterBounds.y;
            rotatedCenterBottomBounds.y = centerBottomBounds.y;
            rotatedCenterTopBounds.y = centerTopBounds.y;
        }
        if(!this._centre)
            this._centre = new cc.Sprite();
        this._centre.initWithTexture(selTexture, rotatedCenterBounds, rotated);
        if(rotatedCenterBounds.width > 0 && rotatedCenterBounds.height > 0 )
            this._renderers.push(this._centre);
        if(!this._top)
            this._top = new cc.Sprite();
        this._top.initWithTexture(selTexture, rotatedCenterTopBounds, rotated);
        if(rotatedCenterTopBounds.width > 0 && rotatedCenterTopBounds.height > 0 )
            this._renderers.push(this._top);
        if(!this._bottom)
            this._bottom = new cc.Sprite();
        this._bottom.initWithTexture(selTexture, rotatedCenterBottomBounds, rotated);
        if(rotatedCenterBottomBounds.width > 0 && rotatedCenterBottomBounds.height > 0 )
            this._renderers.push(this._bottom);
        if(!this._left)
            this._left = new cc.Sprite();
        this._left.initWithTexture(selTexture, rotatedLeftCenterBounds, rotated);
        if(rotatedLeftCenterBounds.width > 0 && rotatedLeftCenterBounds.height > 0 )
            this._renderers.push(this._left);
        if(!this._right)
            this._right = new cc.Sprite();
        this._right.initWithTexture(selTexture, rotatedRightCenterBounds, rotated);
        if(rotatedRightCenterBounds.width > 0 && rotatedRightCenterBounds.height > 0 )
            this._renderers.push(this._right);
        if(!this._topLeft)
            this._topLeft = new cc.Sprite();
        this._topLeft.initWithTexture(selTexture, rotatedLeftTopBounds, rotated);
        if(rotatedLeftTopBounds.width > 0 && rotatedLeftTopBounds.height > 0 )
            this._renderers.push(this._topLeft);
        if(!this._topRight)
            this._topRight = new cc.Sprite();
        this._topRight.initWithTexture(selTexture, rotatedRightTopBounds, rotated);
        if(rotatedRightTopBounds.width > 0 && rotatedRightTopBounds.height > 0 )
            this._renderers.push(this._topRight);
        if(!this._bottomLeft)
            this._bottomLeft = new cc.Sprite();
        this._bottomLeft.initWithTexture(selTexture, rotatedLeftBottomBounds, rotated);
        if(rotatedLeftBottomBounds.width > 0 && rotatedLeftBottomBounds.height > 0 )
            this._renderers.push(this._bottomLeft);
        if(!this._bottomRight)
            this._bottomRight = new cc.Sprite();
        this._bottomRight.initWithTexture(selTexture, rotatedRightBottomBounds, rotated);
        if(rotatedRightBottomBounds.width > 0 && rotatedRightBottomBounds.height > 0 )
            this._renderers.push(this._bottomRight);
    },
    updateWithSprite: function(sprite, spriteRect, spriteFrameRotated, offset, originalSize, capInsets) {
        if (!sprite) return false;
        this._loader.clear();
        this._textureLoaded = sprite._textureLoaded;
        if (!sprite._textureLoaded) {
            this._loader.once(sprite, function () {
                this.updateWithSprite(sprite, spriteRect, spriteFrameRotated, offset, originalSize, capInsets);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        this._scale9Image = sprite;
        if(!this._scale9Image)  return false;
        var tmpTexture = this._scale9Image.getTexture();
        this._textureLoaded = tmpTexture && tmpTexture.isLoaded();
        var spriteFrame = sprite.getSpriteFrame();
        if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
            if (spriteFrame && tmpTexture._htmlElementObj instanceof window.HTMLCanvasElement) {
                spriteFrameRotated = false;
                spriteRect = { x: 0, y: 0, height: spriteRect.height, width: spriteRect.width }
            }
        }
        var opacity = this.getOpacity();
        var color = this.getColor();
        this._renderers.length = 0;
        var rect = spriteRect;
        var size = originalSize;
        if(cc._rectEqualToZero(rect)) {
            var textureSize = tmpTexture.getContentSize();
            rect = cc.rect(0, 0, textureSize.width, textureSize.height);
        }
        if(size.width === 0 && size.height === 0)
            size = cc.size(rect.width, rect.height);
        this._capInsets = capInsets;
        this._spriteRect = rect;
        this._offset = offset;
        this._spriteFrameRotated = spriteFrameRotated;
        this._originalSize = size;
        this._preferredSize = size;
        this._capInsetsInternal = capInsets;
        if(this._scale9Enabled)
            this.createSlicedSprites();
        else
            this._scale9Image.initWithTexture(tmpTexture, this._spriteRect, this._spriteFrameRotated);
        this.setState(this._brightState);
        this.setContentSize(size);
        this.setOpacity(opacity);
        this.setColor(color);
        return true;
    },
    updateWithBatchNode: function (batchNode, originalRect, rotated, capInsets) {
        if (!batchNode) {
            return false;
        }
        var texture = batchNode.getTexture();
        this._loader.clear();
        var loaded = this._textureLoaded = texture.isLoaded();
        if (!loaded) {
            this._loader.once(texture, function () {
                this.updateWithBatchNode(batchNode, originalRect, rotated, capInsets);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        var sprite = new cc.Sprite(texture);
        var pos = cc.p(0,0);
        var originalSize = cc.size(originalRect.width,originalRect.height);
        return this.updateWithSprite(sprite, originalRect, rotated, pos, originalSize, capInsets);
    },
    setSpriteFrame: function (spriteFrame, capInsets) {
        capInsets = capInsets || cc.rect();
        var texture = spriteFrame.getTexture();
        this._textureLoaded = texture._textureLoaded;
        this._loader.clear();
        if (!texture._textureLoaded) {
            this._loader.once(spriteFrame, function () {
                this.setSpriteFrame(spriteFrame, capInsets);
                this.dispatchEvent("load");
            }, this);
            return false;
        }
        var sprite = new cc.Sprite(spriteFrame.getTexture());
        this.updateWithSprite(sprite, spriteFrame.getRect(),spriteFrame.isRotated(),spriteFrame.getOffset(),spriteFrame.getOriginalSize(),capInsets);
        this._insetLeft = capInsets.x;
        this._insetTop = capInsets.y;
        this._insetRight = this._originalSize.width - this._insetLeft - capInsets.width;
        this._insetBottom = this._originalSize.height - this._insetTop - capInsets.height;
    },
    setState: function (state) {
        if (state === ccui.Scale9Sprite.state.NORMAL || state === ccui.Scale9Sprite.state.GRAY) {
            this._brightState = state;
            this._renderCmd.setState(state);
        }
    },
    setScale9Enabled: function (enabled) {
        if (this._scale9Enabled === enabled)
        {
            return;
        }
        this._scale9Enabled = enabled;
        this._renderers.length = 0;
        cc.Node.transformDirty = true;
        if (this._scale9Enabled) {
            if (this._scale9Image) {
                this.updateWithSprite(this._scale9Image,
                    this._spriteRect,
                    this._spriteFrameRotated,
                    this._offset,
                    this._originalSize,
                    this._capInsets);
            }
        }
        this._positionsAreDirty = true;
    },
    _setRenderersPosition: function() {
        if(this._positionsAreDirty) {
            this._updatePositions();
            this._adjustScale9ImagePosition();
            this._positionsAreDirty = false;
        }
    },
    _adjustScale9ImagePosition: function() {
        var image = this._scale9Image;
        var contentSize = this._contentSize;
        if(image) {
            image.x = contentSize.width * image.getAnchorPoint().x;
            image.y = contentSize.height * image.getAnchorPoint().y;
        }
    },
    _adjustScale9ImageScale: function() {
        var image = this._scale9Image;
        var contentSize = this._contentSize;
        if(image) {
            image.setScale(contentSize.width/image.width, contentSize.height/image.height);
        }
    },
    setFlippedX: function(flippedX){
        var realScale = this.getScaleX();
        this._flippedX = flippedX;
        this.setScaleX(realScale);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    isFlippedX: function(){
        return this._flippedX;
    },
    setFlippedY:function(flippedY){
        var realScale = this.getScaleY();
        this._flippedY = flippedY;
        this.setScaleY(realScale);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    isFlippedY:function(){
        return this._flippedY;
    },
    setScaleX: function (scaleX) {
        if (this._flippedX)
            scaleX = scaleX * -1;
        cc.Node.prototype.setScaleX.call(this, scaleX);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    setScaleY: function (scaleY) {
        if (this._flippedY)
            scaleY = scaleY * -1;
        cc.Node.prototype.setScaleY.call(this, scaleY);
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    },
    setScale: function (scaleX, scaleY) {
        if(scaleY === undefined)
            scaleY = scaleX;
        this.setScaleX(scaleX);
        this.setScaleY(scaleY);
    },
    getScaleX: function () {
        var originalScale = cc.Node.prototype.getScaleX.call(this);
        if (this._flippedX)
            originalScale = originalScale * -1.0;
        return originalScale;
    },
    getScaleY: function () {
        var originalScale = cc.Node.prototype.getScaleY.call(this);
        if (this._flippedY)
            originalScale = originalScale * -1.0;
        return originalScale;
    },
    getScale: function () {
        if(this.getScaleX() !== this.getScaleY())
            cc.log("Scale9Sprite#scale. ScaleX != ScaleY. Don't know which one to return");
        return this.getScaleX();
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new ccui.Scale9Sprite.CanvasRenderCmd(this);
        else
            return new ccui.Scale9Sprite.WebGLRenderCmd(this);
    }
});
var _p = ccui.Scale9Sprite.prototype;
cc.EventHelper.prototype.apply(_p);
_p.preferredSize;
cc.defineGetterSetter(_p, "preferredSize", _p.getPreferredSize, _p.setPreferredSize);
_p.capInsets;
cc.defineGetterSetter(_p, "capInsets", _p.getCapInsets, _p.setCapInsets);
_p.insetLeft;
cc.defineGetterSetter(_p, "insetLeft", _p.getInsetLeft, _p.setInsetLeft);
_p.insetTop;
cc.defineGetterSetter(_p, "insetTop", _p.getInsetTop, _p.setInsetTop);
_p.insetRight;
cc.defineGetterSetter(_p, "insetRight", _p.getInsetRight, _p.setInsetRight);
_p.insetBottom;
cc.defineGetterSetter(_p, "insetBottom", _p.getInsetBottom, _p.setInsetBottom);
_p = null;
ccui.Scale9Sprite.create = function (file, rect, capInsets) {
    return new ccui.Scale9Sprite(file, rect, capInsets);
};
ccui.Scale9Sprite.createWithSpriteFrame = function (spriteFrame, capInsets) {
    return new ccui.Scale9Sprite(spriteFrame, capInsets);
};
ccui.Scale9Sprite.createWithSpriteFrameName = function (spriteFrameName, capInsets) {
    return new ccui.Scale9Sprite(spriteFrameName, capInsets);
};
ccui.Scale9Sprite.POSITIONS_CENTRE = 0;
ccui.Scale9Sprite.POSITIONS_TOP = 1;
ccui.Scale9Sprite.POSITIONS_LEFT = 2;
ccui.Scale9Sprite.POSITIONS_RIGHT = 3;
ccui.Scale9Sprite.POSITIONS_BOTTOM = 4;
ccui.Scale9Sprite.POSITIONS_TOPRIGHT = 5;
ccui.Scale9Sprite.POSITIONS_TOPLEFT = 6;
ccui.Scale9Sprite.POSITIONS_BOTTOMRIGHT = 7;
ccui.Scale9Sprite.state = {NORMAL: 0, GRAY: 1};
(function() {
    ccui.Scale9Sprite.CanvasRenderCmd = function (renderable) {
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._cachedParent = null;
        this._cacheDirty = false;
        this._state = ccui.Scale9Sprite.state.NORMAL;
        var node = this._node;
        var locCacheCanvas = this._cacheCanvas = document.createElement('canvas');
        locCacheCanvas.width = 1;
        locCacheCanvas.height = 1;
        this._cacheContext = new cc.CanvasContextWrapper(locCacheCanvas.getContext("2d"));
        var locTexture = this._cacheTexture = new cc.Texture2D();
        locTexture.initWithElement(locCacheCanvas);
        locTexture.handleLoadedTexture();
        this._cacheSprite = new cc.Sprite(locTexture);
        this._cacheSprite.setAnchorPoint(0,0);
        node.addChild(this._cacheSprite);
    };
    var proto = ccui.Scale9Sprite.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    proto.constructor = ccui.Scale9Sprite.CanvasRenderCmd;
    proto.visit = function(parentCmd){
        var node = this._node;
        if(!node._visible)
            return;
        if (node._positionsAreDirty) {
            node._updatePositions();
            node._positionsAreDirty = false;
        }
        this.originVisit(parentCmd);
    };
    proto.transform = function(parentCmd){
        var node = this._node;
        cc.Node.CanvasRenderCmd.prototype.transform.call(this, parentCmd);
        if (node._positionsAreDirty) {
            node._updatePositions();
            node._positionsAreDirty = false;
        }
        var children = node._children;
        for(var i=0; i<children.length; i++){
            children[i].transform(this, true);
        }
    };
    proto._updateDisplayColor = function(parentColor){
        cc.Node.CanvasRenderCmd.prototype._updateDisplayColor.call(this, parentColor);
        var node = this._node;
        if(!node)   return;
        var locRenderers = node._renderers;
        if(node._scale9Enabled) {
            var protectChildLen = locRenderers.length;
            for(var j=0 ; j < protectChildLen; j++) {
                var renderer = locRenderers[j];
                if(renderer) {
                    renderer._renderCmd._updateDisplayColor(parentColor);
                    renderer._renderCmd._updateColor();
                }
                else
                    break;
            }
        }
        else {
            if (node._scale9Image) {
                node._scale9Image._renderCmd._updateDisplayColor(parentColor);
                node._scale9Image._renderCmd._updateColor();
            }
        }
    };
    proto.updateStatus = function () {
        var flags = cc.Node._dirtyFlags,
            locFlag = this._dirtyFlag;
        cc.Node.RenderCmd.prototype.updateStatus.call(this);
        if (locFlag & flags.cacheDirty) {
            this._cacheScale9Sprite();
            this._dirtyFlag = this._dirtyFlag & flags.cacheDirty ^ this._dirtyFlag;
        }
    };
    proto._syncStatus = function (parentCmd) {
        var flags = cc.Node._dirtyFlags,
            locFlag = this._dirtyFlag;
        cc.Node.RenderCmd.prototype._syncStatus.call(this, parentCmd);
        if (locFlag & flags.cacheDirty) {
            this._cacheScale9Sprite();
            this._dirtyFlag = this._dirtyFlag & flags.cacheDirty ^ this._dirtyFlag;
        }
    };
    proto._cacheScale9Sprite = function() {
        var node = this._node;
        if(!node._scale9Image)
            return;
        var locScaleFactor = cc.contentScaleFactor();
        var size = node._contentSize;
        var sizeInPixels = cc.size(size.width * locScaleFactor, size.height * locScaleFactor);
        var locCanvas = this._cacheCanvas, wrapper = this._cacheContext, locContext = wrapper.getContext();
        var contentSizeChanged = false;
        if(locCanvas.width !== sizeInPixels.width || locCanvas.height !== sizeInPixels.height){
            locCanvas.width = sizeInPixels.width;
            locCanvas.height = sizeInPixels.height;
            contentSizeChanged = true;
        }
        cc.renderer._turnToCacheMode(node.__instanceId);
        if(node._scale9Enabled) {
            var locRenderers = node._renderers;
            node._setRenderersPosition();
            var protectChildLen = locRenderers.length;
            for(var j=0; j < protectChildLen; j++) {
                var renderer = locRenderers[j];
                if(renderer) {
                    var tempCmd = renderer._renderCmd;
                    tempCmd.updateStatus();
                    cc.renderer.pushRenderCommand(tempCmd);
                }
                else
                    break;
            }
        }
        else {
            var tempCmd = node._scale9Image._renderCmd;
            node._adjustScale9ImagePosition();
            node._adjustScale9ImageScale();
            tempCmd.updateStatus();
            cc.renderer.pushRenderCommand(node._scale9Image._renderCmd);
        }
        var selTexture = node._scale9Image.getTexture();
        if(selTexture && this._state === ccui.Scale9Sprite.state.GRAY)
            selTexture._switchToGray(true);
        locContext.setTransform(1, 0, 0, 1, 0, 0);
        locContext.clearRect(0, 0, sizeInPixels.width, sizeInPixels.height);
        cc.renderer._renderingToCacheCanvas(wrapper, node.__instanceId, locScaleFactor, locScaleFactor);
        cc.renderer._turnToNormalMode();
        if(selTexture && this._state === ccui.Scale9Sprite.state.GRAY)
            selTexture._switchToGray(false);
        if(contentSizeChanged)
            this._cacheSprite.setTextureRect(cc.rect(0,0, size.width, size.height));
        if(!this._cacheSprite.getParent())
            node.addChild(this._cacheSprite, -1);
        this._cacheSprite._renderCmd._updateColor();
    };
    proto.setState = function(state){
        var locScale9Image = this._node._scale9Image;
        if(!locScale9Image)
            return;
        this._state = state;
        this.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
    };
})();
(function() {
    if(!cc.Node.WebGLRenderCmd)
        return;
    ccui.Scale9Sprite.WebGLRenderCmd = function (renderable) {
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._cachedParent = null;
        this._cacheDirty = false;
    };
    var proto = ccui.Scale9Sprite.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    proto.constructor = ccui.Scale9Sprite.WebGLRenderCmd;
    proto.setShaderProgram = function (shaderProgram) {
        var node = this._node;
        if (node._scale9Enabled) {
            var renderers = node._renderers, l = renderers.length;
            for (var i = 0; i < l; i++) {
                if (renderers[i]) {
                    renderers[i]._renderCmd._shaderProgram = shaderProgram;
                }
            }
        }
        else {
            node._scale9Image._renderCmd._shaderProgram = shaderProgram;
        }
        this._shaderProgram = shaderProgram;
    };
    proto.visit = function(parentCmd) {
        var node = this._node;
        if (!node._visible)
            return;
        if (!node._scale9Image)
            return;
        if (node._positionsAreDirty) {
            node._updatePositions();
            node._positionsAreDirty = false;
        }
        parentCmd = parentCmd || this.getParentRenderCmd();
        if (node._parent && node._parent._renderCmd)
            this._curLevel = node._parent._renderCmd._curLevel + 1;
        this._syncStatus(parentCmd);
        if (node._scale9Enabled) {
            var locRenderers = node._renderers;
            var rendererLen = locRenderers.length;
            for (var j=0; j < rendererLen; j++) {
                var renderer = locRenderers[j];
                if (renderer) {
                    var tempCmd = renderer._renderCmd;
                    tempCmd.visit(this);
                }
                else
                    break;
            }
        }
        else {
            node._adjustScale9ImageScale();
            node._adjustScale9ImagePosition();
            node._scale9Image._renderCmd.visit(this);
        }
        this._dirtyFlag = 0;
        this.originVisit(parentCmd);
    };
    proto.transform = function(parentCmd, recursive){
        var node = this._node;
        parentCmd = parentCmd || this.getParentRenderCmd();
        this.originTransform(parentCmd, recursive);
        if (node._positionsAreDirty) {
            node._updatePositions();
            node._positionsAreDirty = false;
        }
        if(node._scale9Enabled) {
            var locRenderers = node._renderers;
            var protectChildLen = locRenderers.length;
            var flags = cc.Node._dirtyFlags;
            for(var j=0; j < protectChildLen; j++) {
                var pchild = locRenderers[j];
                if(pchild) {
                    pchild._vertexZ = parentCmd._node._vertexZ;
                    var tempCmd = pchild._renderCmd;
                    tempCmd.transform(this, true);
                    tempCmd._dirtyFlag = tempCmd._dirtyFlag & flags.transformDirty ^ tempCmd._dirtyFlag;
                }
                else {
                    break;
                }
            }
        }
        else {
            node._adjustScale9ImageScale();
            node._adjustScale9ImagePosition();
            node._scale9Image._renderCmd.transform(this, true);
        }
    };
    proto.setDirtyFlag = function (dirtyFlag, child) {
        if (dirtyFlag === cc.Node._dirtyFlags.cacheDirty)
            dirtyFlag = cc.Node._dirtyFlags.transformDirty;
        cc.Node.RenderCmd.prototype.setDirtyFlag.call(this, dirtyFlag, child);
    };
    proto._syncStatus = function (parentCmd){
        cc.Node.WebGLRenderCmd.prototype._syncStatus.call(this, parentCmd);
        this._updateDisplayColor(this._displayedColor);
        this._updateDisplayOpacity(this._displayedOpacity);
    };
    proto._updateDisplayColor = function(parentColor){
        cc.Node.WebGLRenderCmd.prototype._updateDisplayColor.call(this, parentColor);
        var node = this._node;
        var scale9Image = node._scale9Image;
        parentColor = this._displayedColor;
        if(node._scale9Enabled) {
            var pChildren = node._renderers;
            for(var i=0; i<pChildren.length; i++) {
                pChildren[i]._renderCmd._updateDisplayColor(parentColor);
                pChildren[i]._renderCmd._updateColor();
            }
        }
        else {
            scale9Image._renderCmd._updateDisplayColor(parentColor);
            scale9Image._renderCmd._updateColor();
        }
    };
    proto._updateDisplayOpacity = function(parentOpacity){
        cc.Node.WebGLRenderCmd.prototype._updateDisplayOpacity.call(this, parentOpacity);
        var node = this._node;
        var scale9Image = node._scale9Image;
        parentOpacity = this._displayedOpacity;
        if(node._scale9Enabled) {
            var pChildren = node._renderers;
            for(var i=0; i<pChildren.length; i++)
            {
                pChildren[i]._renderCmd._updateDisplayOpacity(parentOpacity);
                pChildren[i]._renderCmd._updateColor();
            }
        }
        else
        {
            scale9Image._renderCmd._updateDisplayOpacity(parentOpacity);
            scale9Image._renderCmd._updateColor();
        }
    };
    proto.setState = function (state) {
        if (state === ccui.Scale9Sprite.state.NORMAL) {
            this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR));
        }
        else if (state === ccui.Scale9Sprite.state.GRAY) {
            this.setShaderProgram(ccui.Scale9Sprite.WebGLRenderCmd._getGrayShaderProgram());
        }
    };
    ccui.Scale9Sprite.WebGLRenderCmd._grayShaderProgram = null;
    ccui.Scale9Sprite.WebGLRenderCmd._getGrayShaderProgram = function(){
        var grayShader = ccui.Scale9Sprite.WebGLRenderCmd._grayShaderProgram;
        if(grayShader)
            return grayShader;
        grayShader = new cc.GLProgram();
        grayShader.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT, ccui.Scale9Sprite.WebGLRenderCmd._grayShaderFragment);
        grayShader.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
        grayShader.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
        grayShader.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
        grayShader.link();
        grayShader.updateUniforms();
        ccui.Scale9Sprite.WebGLRenderCmd._grayShaderProgram = grayShader;
        return grayShader;
    };
    ccui.Scale9Sprite.WebGLRenderCmd._grayShaderFragment =
        "precision lowp float;\n"
        + "varying vec4 v_fragmentColor; \n"
        + "varying vec2 v_texCoord; \n"
        + "void main() \n"
        + "{ \n"
        + "    vec4 c = texture2D(CC_Texture0, v_texCoord); \n"
        + "    gl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b); \n"
        +"     gl_FragColor.w = c.w ; \n"
        + "}";
})();
ccui.Layout = ccui.Widget.extend({
    _clippingEnabled: false,
    _backGroundScale9Enabled: null,
    _backGroundImage: null,
    _backGroundImageFileName: null,
    _backGroundImageCapInsets: null,
    _colorType: null,
    _bgImageTexType: ccui.Widget.LOCAL_TEXTURE,
    _colorRender: null,
    _gradientRender: null,
    _color: null,
    _startColor: null,
    _endColor: null,
    _alongVector: null,
    _opacity: 255,
    _backGroundImageTextureSize: null,
    _layoutType: null,
    _doLayoutDirty: true,
    _clippingRectDirty: true,
    _clippingType: null,
    _clippingStencil: null,
    _scissorRectDirty: false,
    _clippingRect: null,
    _clippingParent: null,
    _className: "Layout",
    _backGroundImageColor: null,
    _finalPositionX: 0,
    _finalPositionY: 0,
    _backGroundImageOpacity:0,
    _loopFocus: false,
    __passFocusToChild: true,
    _isFocusPassing:false,
    _isInterceptTouch: false,
    ctor: function () {
        this._layoutType = ccui.Layout.ABSOLUTE;
        this._widgetType = ccui.Widget.TYPE_CONTAINER;
        this._clippingType = ccui.Layout.CLIPPING_SCISSOR;
        this._colorType = ccui.Layout.BG_COLOR_NONE;
        ccui.Widget.prototype.ctor.call(this);
        this.ignoreContentAdaptWithSize(false);
        this.setContentSize(cc.size(0, 0));
        this.setAnchorPoint(0, 0);
        this.onPassFocusToChild  = this._findNearestChildWidgetIndex.bind(this);
        this._backGroundImageCapInsets = cc.rect(0, 0, 0, 0);
        this._color = cc.color(255, 255, 255, 255);
        this._startColor = cc.color(255, 255, 255, 255);
        this._endColor = cc.color(255, 255, 255, 255);
        this._alongVector = cc.p(0, -1);
        this._backGroundImageTextureSize = cc.size(0, 0);
        this._clippingRect = cc.rect(0, 0, 0, 0);
        this._backGroundImageColor = cc.color(255, 255, 255, 255);
    },
    onEnter: function(){
        ccui.Widget.prototype.onEnter.call(this);
        if (this._clippingStencil)
            this._clippingStencil.onEnter();
        this._doLayoutDirty = true;
        this._clippingRectDirty = true;
    },
    onExit: function(){
        ccui.Widget.prototype.onExit.call(this);
        if (this._clippingStencil)
            this._clippingStencil.onExit();
    },
    setLoopFocus: function(loop){
        this._loopFocus = loop;
    },
    isLoopFocus: function(){
        return this._loopFocus;
    },
    setPassFocusToChild: function(pass){
        this.__passFocusToChild = pass;
    },
    isPassFocusToChild: function(){
        return this.__passFocusToChild;
    },
    findNextFocusedWidget: function(direction, current){
        if (this._isFocusPassing || this.isFocused()) {
            var parent = this.getParent();
            this._isFocusPassing = false;
            if (this.__passFocusToChild) {
                var w = this._passFocusToChild(direction, current);
                if (w instanceof ccui.Layout && parent) {
                    parent._isFocusPassing = true;
                    return parent.findNextFocusedWidget(direction, this);
                }
                return w;
            }
            if (null == parent || !(parent instanceof ccui.Layout))
                return this;
            parent._isFocusPassing = true;
            return parent.findNextFocusedWidget(direction, this);
        } else if(current.isFocused() || current instanceof ccui.Layout) {
            if (this._layoutType === ccui.Layout.LINEAR_HORIZONTAL) {
                switch (direction){
                    case ccui.Widget.LEFT:
                        return this._getPreviousFocusedWidget(direction, current);
                    break;
                    case ccui.Widget.RIGHT:
                        return this._getNextFocusedWidget(direction, current);
                    break;
                    case ccui.Widget.DOWN:
                    case ccui.Widget.UP:
                        if (this._isLastWidgetInContainer(this, direction)){
                            if (this._isWidgetAncestorSupportLoopFocus(current, direction))
                                return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
                            return current;
                        } else {
                            return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
                        }
                    break;
                    default:
                        cc.assert(0, "Invalid Focus Direction");
                        return current;
                }
            } else if (this._layoutType === ccui.Layout.LINEAR_VERTICAL) {
                switch (direction){
                    case ccui.Widget.LEFT:
                    case ccui.Widget.RIGHT:
                        if (this._isLastWidgetInContainer(this, direction)) {
                            if (this._isWidgetAncestorSupportLoopFocus(current, direction))
                                return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
                            return current;
                        }
                        else
                            return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
                     break;
                    case ccui.Widget.DOWN:
                        return this._getNextFocusedWidget(direction, current);
                        break;
                    case ccui.Widget.UP:
                        return this._getPreviousFocusedWidget(direction, current);
                        break;
                    default:
                        cc.assert(0, "Invalid Focus Direction");
                        return current;
                }
            } else {
                cc.assert(0, "Un Supported Layout type, please use VBox and HBox instead!!!");
                return current;
            }
        } else
            return current;
    },
    onPassFocusToChild: null,
    addChild: function (widget, zOrder, tag) {
        if ((widget instanceof ccui.Widget)) {
            this._supplyTheLayoutParameterLackToChild(widget);
        }
        ccui.Widget.prototype.addChild.call(this, widget, zOrder, tag);
        this._doLayoutDirty = true;
    },
    removeChild: function (widget, cleanup) {
        ccui.Widget.prototype.removeChild.call(this, widget, cleanup);
        this._doLayoutDirty = true;
    },
    removeAllChildren: function (cleanup) {
        ccui.Widget.prototype.removeAllChildren.call(this, cleanup);
        this._doLayoutDirty = true;
    },
    removeAllChildrenWithCleanup: function(cleanup){
        ccui.Widget.prototype.removeAllChildrenWithCleanup.call(this, cleanup);
        this._doLayoutDirty = true;
    },
    isClippingEnabled: function () {
        return this._clippingEnabled;
    },
    visit: function (parentCmd) {
        if (!this._visible)
            return;
        this._adaptRenderers();
        this._doLayout();
        if (this._clippingEnabled) {
            switch (this._clippingType) {
                case ccui.Layout.CLIPPING_STENCIL:
                    this._renderCmd.stencilClippingVisit(parentCmd);
                    break;
                case ccui.Layout.CLIPPING_SCISSOR:
                    this._renderCmd.scissorClippingVisit(parentCmd);
                    break;
                default:
                    break;
            }
        } else {
            ccui.Widget.prototype.visit.call(this, parentCmd);
        }
    },
    setClippingEnabled: function (able) {
        if (able === this._clippingEnabled)
            return;
        this._clippingEnabled = able;
        switch (this._clippingType) {
            case ccui.Layout.CLIPPING_SCISSOR:
            case ccui.Layout.CLIPPING_STENCIL:
                if (able){
                    this._clippingStencil = new cc.DrawNode();
                    this._renderCmd.rebindStencilRendering(this._clippingStencil);
                    if (this._running)
                        this._clippingStencil.onEnter();
                    this._setStencilClippingSize(this._contentSize);
                } else {
                    if (this._running && this._clippingStencil)
                        this._clippingStencil.onExit();
                    this._clippingStencil = null;
                }
                break;
            default:
                break;
        }
    },
    setClippingType: function (type) {
        if (type === this._clippingType)
            return;
        var clippingEnabled = this.isClippingEnabled();
        this.setClippingEnabled(false);
        this._clippingType = type;
        this.setClippingEnabled(clippingEnabled);
    },
    getClippingType: function () {
        return this._clippingType;
    },
    _setStencilClippingSize: function (size) {
        if (this._clippingEnabled) {
            var rect = [];
            rect[0] = cc.p(0, 0);
            rect[1] = cc.p(size.width, 0);
            rect[2] = cc.p(size.width, size.height);
            rect[3] = cc.p(0, size.height);
            var green = cc.color.GREEN;
            this._clippingStencil.clear();
            this._clippingStencil.setLocalBB && this._clippingStencil.setLocalBB(0, 0, size.width, size.height);
            this._clippingStencil.drawPoly(rect, 4, green, 0, green);
        }
    },
    _getClippingRect: function () {
        if (this._clippingRectDirty) {
            var worldPos = this.convertToWorldSpace(cc.p(0, 0));
            var t = this.getNodeToWorldTransform();
            var scissorWidth = this._contentSize.width * t.a;
            var scissorHeight = this._contentSize.height * t.d;
            var parentClippingRect;
            var parent = this;
            while (parent) {
                parent = parent.getParent();
                if (parent && parent instanceof ccui.Layout && parent.isClippingEnabled()) {
                    this._clippingParent = parent;
                    break;
                }
            }
            if (this._clippingParent) {
                parentClippingRect = this._clippingParent._getClippingRect();
                this._clippingRect.x = Math.max(worldPos.x, parentClippingRect.x);
                this._clippingRect.y = Math.max(worldPos.y, parentClippingRect.y);
                var right = Math.min(worldPos.x + scissorWidth, parentClippingRect.x + parentClippingRect.width);
                var top = Math.min(worldPos.y + scissorHeight, parentClippingRect.y + parentClippingRect.height);
                this._clippingRect.width = Math.max(0.0, right -  this._clippingRect.x);
                this._clippingRect.height = Math.max(0.0, top -  this._clippingRect.y);
            } else {
                this._clippingRect.x = worldPos.x;
                this._clippingRect.y = worldPos.y;
                this._clippingRect.width = scissorWidth;
                this._clippingRect.height = scissorHeight;
            }
            this._clippingRectDirty = false;
        }
        return this._clippingRect;
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        var locContentSize = this._contentSize;
        this._setStencilClippingSize(locContentSize);
        this._doLayoutDirty = true;
        this._clippingRectDirty = true;
        if (this._backGroundImage) {
            this._backGroundImage.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
            if (this._backGroundScale9Enabled && this._backGroundImage instanceof ccui.Scale9Sprite)
                this._backGroundImage.setPreferredSize(locContentSize);
        }
        if (this._colorRender)
            this._colorRender.setContentSize(locContentSize);
        if (this._gradientRender)
            this._gradientRender.setContentSize(locContentSize);
    },
    setBackGroundImageScale9Enabled: function (able) {
        if (this._backGroundScale9Enabled === able)
            return;
        this.removeProtectedChild(this._backGroundImage);
        this._backGroundImage = null;
        this._backGroundScale9Enabled = able;
        this._addBackGroundImage();
        this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType);
        this.setBackGroundImageCapInsets(this._backGroundImageCapInsets);
    },
    isBackGroundImageScale9Enabled: function () {
        return this._backGroundScale9Enabled;
    },
    setBackGroundImage: function (fileName, texType) {
        if (!fileName)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        if (this._backGroundImage === null){
            this._addBackGroundImage();
            this.setBackGroundImageScale9Enabled(this._backGroundScale9Enabled);
        }
        this._backGroundImageFileName = fileName;
        this._bgImageTexType = texType;
        var locBackgroundImage = this._backGroundImage;
        switch (this._bgImageTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                locBackgroundImage.initWithFile(fileName);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                locBackgroundImage.initWithSpriteFrameName(fileName);
                break;
            default:
                break;
        }
        if (this._backGroundScale9Enabled)
            locBackgroundImage.setPreferredSize(this._contentSize);
        this._backGroundImageTextureSize = locBackgroundImage.getContentSize();
        locBackgroundImage.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
        this._updateBackGroundImageColor();
    },
    setBackGroundImageCapInsets: function (capInsets) {
        if(!capInsets)
            return;
        var locInsets = this._backGroundImageCapInsets;
        locInsets.x = capInsets.x;
        locInsets.y = capInsets.y;
        locInsets.width = capInsets.width;
        locInsets.height = capInsets.height;
        if (this._backGroundScale9Enabled)
            this._backGroundImage.setCapInsets(capInsets);
    },
    getBackGroundImageCapInsets: function () {
        return cc.rect(this._backGroundImageCapInsets);
    },
    _supplyTheLayoutParameterLackToChild: function (locChild) {
        if (!locChild) {
            return;
        }
        switch (this._layoutType) {
            case ccui.Layout.ABSOLUTE:
                break;
            case ccui.Layout.LINEAR_HORIZONTAL:
            case ccui.Layout.LINEAR_VERTICAL:
                var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.LINEAR);
                if (!layoutParameter)
                    locChild.setLayoutParameter(new ccui.LinearLayoutParameter());
                break;
            case ccui.Layout.RELATIVE:
                var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.RELATIVE);
                if (!layoutParameter)
                    locChild.setLayoutParameter(new ccui.RelativeLayoutParameter());
                break;
            default:
                break;
        }
    },
    _addBackGroundImage: function () {
        var contentSize = this._contentSize;
        if (this._backGroundScale9Enabled) {
            this._backGroundImage = new ccui.Scale9Sprite();
            this._backGroundImage.setPreferredSize(contentSize);
        } else
            this._backGroundImage = new cc.Sprite();
        this.addProtectedChild(this._backGroundImage, ccui.Layout.BACKGROUND_IMAGE_ZORDER, -1);
        this._backGroundImage.setPosition(contentSize.width * 0.5, contentSize.height * 0.5);
    },
    removeBackGroundImage: function () {
        if (!this._backGroundImage)
            return;
        this.removeProtectedChild(this._backGroundImage);
        this._backGroundImage = null;
        this._backGroundImageFileName = "";
        this._backGroundImageTextureSize.width = 0;
        this._backGroundImageTextureSize.height = 0;
    },
    setBackGroundColorType: function (type) {
        if (this._colorType === type)
            return;
        switch (this._colorType) {
            case ccui.Layout.BG_COLOR_NONE:
                if (this._colorRender) {
                    this.removeProtectedChild(this._colorRender);
                    this._colorRender = null;
                }
                if (this._gradientRender) {
                    this.removeProtectedChild(this._gradientRender);
                    this._gradientRender = null;
                }
                break;
            case ccui.Layout.BG_COLOR_SOLID:
                if (this._colorRender) {
                    this.removeProtectedChild(this._colorRender);
                    this._colorRender = null;
                }
                break;
            case ccui.Layout.BG_COLOR_GRADIENT:
                if (this._gradientRender) {
                    this.removeProtectedChild(this._gradientRender);
                    this._gradientRender = null;
                }
                break;
            default:
                break;
        }
        this._colorType = type;
        switch (this._colorType) {
            case ccui.Layout.BG_COLOR_NONE:
                break;
            case ccui.Layout.BG_COLOR_SOLID:
                this._colorRender = new cc.LayerColor();
                this._colorRender.setContentSize(this._contentSize);
                this._colorRender.setOpacity(this._opacity);
                this._colorRender.setColor(this._color);
                this.addProtectedChild(this._colorRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1);
                break;
            case ccui.Layout.BG_COLOR_GRADIENT:
                this._gradientRender = new cc.LayerGradient(cc.color(255, 0, 0, 255), cc.color(0, 255, 0, 255));
                this._gradientRender.setContentSize(this._contentSize);
                this._gradientRender.setOpacity(this._opacity);
                this._gradientRender.setStartColor(this._startColor);
                this._gradientRender.setEndColor(this._endColor);
                this._gradientRender.setVector(this._alongVector);
                this.addProtectedChild(this._gradientRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1);
                break;
            default:
                break;
        }
    },
    getBackGroundColorType: function () {
        return this._colorType;
    },
    setBackGroundColor: function (color, endColor) {
        if (!endColor) {
            this._color.r = color.r;
            this._color.g = color.g;
            this._color.b = color.b;
            if (this._colorRender)
                this._colorRender.setColor(color);
        } else {
            this._startColor.r = color.r;
            this._startColor.g = color.g;
            this._startColor.b = color.b;
            if (this._gradientRender)
                this._gradientRender.setStartColor(color);
            this._endColor.r = endColor.r;
            this._endColor.g = endColor.g;
            this._endColor.b = endColor.b;
            if (this._gradientRender)
                this._gradientRender.setEndColor(endColor);
        }
    },
    getBackGroundColor: function () {
        var tmpColor = this._color;
        return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
    },
    getBackGroundStartColor: function () {
        var tmpColor = this._startColor;
        return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
    },
    getBackGroundEndColor: function () {
        var tmpColor = this._endColor;
        return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
    },
    setBackGroundColorOpacity: function (opacity) {
        this._opacity = opacity;
        switch (this._colorType) {
            case ccui.Layout.BG_COLOR_NONE:
                break;
            case ccui.Layout.BG_COLOR_SOLID:
                this._colorRender.setOpacity(opacity);
                break;
            case ccui.Layout.BG_COLOR_GRADIENT:
                this._gradientRender.setOpacity(opacity);
                break;
            default:
                break;
        }
    },
    getBackGroundColorOpacity: function () {
        return this._opacity;
    },
    setBackGroundColorVector: function (vector) {
        this._alongVector.x = vector.x;
        this._alongVector.y = vector.y;
        if (this._gradientRender) {
            this._gradientRender.setVector(vector);
        }
    },
    getBackGroundColorVector: function () {
        return this._alongVector;
    },
    setBackGroundImageColor: function (color) {
        this._backGroundImageColor.r = color.r;
        this._backGroundImageColor.g = color.g;
        this._backGroundImageColor.b = color.b;
        this._updateBackGroundImageColor();
    },
    setBackGroundImageOpacity: function (opacity) {
        this._backGroundImageColor.a = opacity;
        this.getBackGroundImageColor();
    },
    getBackGroundImageColor: function () {
        var color = this._backGroundImageColor;
        return cc.color(color.r, color.g, color.b, color.a);
    },
    getBackGroundImageOpacity: function () {
        return this._backGroundImageColor.a;
    },
    _updateBackGroundImageColor: function () {
        if(this._backGroundImage)
            this._backGroundImage.setColor(this._backGroundImageColor);
    },
    getBackGroundImageTextureSize: function () {
        return this._backGroundImageTextureSize;
    },
    setLayoutType: function (type) {
        this._layoutType = type;
        var layoutChildrenArray = this._children;
        var locChild = null;
        for (var i = 0; i < layoutChildrenArray.length; i++) {
            locChild = layoutChildrenArray[i];
            if(locChild instanceof ccui.Widget)
                this._supplyTheLayoutParameterLackToChild(locChild);
        }
        this._doLayoutDirty = true;
    },
    getLayoutType: function () {
        return this._layoutType;
    },
    requestDoLayout: function () {
        this._doLayoutDirty = true;
    },
    _doLayout: function () {
        if (!this._doLayoutDirty)
            return;
        this.sortAllChildren();
        var executant = ccui.getLayoutManager(this._layoutType);
        if (executant)
            executant._doLayout(this);
        this._doLayoutDirty = false;
    },
    _getLayoutContentSize: function(){
        return this.getContentSize();
    },
    _getLayoutElements: function(){
        return this.getChildren();
    },
    _updateBackGroundImageOpacity: function(){
        if (this._backGroundImage)
            this._backGroundImage.setOpacity(this._backGroundImageOpacity);
    },
    _updateBackGroundImageRGBA: function(){
        if (this._backGroundImage) {
            this._backGroundImage.setColor(this._backGroundImageColor);
            this._backGroundImage.setOpacity(this._backGroundImageOpacity);
        }
    },
    _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 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;
    },
    _findNearestChildWidgetIndex: function(direction, baseWidget){
        if (baseWidget == null || baseWidget === this)
            return this._findFirstFocusEnabledWidgetIndex();
        var index = 0, locChildren = this.getChildren();
        var count = locChildren.length, widgetPosition;
        var distance = cc.FLT_MAX, found = 0;
        if (direction === ccui.Widget.LEFT || direction === ccui.Widget.RIGHT || direction === ccui.Widget.DOWN || direction === ccui.Widget.UP) {
            widgetPosition = this._getWorldCenterPoint(baseWidget);
            while (index < count) {
                var w = locChildren[index];
                if (w && w instanceof ccui.Widget && w.isFocusEnabled()) {
                    var length = (w instanceof ccui.Layout)? w._calculateNearestDistance(baseWidget)
                        : cc.pLength(cc.pSub(this._getWorldCenterPoint(w), widgetPosition));
                    if (length < distance){
                        found = index;
                        distance = length;
                    }
                }
                index++;
            }
            return found;
        }
        cc.log("invalid focus direction!");
        return 0;
    },
    _findFarthestChildWidgetIndex: function(direction, baseWidget){
        if (baseWidget == null || baseWidget === this)
            return this._findFirstFocusEnabledWidgetIndex();
        var index = 0, locChildren = this.getChildren();
        var count = locChildren.length;
        var distance = -cc.FLT_MAX, found = 0;
        if (direction === ccui.Widget.LEFT || direction === ccui.Widget.RIGHT || direction === ccui.Widget.DOWN || direction === ccui.Widget.UP) {
            var widgetPosition =  this._getWorldCenterPoint(baseWidget);
            while (index <  count) {
                var w = locChildren[index];
                if (w && w instanceof ccui.Widget && w.isFocusEnabled()) {
                    var length = (w instanceof ccui.Layout)?w._calculateFarthestDistance(baseWidget)
                        : cc.pLength(cc.pSub(this._getWorldCenterPoint(w), widgetPosition));
                    if (length > distance){
                        found = index;
                        distance = length;
                    }
                }
                index++;
            }
            return  found;
        }
        cc.log("invalid focus direction!!!");
        return 0;
    },
    _calculateNearestDistance: function(baseWidget){
        var distance = cc.FLT_MAX;
        var widgetPosition =  this._getWorldCenterPoint(baseWidget);
        var locChildren = this._children;
        for (var i = 0, len = locChildren.length; i < len; i++) {
            var widget = locChildren[i], length;
            if (widget instanceof ccui.Layout)
                length = widget._calculateNearestDistance(baseWidget);
            else {
                if (widget instanceof ccui.Widget && widget.isFocusEnabled())
                    length = cc.pLength(cc.pSub(this._getWorldCenterPoint(widget), widgetPosition));
                else
                    continue;
            }
            if (length < distance)
                distance = length;
        }
        return distance;
    },
    _calculateFarthestDistance:function(baseWidget){
        var distance = -cc.FLT_MAX;
        var widgetPosition =  this._getWorldCenterPoint(baseWidget);
        var locChildren = this._children;
        for (var i = 0, len = locChildren.length; i < len; i++) {
            var layout = locChildren[i];
            var length;
            if (layout instanceof ccui.Layout)
                length = layout._calculateFarthestDistance(baseWidget);
            else {
                if (layout instanceof ccui.Widget && layout.isFocusEnabled()) {
                    var wPosition = this._getWorldCenterPoint(layout);
                    length = cc.pLength(cc.pSub(wPosition, widgetPosition));
                } else
                    continue;
            }
            if (length > distance)
                distance = length;
        }
        return distance;
    },
    _findProperSearchingFunctor: function(direction, baseWidget){
        if (baseWidget === undefined)
            return;
        var previousWidgetPosition = this._getWorldCenterPoint(baseWidget);
        var widgetPosition = this._getWorldCenterPoint(this._findFirstNonLayoutWidget());
        if (direction === ccui.Widget.LEFT) {
            this.onPassFocusToChild = (previousWidgetPosition.x > widgetPosition.x) ? this._findNearestChildWidgetIndex
                : this._findFarthestChildWidgetIndex;
        } else if (direction === ccui.Widget.RIGHT) {
            this.onPassFocusToChild = (previousWidgetPosition.x > widgetPosition.x) ? this._findFarthestChildWidgetIndex
                : this._findNearestChildWidgetIndex;
        }else if(direction === ccui.Widget.DOWN) {
            this.onPassFocusToChild = (previousWidgetPosition.y > widgetPosition.y) ? this._findNearestChildWidgetIndex
                : this._findFarthestChildWidgetIndex;
        }else if(direction === ccui.Widget.UP) {
            this.onPassFocusToChild = (previousWidgetPosition.y < widgetPosition.y) ? this._findNearestChildWidgetIndex
                : this._findFarthestChildWidgetIndex;
        }else
            cc.log("invalid direction!");
    },
    _findFirstNonLayoutWidget:function(){
        var locChildren = this._children;
        for(var i = 0, len = locChildren.length; i < len; i++) {
            var child = locChildren[i];
            if (child instanceof ccui.Layout){
                var widget = child._findFirstNonLayoutWidget();
                if(widget)
                    return widget;
            } else{
                if (child instanceof ccui.Widget)
                    return child;
            }
        }
        return null;
    },
    _findFirstFocusEnabledWidgetIndex: function(){
        var index = 0, locChildren = this.getChildren();
        var count = locChildren.length;
        while (index < count) {
            var w = locChildren[index];
            if (w && w instanceof ccui.Widget && w.isFocusEnabled())
                return index;
            index++;
        }
        return 0;
    },
    _findFocusEnabledChildWidgetByIndex: function(index){
        var widget = this._getChildWidgetByIndex(index);
        if (widget){
            if (widget.isFocusEnabled())
                return widget;
            index = index + 1;
            return this._findFocusEnabledChildWidgetByIndex(index);
        }
        return null;
    },
    _getWorldCenterPoint: function(widget){
        var widgetSize = widget instanceof ccui.Layout ? widget._getLayoutAccumulatedSize() :  widget.getContentSize();
        return widget.convertToWorldSpace(cc.p(widgetSize.width /2, widgetSize.height /2));
    },
    _getNextFocusedWidget: function(direction, current){
        var nextWidget = null, locChildren = this._children;
        var  previousWidgetPos = locChildren.indexOf(current);
        previousWidgetPos = previousWidgetPos + 1;
        if (previousWidgetPos < locChildren.length) {
            nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
            if (nextWidget) {
                if (nextWidget.isFocusEnabled()) {
                    if (nextWidget instanceof ccui.Layout) {
                        nextWidget._isFocusPassing = true;
                        return nextWidget.findNextFocusedWidget(direction, nextWidget);
                    } else {
                        this.dispatchFocusEvent(current, nextWidget);
                        return nextWidget;
                    }
                } else
                    return this._getNextFocusedWidget(direction, nextWidget);
            } else
                return current;
        } else {
            if (this._loopFocus) {
                if (this._checkFocusEnabledChild()) {
                    previousWidgetPos = 0;
                    nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
                    if (nextWidget.isFocusEnabled()) {
                        if (nextWidget instanceof ccui.Layout) {
                            nextWidget._isFocusPassing = true;
                            return nextWidget.findNextFocusedWidget(direction, nextWidget);
                        } else {
                            this.dispatchFocusEvent(current, nextWidget);
                            return nextWidget;
                        }
                    } else
                        return this._getNextFocusedWidget(direction, nextWidget);
                } else
                    return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
            } else{
                if (this._isLastWidgetInContainer(current, direction)){
                    if (this._isWidgetAncestorSupportLoopFocus(this, direction))
                        return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
                    return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
                } else
                    return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
            }
        }
    },
    _getPreviousFocusedWidget: function(direction, current){
        var nextWidget = null, locChildren = this._children;
        var previousWidgetPos = locChildren.indexOf(current);
        previousWidgetPos = previousWidgetPos - 1;
        if (previousWidgetPos >= 0){
            nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
            if (nextWidget.isFocusEnabled()) {
                if (nextWidget instanceof ccui.Layout){
                    nextWidget._isFocusPassing = true;
                    return nextWidget.findNextFocusedWidget(direction, nextWidget);
                }
                this.dispatchFocusEvent(current, nextWidget);
                return nextWidget;
            } else
                return this._getPreviousFocusedWidget(direction, nextWidget);
        }else {
            if (this._loopFocus){
                if (this._checkFocusEnabledChild()) {
                    previousWidgetPos = locChildren.length -1;
                    nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
                    if (nextWidget.isFocusEnabled()){
                        if (nextWidget instanceof ccui.Layout){
                            nextWidget._isFocusPassing = true;
                            return nextWidget.findNextFocusedWidget(direction, nextWidget);
                        } else {
                            this.dispatchFocusEvent(current, nextWidget);
                            return nextWidget;
                        }
                    } else
                        return this._getPreviousFocusedWidget(direction, nextWidget);
                } else
                    return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
            } else {
                if (this._isLastWidgetInContainer(current, direction)) {
                    if (this._isWidgetAncestorSupportLoopFocus(this, direction))
                        return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
                    return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
                } else
                    return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
            }
        }
    },
    _getChildWidgetByIndex: function (index) {
        var locChildren = this._children;
        var size = locChildren.length, count = 0, oldIndex = index;
        while (index < size) {
            var firstChild = locChildren[index];
            if (firstChild && firstChild instanceof ccui.Widget)
                return firstChild;
            count++;
            index++;
        }
        var begin = 0;
        while (begin < oldIndex) {
            var child = locChildren[begin];
            if (child && child instanceof ccui.Widget)
                return child;
            count++;
            begin++;
        }
        return null;
    },
    _isLastWidgetInContainer:function(widget, direction){
        var parent = widget.getParent();
        if (parent == null || !(parent instanceof ccui.Layout))
            return true;
        var container = parent.getChildren();
        var index = container.indexOf(widget);
        if (parent.getLayoutType() === ccui.Layout.LINEAR_HORIZONTAL) {
            if (direction === ccui.Widget.LEFT) {
                if (index === 0)
                    return this._isLastWidgetInContainer(parent, direction);
                else
                    return false;
            }
            if (direction === ccui.Widget.RIGHT) {
                if (index === container.length - 1)
                    return this._isLastWidgetInContainer(parent, direction);
                else
                    return false;
            }
            if (direction === ccui.Widget.DOWN)
                return this._isLastWidgetInContainer(parent, direction);
            if (direction === ccui.Widget.UP)
                return this._isLastWidgetInContainer(parent, direction);
        } else if(parent.getLayoutType() === ccui.Layout.LINEAR_VERTICAL){
            if (direction === ccui.Widget.UP){
                if (index === 0)
                    return this._isLastWidgetInContainer(parent, direction);
                else
                    return false;
            }
            if (direction === ccui.Widget.DOWN) {
                if (index === container.length - 1)
                    return this._isLastWidgetInContainer(parent, direction);
                else
                    return false;
            }
            if (direction === ccui.Widget.LEFT)
                return this._isLastWidgetInContainer(parent, direction);
            if (direction === ccui.Widget.RIGHT)
                return this._isLastWidgetInContainer(parent, direction);
        } else {
            cc.log("invalid layout Type");
            return false;
        }
    },
    _isWidgetAncestorSupportLoopFocus: function(widget, direction){
        var parent = widget.getParent();
        if (parent == null || !(parent instanceof ccui.Layout))
            return false;
        if (parent.isLoopFocus()) {
            var layoutType = parent.getLayoutType();
            if (layoutType === ccui.Layout.LINEAR_HORIZONTAL) {
                if (direction === ccui.Widget.LEFT || direction === ccui.Widget.RIGHT)
                    return true;
                else
                    return this._isWidgetAncestorSupportLoopFocus(parent, direction);
            }
            if (layoutType === ccui.Layout.LINEAR_VERTICAL){
                if (direction === ccui.Widget.DOWN || direction === ccui.Widget.UP)
                    return true;
                else
                    return this._isWidgetAncestorSupportLoopFocus(parent, direction);
            } else{
                cc.assert(0, "invalid layout type");
                return false;
            }
        } else
            return this._isWidgetAncestorSupportLoopFocus(parent, direction);
    },
    _passFocusToChild: function(direction, current){
        if (this._checkFocusEnabledChild()) {
            var previousWidget = ccui.Widget.getCurrentFocusedWidget();
            this._findProperSearchingFunctor(direction, previousWidget);
            var index = this.onPassFocusToChild(direction, previousWidget);
            var widget = this._getChildWidgetByIndex(index);
            if (widget instanceof ccui.Layout) {
                widget._isFocusPassing = true;
                return widget.findNextFocusedWidget(direction, widget);
            } else {
                this.dispatchFocusEvent(current, widget);
                return widget;
            }
        }else
            return this;
    },
    _checkFocusEnabledChild: function(){
        var locChildren = this._children;
        for(var i = 0, len = locChildren.length; i < len; i++){
            var widget = locChildren[i];
            if (widget && widget instanceof ccui.Widget && widget.isFocusEnabled())
                return true;
        }
        return false;
    },
    getDescription: function () {
        return "Layout";
    },
    _createCloneInstance: function () {
        return new ccui.Layout();
    },
    _copyClonedWidgetChildren: function (model) {
        ccui.Widget.prototype._copyClonedWidgetChildren.call(this, model);
    },
    _copySpecialProperties: function (layout) {
        if(!(layout instanceof  ccui.Layout))
            return;
        this.setBackGroundImageScale9Enabled(layout._backGroundScale9Enabled);
        this.setBackGroundImage(layout._backGroundImageFileName, layout._bgImageTexType);
        this.setBackGroundImageCapInsets(layout._backGroundImageCapInsets);
        this.setBackGroundColorType(layout._colorType);
        this.setBackGroundColor(layout._color);
        this.setBackGroundColor(layout._startColor, layout._endColor);
        this.setBackGroundColorOpacity(layout._opacity);
        this.setBackGroundColorVector(layout._alongVector);
        this.setLayoutType(layout._layoutType);
        this.setClippingEnabled(layout._clippingEnabled);
        this.setClippingType(layout._clippingType);
        this._loopFocus = layout._loopFocus;
        this.__passFocusToChild = layout.__passFocusToChild;
        this._isInterceptTouch = layout._isInterceptTouch;
    },
    forceDoLayout: function(){
        this.requestDoLayout();
        this._doLayout();
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new ccui.Layout.WebGLRenderCmd(this);
        else
            return new ccui.Layout.CanvasRenderCmd(this);
    }
});
var _p = ccui.Layout.prototype;
_p.clippingEnabled;
cc.defineGetterSetter(_p, "clippingEnabled", _p.isClippingEnabled, _p.setClippingEnabled);
_p.clippingType;
cc.defineGetterSetter(_p, "clippingType", null, _p.setClippingType);
_p.layoutType;
cc.defineGetterSetter(_p, "layoutType", _p.getLayoutType, _p.setLayoutType);
_p = null;
ccui.Layout.create = function () {
    return new ccui.Layout();
};
ccui.Layout.BG_COLOR_NONE = 0;
ccui.Layout.BG_COLOR_SOLID = 1;
ccui.Layout.BG_COLOR_GRADIENT = 2;
ccui.Layout.ABSOLUTE = 0;
ccui.Layout.LINEAR_VERTICAL = 1;
ccui.Layout.LINEAR_HORIZONTAL = 2;
ccui.Layout.RELATIVE = 3;
ccui.Layout.CLIPPING_STENCIL = 0;
ccui.Layout.CLIPPING_SCISSOR = 1;
ccui.Layout.BACKGROUND_IMAGE_ZORDER = -1;
ccui.Layout.BACKGROUND_RENDERER_ZORDER = -2;
(function(){
    ccui.Layout.CanvasRenderCmd = function(renderable){
        ccui.ProtectedNode.CanvasRenderCmd.call(this, renderable);
        this._needDraw = false;
        this._rendererSaveCmd = new cc.CustomRenderCmd(this, this._onRenderSaveCmd);
        this._rendererClipCmd = new cc.CustomRenderCmd(this, this._onRenderClipCmd);
        this._rendererRestoreCmd = new cc.CustomRenderCmd(this, this._onRenderRestoreCmd);
        this._rendererSaveCmd._canUseDirtyRegion = true;
        this._rendererClipCmd._canUseDirtyRegion = true;
        this._rendererRestoreCmd._canUseDirtyRegion = true;
    };
    var proto = ccui.Layout.CanvasRenderCmd.prototype = Object.create(ccui.ProtectedNode.CanvasRenderCmd.prototype);
    proto.constructor = ccui.Layout.CanvasRenderCmd;
    cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
        if (ccui.Widget.CanvasRenderCmd) {
            ccui.Layout.CanvasRenderCmd.prototype.widgetVisit = ccui.Widget.CanvasRenderCmd.prototype.widgetVisit;
        }
    });
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        node._adaptRenderers();
        node._doLayout();
        if (node._clippingEnabled) {
            switch (node._clippingType) {
                case ccui.Layout.CLIPPING_STENCIL:
                    this.stencilClippingVisit(parentCmd);
                    break;
                case ccui.Layout.CLIPPING_SCISSOR:
                    this.scissorClippingVisit(parentCmd);
                    break;
                default:
                    break;
            }
        } else {
            this.widgetVisit(parentCmd);
        }
    };
    proto.layoutVisit = proto.visit;
    proto._onRenderSaveCmd = function(ctx, scaleX, scaleY){
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        wrapper.save();
        wrapper.save();
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        var buffer = this._node._clippingStencil._renderCmd._buffer;
        for (var i = 0, bufLen = buffer.length; i < bufLen; i++) {
            var element = buffer[i], vertices = element.verts;
            var firstPoint = vertices[0];
            context.beginPath();
            context.moveTo(firstPoint.x, -firstPoint.y );
            for (var j = 1, len = vertices.length; j < len; j++)
                context.lineTo(vertices[j].x , -vertices[j].y );
            context.closePath();
        }
    };
    proto._onRenderClipCmd = function(ctx){
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        wrapper.restore();
        context.clip();
    };
    proto._onRenderRestoreCmd = function(ctx){
        var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
        wrapper.restore();
    };
    proto.rebindStencilRendering = function(stencil){
        stencil._renderCmd.rendering = this.__stencilDraw;
        stencil._renderCmd._canUseDirtyRegion = true;
    };
    proto.__stencilDraw = function(ctx,scaleX, scaleY){
    };
    proto.stencilClippingVisit = proto.scissorClippingVisit = function (parentCmd) {
        var node = this._node;
        if (!node._clippingStencil || !node._clippingStencil.isVisible())
            return;
        this._syncStatus(parentCmd);
        cc.renderer.pushRenderCommand(this._rendererSaveCmd);
        node._clippingStencil.visit(this);
        cc.renderer.pushRenderCommand(this._rendererClipCmd);
            node.sortAllChildren();
            node.sortAllProtectedChildren();
            var children = node._children;
            var j=0, locProtectChildren = node._protectedChildren, i = 0, locChild;
            var iLen = children.length, jLen = locProtectChildren.length;
            for( ; i < iLen; i++ ){
                locChild = children[i];
                if ( locChild && locChild.getLocalZOrder() < 0 )
                    locChild.visit(this);
                else
                    break;
            }
            for( ; j < jLen; j++ ) {
                locChild = locProtectChildren[j];
                if ( locChild && locChild.getLocalZOrder() < 0 )
                    locChild.visit(this);
                else
                    break;
            }
            for (; i < iLen; i++)
                children[i].visit(this);
            for (; j < jLen; j++)
                locProtectChildren[j].visit(this);
            cc.renderer.pushRenderCommand(this._rendererRestoreCmd);
        this._dirtyFlag = 0;
    };
    ccui.Layout.CanvasRenderCmd._getSharedCache = function () {
        return (cc.ClippingNode._sharedCache) || (cc.ClippingNode._sharedCache = document.createElement("canvas"));
    };
})();
(function(){
    if(!ccui.ProtectedNode.WebGLRenderCmd)
        return;
    ccui.Layout.WebGLRenderCmd = function(renderable){
        ccui.ProtectedNode.WebGLRenderCmd.call(this, renderable);
        this._needDraw = false;
        this._currentStencilEnabled = 0;
        this._scissorOldState = false;
        this._clippingOldRect = null;
        this._mask_layer_le = 0;
        this._beforeVisitCmdStencil = new cc.CustomRenderCmd(this, this._onBeforeVisitStencil);
        this._afterDrawStencilCmd = new cc.CustomRenderCmd(this, this._onAfterDrawStencil);
        this._afterVisitCmdStencil = new cc.CustomRenderCmd(this, this._onAfterVisitStencil);
        this._beforeVisitCmdScissor = new cc.CustomRenderCmd(this, this._onBeforeVisitScissor);
        this._afterVisitCmdScissor = new cc.CustomRenderCmd(this, this._onAfterVisitScissor);
    };
    var proto = ccui.Layout.WebGLRenderCmd.prototype = Object.create(ccui.ProtectedNode.WebGLRenderCmd.prototype);
    proto.constructor = ccui.Layout.WebGLRenderCmd;
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        if(parentCmd && (parentCmd._dirtyFlag & cc.Node._dirtyFlags.transformDirty))
            node._clippingRectDirty = true;
        node._adaptRenderers();
        node._doLayout();
        if (node._clippingEnabled) {
            switch (node._clippingType) {
                case ccui.Layout.CLIPPING_STENCIL:
                    this.stencilClippingVisit(parentCmd);
                    break;
                case ccui.Layout.CLIPPING_SCISSOR:
                    this.scissorClippingVisit(parentCmd);
                    break;
                default:
                    break;
            }
        } else {
            this.pNodeVisit(parentCmd);
        }
    };
    proto.layoutVisit = proto.visit;
    proto._onBeforeVisitStencil = function(ctx){
        var gl = ctx || cc._renderContext;
        ccui.Layout.WebGLRenderCmd._layer++;
        var mask_layer = 0x1 << ccui.Layout.WebGLRenderCmd._layer;
        var mask_layer_l = mask_layer - 1;
        this._mask_layer_le = mask_layer | mask_layer_l;
        this._currentStencilEnabled = gl.isEnabled(gl.STENCIL_TEST);
        gl.clear(gl.DEPTH_BUFFER_BIT);
        gl.enable(gl.STENCIL_TEST);
        gl.depthMask(false);
        gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
        gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
        gl.stencilMask(mask_layer);
        gl.clear(gl.STENCIL_BUFFER_BIT);
    };
    proto._onAfterDrawStencil = function(ctx){
        var gl = ctx || cc._renderContext;
        gl.depthMask(true);
        gl.stencilFunc(gl.EQUAL, this._mask_layer_le, this._mask_layer_le);
        gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
    };
    proto._onAfterVisitStencil = function(ctx){
        var gl = ctx || cc._renderContext;
        ccui.Layout.WebGLRenderCmd._layer--;
        if (this._currentStencilEnabled)
        {
            var mask_layer = 0x1 << ccui.Layout.WebGLRenderCmd._layer;
            var mask_layer_l = mask_layer - 1;
            var mask_layer_le = mask_layer | mask_layer_l;
            gl.stencilMask(mask_layer);
            gl.stencilFunc(gl.EQUAL, mask_layer_le, mask_layer_le);
        }
        else
        {
            gl.disable(gl.STENCIL_TEST);
        }
    };
    proto._onBeforeVisitScissor = function(ctx){
        this._node._clippingRectDirty = true;
        var clippingRect = this._node._getClippingRect();
        var gl = ctx || cc._renderContext;
        this._scissorOldState = gl.isEnabled(gl.SCISSOR_TEST);
        if (!this._scissorOldState) {
            gl.enable(gl.SCISSOR_TEST);
            cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
        }
        else {
            this._clippingOldRect = cc.view.getScissorRect();
            if (!cc.rectEqualToRect(this._clippingOldRect, clippingRect))
                cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
        }
    };
    proto._onAfterVisitScissor = function(ctx){
        var gl = ctx || cc._renderContext;
        if (this._scissorOldState) {
            if (!cc.rectEqualToRect(this._clippingOldRect, this._node._clippingRect)) {
                cc.view.setScissorInPoints( this._clippingOldRect.x,
                    this._clippingOldRect.y,
                    this._clippingOldRect.width,
                    this._clippingOldRect.height);
            }
        }
        else {
            gl.disable(gl.SCISSOR_TEST);
        }
    };
    proto.rebindStencilRendering = function(stencil){};
    proto.transform = function(parentCmd, recursive){
        var node = this._node;
        this.pNodeTransform(parentCmd, recursive);
        if(node._clippingStencil)
            node._clippingStencil._renderCmd.transform(this, recursive);
    };
    proto.stencilClippingVisit = function (parentCmd) {
        var node = this._node;
        if (!node._clippingStencil || !node._clippingStencil.isVisible())
            return;
        if (ccui.Layout.WebGLRenderCmd._layer + 1 === cc.stencilBits) {
            ccui.Layout.WebGLRenderCmd._visit_once = true;
            if (ccui.Layout.WebGLRenderCmd._visit_once) {
                cc.log("Nesting more than " + cc.stencilBits + "stencils is not supported. Everything will be drawn without stencil for this node and its childs.");
                ccui.Layout.WebGLRenderCmd._visit_once = false;
            }
            cc.Node.prototype.visit.call(node, parentCmd);
            return;
        }
        cc.renderer.pushRenderCommand(this._beforeVisitCmdStencil);
        var currentStack = cc.current_stack;
        currentStack.stack.push(currentStack.top);
        this._syncStatus(parentCmd);
        this._dirtyFlag = 0;
        currentStack.top = this._stackMatrix;
        node._clippingStencil.visit(this);
        cc.renderer.pushRenderCommand(this._afterDrawStencilCmd);
        var i = 0;
        var j = 0;
        node.sortAllChildren();
        node.sortAllProtectedChildren();
        var locChildren = node._children, locProtectChildren = node._protectedChildren;
        var iLen = locChildren.length, jLen = locProtectChildren.length, child;
        for( ; i < iLen; i++ ){
            child = locChildren[i];
            if ( child && child.getLocalZOrder() < 0 )
                child.visit(this);
            else
                break;
        }
        for( ; j < jLen; j++ ) {
            child = locProtectChildren[j];
            if ( child && child.getLocalZOrder() < 0 )
                child.visit(this);
            else
                break;
        }
        for (; i < iLen; i++)
            locChildren[i].visit(this);
        for (; j < jLen; j++)
            locProtectChildren[j].visit(this);
        cc.renderer.pushRenderCommand(this._afterVisitCmdStencil);
        currentStack.top = currentStack.stack.pop();
    };
    proto.scissorClippingVisit = function(parentCmd){
        cc.renderer.pushRenderCommand(this._beforeVisitCmdScissor);
        this.pNodeVisit(parentCmd);
        cc.renderer.pushRenderCommand(this._afterVisitCmdScissor);
    };
    ccui.Layout.WebGLRenderCmd._layer = -1;
    ccui.Layout.WebGLRenderCmd._visit_once = null;
})();
ccui.Margin = ccui.Class.extend({
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
    ctor: function (margin, top, right, bottom) {
        if (margin !== undefined && top === undefined) {
            this.left = margin.left;
            this.top = margin.top;
            this.right = margin.right;
            this.bottom = margin.bottom;
        }
        if (bottom !== undefined) {
            this.left = margin;
            this.top = top;
            this.right = right;
            this.bottom = bottom;
        }
    },
    setMargin: function (l, t, r, b) {
        this.left = l;
        this.top = t;
        this.right = r;
        this.bottom = b;
    },
    equals: function (target) {
        return (this.left === target.left && this.top === target.top && this.right === target.right && this.bottom === target.bottom);
    }
});
ccui.MarginZero = function(){
    return new ccui.Margin(0,0,0,0);
};
ccui.LayoutParameter = ccui.Class.extend({
    _margin: null,
    _layoutParameterType: null,
    ctor: function () {
        this._margin = new ccui.Margin();
        this._layoutParameterType = ccui.LayoutParameter.NONE;
    },
    setMargin: function (margin) {
        if(cc.isObject(margin)){
            this._margin.left = margin.left;
            this._margin.top = margin.top;
            this._margin.right = margin.right;
            this._margin.bottom = margin.bottom;
        }else{
            this._margin.left = arguments[0];
            this._margin.top = arguments[1];
            this._margin.right = arguments[2];
            this._margin.bottom = arguments[3];
        }
    },
    getMargin: function () {
        return this._margin;
    },
    getLayoutType: function () {
        return this._layoutParameterType;
    },
    clone:function(){
        var parameter = this._createCloneInstance();
        parameter._copyProperties(this);
        return parameter;
    },
    _createCloneInstance:function(){
        return new ccui.LayoutParameter();
    },
    _copyProperties:function(model){
        this._margin.bottom = model._margin.bottom;
        this._margin.left = model._margin.left;
        this._margin.right = model._margin.right;
        this._margin.top = model._margin.top;
    }
});
ccui.LayoutParameter.create = function () {
    return new ccui.LayoutParameter();
};
ccui.LayoutParameter.NONE = 0;
ccui.LayoutParameter.LINEAR = 1;
ccui.LayoutParameter.RELATIVE = 2;
ccui.LinearLayoutParameter = ccui.LayoutParameter.extend({
    _linearGravity: null,
    ctor: function () {
        ccui.LayoutParameter.prototype.ctor.call(this);
        this._linearGravity = ccui.LinearLayoutParameter.NONE;
        this._layoutParameterType = ccui.LayoutParameter.LINEAR;
    },
    setGravity: function (gravity) {
        this._linearGravity = gravity;
    },
    getGravity: function () {
        return this._linearGravity;
    },
    _createCloneInstance: function () {
        return new ccui.LinearLayoutParameter();
    },
    _copyProperties: function (model) {
        ccui.LayoutParameter.prototype._copyProperties.call(this, model);
        if (model instanceof ccui.LinearLayoutParameter)
            this.setGravity(model._linearGravity);
    }
});
ccui.LinearLayoutParameter.create = function () {
    return new ccui.LinearLayoutParameter();
};
ccui.LinearLayoutParameter.NONE = 0;
ccui.LinearLayoutParameter.LEFT = 1;
ccui.LinearLayoutParameter.TOP = 2;
ccui.LinearLayoutParameter.RIGHT = 3;
ccui.LinearLayoutParameter.BOTTOM = 4;
ccui.LinearLayoutParameter.CENTER_VERTICAL = 5;
ccui.LinearLayoutParameter.CENTER_HORIZONTAL = 6;
ccui.RelativeLayoutParameter = ccui.LayoutParameter.extend({
    _relativeAlign: null,
    _relativeWidgetName: "",
    _relativeLayoutName: "",
    _put:false,
    ctor: function () {
        ccui.LayoutParameter.prototype.ctor.call(this);
        this._relativeAlign = ccui.RelativeLayoutParameter.NONE;
        this._relativeWidgetName = "";
        this._relativeLayoutName = "";
        this._put = false;
        this._layoutParameterType = ccui.LayoutParameter.RELATIVE;
    },
    setAlign: function (align) {
        this._relativeAlign = align;
    },
    getAlign: function () {
        return this._relativeAlign;
    },
    setRelativeToWidgetName: function (name) {
        this._relativeWidgetName = name;
    },
    getRelativeToWidgetName: function () {
        return this._relativeWidgetName;
    },
    setRelativeName: function (name) {
        this._relativeLayoutName = name;
    },
    getRelativeName: function () {
        return this._relativeLayoutName;
    },
    _createCloneInstance:function(){
        return new ccui.RelativeLayoutParameter();
    },
    _copyProperties:function(model){
        ccui.LayoutParameter.prototype._copyProperties.call(this, model);
        if (model instanceof ccui.RelativeLayoutParameter) {
            this.setAlign(model._relativeAlign);
            this.setRelativeToWidgetName(model._relativeWidgetName);
            this.setRelativeName(model._relativeLayoutName);
        }
    }
});
ccui.RelativeLayoutParameter.create = function () {
    return new ccui.RelativeLayoutParameter();
};
ccui.RelativeLayoutParameter.NONE = 0;
ccui.RelativeLayoutParameter.PARENT_TOP_LEFT = 1;
ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL = 2;
ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT = 3;
ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL = 4;
ccui.RelativeLayoutParameter.CENTER_IN_PARENT = 5;
ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL = 6;
ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM = 7;
ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL = 8;
ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM = 9;
ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN = 10;
ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER = 11;
ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN = 12;
ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN = 13;
ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER = 14;
ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN = 15;
ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN = 16;
ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER = 17;
ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN = 18;
ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN = 19;
ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER = 20;
ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN = 21;
ccui.LINEAR_GRAVITY_NONE = 0;
ccui.LINEAR_GRAVITY_LEFT = 1;
ccui.LINEAR_GRAVITY_TOP = 2;
ccui.LINEAR_GRAVITY_RIGHT = 3;
ccui.LINEAR_GRAVITY_BOTTOM = 4;
ccui.LINEAR_GRAVITY_CENTER_VERTICAL = 5;
ccui.LINEAR_GRAVITY_CENTER_HORIZONTAL = 6;
ccui.RELATIVE_ALIGN_NONE = 0;
ccui.RELATIVE_ALIGN_PARENT_TOP_LEFT = 1;
ccui.RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL = 2;
ccui.RELATIVE_ALIGN_PARENT_TOP_RIGHT = 3;
ccui.RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL = 4;
ccui.RELATIVE_ALIGN_PARENT_CENTER = 5;
ccui.RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL = 6;
ccui.RELATIVE_ALIGN_PARENT_LEFT_BOTTOM = 7;
ccui.RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL = 8;
ccui.RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM = 9;
ccui.RELATIVE_ALIGN_LOCATION_ABOVE_LEFT = 10;
ccui.RELATIVE_ALIGN_LOCATION_ABOVE_CENTER = 11;
ccui.RELATIVE_ALIGN_LOCATION_ABOVE_RIGHT = 12;
ccui.RELATIVE_ALIGN_LOCATION_LEFT_TOP = 13;
ccui.RELATIVE_ALIGN_LOCATION_LEFT_CENTER = 14;
ccui.RELATIVE_ALIGN_LOCATION_LEFT_BOTTOM = 15;
ccui.RELATIVE_ALIGN_LOCATION_RIGHT_TOP = 16;
ccui.RELATIVE_ALIGN_LOCATION_RIGHT_CENTER = 17;
ccui.RELATIVE_ALIGN_LOCATION_RIGHT_BOTTOM = 18;
ccui.RELATIVE_ALIGN_LOCATION_BELOW_TOP = 19;
ccui.RELATIVE_ALIGN_LOCATION_BELOW_CENTER = 20;
ccui.RELATIVE_ALIGN_LOCATION_BELOW_BOTTOM = 21;
ccui.getLayoutManager = function (type) {
    switch (type) {
        case ccui.Layout.LINEAR_VERTICAL:
            return ccui.linearVerticalLayoutManager;
        case ccui.Layout.LINEAR_HORIZONTAL:
            return ccui.linearHorizontalLayoutManager;
        case ccui.Layout.RELATIVE:
            return ccui.relativeLayoutManager;
    }
    return null;
};
ccui.linearVerticalLayoutManager = {
    _doLayout: function(layout){
        var layoutSize = layout._getLayoutContentSize();
        var container = layout._getLayoutElements();
        var topBoundary = layoutSize.height;
        for (var i = 0, len = container.length; i < len; i++) {
            var child = container[i];
            if (child) {
                var layoutParameter = child.getLayoutParameter();
                if (layoutParameter){
                    var childGravity = layoutParameter.getGravity();
                    var ap = child.getAnchorPoint();
                    var cs = child.getContentSize();
                    var finalPosX = ap.x * cs.width;
                    var finalPosY = topBoundary - ((1.0 - ap.y) * cs.height);
                    switch (childGravity){
                        case ccui.LinearLayoutParameter.NONE:
                        case ccui.LinearLayoutParameter.LEFT:
                            break;
                        case ccui.LinearLayoutParameter.RIGHT:
                            finalPosX = layoutSize.width - ((1.0 - ap.x) * cs.width);
                            break;
                        case ccui.LinearLayoutParameter.CENTER_HORIZONTAL:
                            finalPosX = layoutSize.width / 2.0 - cs.width * (0.5 - ap.x);
                            break;
                        default:
                            break;
                    }
                    var mg = layoutParameter.getMargin();
                    finalPosX += mg.left;
                    finalPosY -= mg.top;
                    child.setPosition(finalPosX, finalPosY);
                    topBoundary = child.getPositionY() - ap.y * cs.height - mg.bottom;
                }
            }
        }
    }
};
ccui.linearHorizontalLayoutManager = {
    _doLayout: function(layout){
        var layoutSize = layout._getLayoutContentSize();
        var container = layout._getLayoutElements();
        var leftBoundary = 0.0;
        for (var i = 0, len = container.length;  i < len; i++) {
            var child = container[i];
            if (child) {
                var layoutParameter = child.getLayoutParameter();
                if (layoutParameter){
                    var childGravity = layoutParameter.getGravity();
                    var ap = child.getAnchorPoint();
                    var cs = child.getContentSize();
                    var finalPosX = leftBoundary + (ap.x * cs.width);
                    var finalPosY = layoutSize.height - (1.0 - ap.y) * cs.height;
                    switch (childGravity){
                        case ccui.LinearLayoutParameter.NONE:
                        case ccui.LinearLayoutParameter.TOP:
                            break;
                        case ccui.LinearLayoutParameter.BOTTOM:
                            finalPosY = ap.y * cs.height;
                            break;
                        case ccui.LinearLayoutParameter.CENTER_VERTICAL:
                            finalPosY = layoutSize.height / 2.0 - cs.height * (0.5 - ap.y);
                            break;
                        default:
                            break;
                    }
                    var mg = layoutParameter.getMargin();
                    finalPosX += mg.left;
                    finalPosY -= mg.top;
                    child.setPosition(finalPosX, finalPosY);
                    leftBoundary = child.getRightBoundary() + mg.right;
                }
            }
        }
    }
};
ccui.relativeLayoutManager = {
    _unlayoutChildCount: 0,
    _widgetChildren: [],
    _widget: null,
    _finalPositionX:0,
    _finalPositionY:0,
    _relativeWidgetLP:null,
    _doLayout: function(layout){
        this._widgetChildren = this._getAllWidgets(layout);
        var locChildren = this._widgetChildren;
        while (this._unlayoutChildCount > 0) {
            for (var i = 0, len = locChildren.length;  i < len; i++) {
                this._widget = locChildren[i];
                var layoutParameter = this._widget.getLayoutParameter();
                if (layoutParameter){
                    if (layoutParameter._put)
                        continue;
                    var ret = this._calculateFinalPositionWithRelativeWidget(layout);
                    if (!ret)
                        continue;
                    this._calculateFinalPositionWithRelativeAlign();
                    this._widget.setPosition(this._finalPositionX, this._finalPositionY);
                    layoutParameter._put = true;
                }
            }
            this._unlayoutChildCount--;
        }
        this._widgetChildren.length = 0;
    },
    _getAllWidgets: function(layout){
        var container = layout._getLayoutElements();
        var locWidgetChildren = this._widgetChildren;
        locWidgetChildren.length = 0;
        for (var i = 0, len = container.length; i < len; i++){
            var child = container[i];
            if (child && child instanceof ccui.Widget) {
                var layoutParameter = child.getLayoutParameter();
                layoutParameter._put = false;
                this._unlayoutChildCount++;
                locWidgetChildren.push(child);
            }
        }
        return locWidgetChildren;
    },
    _getRelativeWidget: function(widget){
        var relativeWidget = null;
        var layoutParameter = widget.getLayoutParameter();
        var relativeName = layoutParameter.getRelativeToWidgetName();
        if (relativeName && relativeName.length !== 0) {
            var locChildren =  this._widgetChildren;
            for(var i = 0, len = locChildren.length;  i  < len; i++){
                var child = locChildren[i];
                if (child){
                    var rlayoutParameter = child.getLayoutParameter();
                    if (rlayoutParameter &&  rlayoutParameter.getRelativeName() === relativeName) {
                        relativeWidget = child;
                        this._relativeWidgetLP = rlayoutParameter;
                        break;
                    }
                }
            }
        }
        return relativeWidget;
    },
    _calculateFinalPositionWithRelativeWidget: function(layout){
        var locWidget = this._widget;
        var ap = locWidget.getAnchorPoint();
        var cs = locWidget.getContentSize();
        this._finalPositionX = 0.0;
        this._finalPositionY = 0.0;
        var relativeWidget = this._getRelativeWidget(locWidget);
        var layoutParameter = locWidget.getLayoutParameter();
        var align = layoutParameter.getAlign();
        var layoutSize = layout._getLayoutContentSize();
        switch (align) {
            case ccui.RelativeLayoutParameter.NONE:
            case ccui.RelativeLayoutParameter.PARENT_TOP_LEFT:
                this._finalPositionX = ap.x * cs.width;
                this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height);
                break;
            case ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL:
                this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x);
                this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height);
                break;
            case ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT:
                this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width);
                this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height);
                break;
            case ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL:
                this._finalPositionX = ap.x * cs.width;
                this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y);
                break;
            case ccui.RelativeLayoutParameter.CENTER_IN_PARENT:
                this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x);
                this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y);
                break;
            case ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL:
                this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width);
                this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y);
                break;
            case ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM:
                this._finalPositionX = ap.x * cs.width;
                this._finalPositionY = ap.y * cs.height;
                break;
            case ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL:
                this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x);
                this._finalPositionY = ap.y * cs.height;
                break;
            case ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM:
                this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width);
                this._finalPositionY = ap.y * cs.height;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height;
                    this._finalPositionX = relativeWidget.getLeftBoundary() + ap.x * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    var rbs = relativeWidget.getContentSize();
                    this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height;
                    this._finalPositionX = relativeWidget.getLeftBoundary() + rbs.width * 0.5 + ap.x * cs.width - cs.width * 0.5;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN:
                if (relativeWidget) {
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height;
                    this._finalPositionX = relativeWidget.getRightBoundary() - (1.0 - ap.x) * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getTopBoundary() - (1.0 - ap.y) * cs.height;
                    this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER:
                if (relativeWidget) {
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    var rbs = relativeWidget.getContentSize();
                    this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width;
                    this._finalPositionY = relativeWidget.getBottomBoundary() + rbs.height * 0.5 + ap.y * cs.height - cs.height * 0.5;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN:
                if (relativeWidget) {
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getBottomBoundary() + ap.y * cs.height;
                    this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getTopBoundary() - (1.0 - ap.y) * cs.height;
                    this._finalPositionX = relativeWidget.getRightBoundary() + ap.x * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    var rbs = relativeWidget.getContentSize();
                    var locationRight = relativeWidget.getRightBoundary();
                    this._finalPositionX = locationRight + ap.x * cs.width;
                    this._finalPositionY = relativeWidget.getBottomBoundary() + rbs.height * 0.5 + ap.y * cs.height - cs.height * 0.5;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getBottomBoundary() + ap.y * cs.height;
                    this._finalPositionX = relativeWidget.getRightBoundary() + ap.x * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN:
                if (relativeWidget){
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY =  relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height;
                    this._finalPositionX = relativeWidget.getLeftBoundary() + ap.x * cs.width;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER:
                if (relativeWidget) {
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    var rbs = relativeWidget.getContentSize();
                    this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height;
                    this._finalPositionX = relativeWidget.getLeftBoundary() + rbs.width * 0.5 + ap.x * cs.width - cs.width * 0.5;
                }
                break;
            case ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN:
                if (relativeWidget) {
                    if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
                        return false;
                    this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height;
                    this._finalPositionX = relativeWidget.getRightBoundary() - (1.0 - ap.x) * cs.width;
                }
                break;
            default:
                break;
        }
        return true;
    },
    _calculateFinalPositionWithRelativeAlign: function(){
        var layoutParameter = this._widget.getLayoutParameter();
        var mg = layoutParameter.getMargin();
        var align = layoutParameter.getAlign();
        switch (align) {
            case ccui.RelativeLayoutParameter.NONE:
            case ccui.RelativeLayoutParameter.PARENT_TOP_LEFT:
                this._finalPositionX += mg.left;
                this._finalPositionY -= mg.top;
                break;
            case ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL:
                this._finalPositionY -= mg.top;
                break;
            case ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT:
                this._finalPositionX -= mg.right;
                this._finalPositionY -= mg.top;
                break;
            case ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL:
                this._finalPositionX += mg.left;
                break;
            case ccui.RelativeLayoutParameter.CENTER_IN_PARENT:
                break;
            case ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL:
                this._finalPositionX -= mg.right;
                break;
            case ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM:
                this._finalPositionX += mg.left;
                this._finalPositionY += mg.bottom;
                break;
            case ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL:
                this._finalPositionY += mg.bottom;
                break;
            case ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM:
                this._finalPositionX -= mg.right;
                this._finalPositionY += mg.bottom;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN:
                this._finalPositionY += mg.bottom;
                this._finalPositionX += mg.left;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN:
                this._finalPositionY += mg.bottom;
                this._finalPositionX -= mg.right;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER:
                this._finalPositionY += mg.bottom;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN:
                this._finalPositionX -= mg.right;
                this._finalPositionY -= mg.top;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN:
                this._finalPositionX -= mg.right;
                this._finalPositionY += mg.bottom;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER:
                this._finalPositionX -= mg.right;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN:
                this._finalPositionX += mg.left;
                this._finalPositionY -= mg.top;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN:
                this._finalPositionX += mg.left;
                this._finalPositionY += mg.bottom;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER:
                this._finalPositionX += mg.left;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN:
                this._finalPositionY -= mg.top;
                this._finalPositionX += mg.left;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN:
                this._finalPositionY -= mg.top;
                this._finalPositionX -= mg.right;
                break;
            case ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER:
                this._finalPositionY -= mg.top;
                break;
            default:
                break;
        }
    }
};
ccui.HBox = ccui.Layout.extend({
    ctor: function(size){
        ccui.Layout.prototype.ctor.call(this);
        this.setLayoutType(ccui.Layout.LINEAR_HORIZONTAL);
        if(size) {
            this.setContentSize(size);
        }
    }
});
ccui.HBox.create = function(size){
    return new ccui.HBox(size);
};
ccui.RelativeBox = ccui.Layout.extend({
    ctor: function(size){
        ccui.Layout.prototype.ctor.call(this);
        this.setLayoutType(ccui.Layout.RELATIVE);
        if(size) {
            this.setContentSize(size);
        }
    }
});
ccui.RelativeBox.create = function(size){
    return new ccui.RelativeBox(size);
};
ccui.VBox = ccui.Layout.extend({
    ctor: function(size){
        ccui.Layout.prototype.ctor.call(this);
        this.setLayoutType(ccui.Layout.LINEAR_VERTICAL);
        if (size) {
            this.setContentSize(size);
        }
    },
    initWithSize: function(size){
        if(this.init()){
            return true;
        }
        return false;
    }
});
ccui.VBox.create = function(size){
    return new ccui.VBox(size);
};
ccui.helper = {
    seekWidgetByTag: function (root, tag) {
        if (!root)
            return null;
        if (root.getTag() === tag)
            return root;
        var arrayRootChildren = root.getChildren();
        var length = arrayRootChildren.length;
        for (var i = 0; i < length; i++) {
            var child = arrayRootChildren[i];
            var res = ccui.helper.seekWidgetByTag(child, tag);
            if (res !== null)
                return res;
        }
        return null;
    },
    seekWidgetByName: function (root, name) {
        if (!root)
            return null;
        if (root.getName() === name)
            return root;
        var arrayRootChildren = root.getChildren();
        var length = arrayRootChildren.length;
        for (var i = 0; i < length; i++) {
            var child = arrayRootChildren[i];
            var res = ccui.helper.seekWidgetByName(child, name);
            if (res !== null)
                return res;
        }
        return null;
    },
    seekWidgetByRelativeName: function (root, name) {
        if (!root)
            return null;
        var arrayRootChildren = root.getChildren();
        var length = arrayRootChildren.length;
        for (var i = 0; i < length; i++) {
            var child = arrayRootChildren[i];
            var layoutParameter = child.getLayoutParameter(ccui.LayoutParameter.RELATIVE);
            if (layoutParameter && layoutParameter.getRelativeName() === name)
                return child;
        }
        return null;
    },
    seekActionWidgetByActionTag: function (root, tag) {
        if (!root)
            return null;
        if (root.getActionTag() === tag)
            return root;
        var arrayRootChildren = root.getChildren();
        for (var i = 0; i < arrayRootChildren.length; i++) {
            var child = arrayRootChildren[i];
            var res = ccui.helper.seekActionWidgetByActionTag(child, tag);
            if (res !== null)
                return res;
        }
        return null;
    } ,
    _activeLayout: true,
    doLayout: function(rootNode){
        if(!this._activeLayout)
            return;
        var children = rootNode.getChildren(), node;
        for(var i = 0, len = children.length;i < len; i++) {
            node = children[i];
            var com = node.getComponent(ccui.LayoutComponent.NAME);
            var parent = node.getParent();
            if (null != com && null !== parent && com.refreshLayout)
                com.refreshLayout();
        }
    },
    changeLayoutSystemActiveState: function(active){
        this._activeLayout = active;
    },
    restrictCapInsetRect: function (capInsets, textureSize) {
        var x = capInsets.x, y = capInsets.y;
        var width = capInsets.width, height = capInsets.height;
        if (textureSize.width < width) {
            x = 0.0;
            width = 0.0;
        }
        if (textureSize.height < height) {
            y = 0.0;
            height = 0.0;
        }
        return cc.rect(x, y, width, height);
    },
    _createSpriteFromBase64: function(base64String, key) {
        var texture2D = cc.textureCache.getTextureForKey(key);
        if(!texture2D) {
            var image = new Image();
            image.src = base64String;
            cc.textureCache.cacheImage(key, image);
            texture2D = cc.textureCache.getTextureForKey(key);
        }
        var sprite = new cc.Sprite(texture2D);
        return sprite;
    }
};
ccui.Button = ccui.Widget.extend({
    _buttonNormalRenderer: null,
    _buttonClickedRenderer: null,
    _buttonDisableRenderer: null,
    _titleRenderer: null,
    _normalFileName: "",
    _clickedFileName: "",
    _disabledFileName: "",
    _prevIgnoreSize: true,
    _scale9Enabled: false,
    _capInsetsNormal: null,
    _capInsetsPressed: null,
    _capInsetsDisabled: null,
    _normalTexType: ccui.Widget.LOCAL_TEXTURE,
    _pressedTexType: ccui.Widget.LOCAL_TEXTURE,
    _disabledTexType: ccui.Widget.LOCAL_TEXTURE,
    _normalTextureSize: null,
    _pressedTextureSize: null,
    _disabledTextureSize: null,
    pressedActionEnabled: false,
    _titleColor: null,
    _normalTextureScaleXInSize: 1,
    _normalTextureScaleYInSize: 1,
    _pressedTextureScaleXInSize: 1,
    _pressedTextureScaleYInSize: 1,
    _zoomScale: 0.1,
    _normalTextureLoaded: false,
    _pressedTextureLoaded: false,
    _disabledTextureLoaded: false,
    _className: "Button",
    _normalTextureAdaptDirty: true,
    _pressedTextureAdaptDirty: true,
    _disabledTextureAdaptDirty: true,
    _fontName: "Thonburi",
    _fontSize: 12,
    _type: 0,
    ctor: function (normalImage, selectedImage, disableImage, texType) {
        this._capInsetsNormal = cc.rect(0, 0, 0, 0);
        this._capInsetsPressed = cc.rect(0, 0, 0, 0);
        this._capInsetsDisabled = cc.rect(0, 0, 0, 0);
        this._normalTextureSize = cc.size(0, 0);
        this._pressedTextureSize = cc.size(0, 0);
        this._disabledTextureSize = cc.size(0, 0);
        this._titleColor = cc.color.WHITE;
        ccui.Widget.prototype.ctor.call(this);
        this.setTouchEnabled(true);
        if (normalImage) {
            this.loadTextures(normalImage, selectedImage,disableImage, texType);
        }
    },
    _initRenderer: function () {
        this._buttonNormalRenderer = new cc.Sprite();
        this._buttonClickedRenderer = new cc.Sprite();
        this._buttonDisableRenderer = new cc.Sprite();
        this._titleRenderer = new cc.LabelTTF("");
        this._titleRenderer.setAnchorPoint(0.5, 0.5);
        this.addProtectedChild(this._buttonNormalRenderer, ccui.Button.NORMAL_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._buttonClickedRenderer, ccui.Button.PRESSED_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._buttonDisableRenderer, ccui.Button.DISABLED_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._titleRenderer, ccui.Button.TITLE_RENDERER_ZORDER, -1);
    },
    setScale9Enabled: function (able) {
        if (this._scale9Enabled === able)
            return;
        this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
        this._scale9Enabled = able;
        this.removeProtectedChild(this._buttonNormalRenderer);
        this.removeProtectedChild(this._buttonClickedRenderer);
        this.removeProtectedChild(this._buttonDisableRenderer);
        if (this._scale9Enabled) {
            this._buttonNormalRenderer = new ccui.Scale9Sprite();
            this._buttonClickedRenderer = new ccui.Scale9Sprite();
            this._buttonDisableRenderer = new ccui.Scale9Sprite();
        } else {
            this._buttonNormalRenderer = new cc.Sprite();
            this._buttonClickedRenderer = new cc.Sprite();
            this._buttonDisableRenderer = new cc.Sprite();
        }
        this._buttonClickedRenderer.setVisible(false);
        this._buttonDisableRenderer.setVisible(false);
        this.loadTextureNormal(this._normalFileName, this._normalTexType);
        this.loadTexturePressed(this._clickedFileName, this._pressedTexType);
        this.loadTextureDisabled(this._disabledFileName, this._disabledTexType);
        this.addProtectedChild(this._buttonNormalRenderer, ccui.Button.NORMAL_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._buttonClickedRenderer, ccui.Button.PRESSED_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._buttonDisableRenderer, ccui.Button.DISABLED_RENDERER_ZORDER, -1);
        if (this._scale9Enabled) {
            var ignoreBefore = this._ignoreSize;
            this.ignoreContentAdaptWithSize(false);
            this._prevIgnoreSize = ignoreBefore;
        } else {
            this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
        }
        this.setCapInsetsNormalRenderer(this._capInsetsNormal);
        this.setCapInsetsPressedRenderer(this._capInsetsPressed);
        this.setCapInsetsDisabledRenderer(this._capInsetsDisabled);
        this.setBright(this._bright);
        this._normalTextureAdaptDirty = true;
        this._pressedTextureAdaptDirty = true;
        this._disabledTextureAdaptDirty = true;
    },
    isScale9Enabled: function () {
        return this._scale9Enabled;
    },
    ignoreContentAdaptWithSize: function (ignore) {
        if(this._unifySize){
            this._updateContentSize();
            return;
        }
        if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
            ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
            this._prevIgnoreSize = ignore;
        }
    },
    getVirtualRendererSize: function(){
        if (this._unifySize)
            return this._getNormalSize();
        if (!this._normalTextureLoaded && this._titleRenderer.getString().length > 0) {
            return this._titleRenderer.getContentSize();
        }
        return cc.size(this._normalTextureSize);
    },
    loadTextures: function (normal, selected, disabled, texType) {
        this.loadTextureNormal(normal, texType);
        this.loadTexturePressed(selected, texType);
        this.loadTextureDisabled(disabled, texType);
    },
    loadTextureNormal: function (normal, texType) {
        if (!normal)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._normalFileName = normal;
        this._normalTexType = texType;
        var self = this;
        var normalRenderer = this._buttonNormalRenderer;
        if(!normalRenderer._textureLoaded){
            normalRenderer.addEventListener("load", function(){
                self.loadTextureNormal(self._normalFileName, self._normalTexType);
            });
        }
        switch (this._normalTexType){
            case ccui.Widget.LOCAL_TEXTURE:
                normalRenderer.initWithFile(normal);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                normalRenderer.initWithSpriteFrameName(normal);
                break;
            default:
                break;
        }
        this._normalTextureLoaded = normalRenderer._textureLoaded;
        this._normalTextureSize = this._buttonNormalRenderer.getContentSize();
        this._updateChildrenDisplayedRGBA();
        if (this._unifySize){
            if (this._scale9Enabled){
                normalRenderer.setCapInsets(this._capInsetsNormal);
                this._updateContentSizeWithTextureSize(this._getNormalSize());
            }
        }else
            this._updateContentSizeWithTextureSize(this._normalTextureSize);
        this._normalTextureAdaptDirty = true;
        this._findLayout();
    },
    loadTexturePressed: function (selected, texType) {
        if (!selected)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._clickedFileName = selected;
        this._pressedTexType = texType;
        var self = this;
        var clickedRenderer = this._buttonClickedRenderer;
        if(!clickedRenderer._textureLoaded){
            clickedRenderer.addEventListener("load", function(){
                self.loadTexturePressed(self._clickedFileName, self._pressedTexType);
            });
        }
        switch (this._pressedTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                clickedRenderer.initWithFile(selected);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                clickedRenderer.initWithSpriteFrameName(selected);
                break;
            default:
                break;
        }
        if (this._scale9Enabled)
            clickedRenderer.setCapInsets(this._capInsetsPressed);
        this._pressedTextureSize = this._buttonClickedRenderer.getContentSize();
        this._updateChildrenDisplayedRGBA();
        this._pressedTextureLoaded = true;
        this._pressedTextureAdaptDirty = true;
        this._findLayout();
    },
    loadTextureDisabled: function (disabled, texType) {
        if (!disabled)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._disabledFileName = disabled;
        this._disabledTexType = texType;
        var self = this;
        var disabledRenderer = this._buttonDisableRenderer;
        if(!disabledRenderer._textureLoaded){
            disabledRenderer.addEventListener("load", function() {
                self.loadTextureDisabled(self._disabledFileName, self._disabledTexType);
            });
        }
        switch (this._disabledTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                disabledRenderer.initWithFile(disabled);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                disabledRenderer.initWithSpriteFrameName(disabled);
                break;
            default:
                break;
        }
        if (this._scale9Enabled)
            disabledRenderer.setCapInsets(this._capInsetsDisabled);
        this._disabledTextureSize = this._buttonDisableRenderer.getContentSize();
        this._updateChildrenDisplayedRGBA();
        this._disabledTextureLoaded = true;
        this._disabledTextureAdaptDirty = true;
        this._findLayout();
    },
    setCapInsets: function (capInsets) {
        this.setCapInsetsNormalRenderer(capInsets);
        this.setCapInsetsPressedRenderer(capInsets);
        this.setCapInsetsDisabledRenderer(capInsets);
    },
    setCapInsetsNormalRenderer: function (capInsets) {
        if(!capInsets)
            return;
        var x = capInsets.x, y = capInsets.y;
        var width = capInsets.width, height = capInsets.height;
        if (this._normalTextureSize.width < width){
            x = 0;
            width = 0;
        }
        if (this._normalTextureSize.height < height){
            y = 0;
            height = 0;
        }
        var locInsets = this._capInsetsNormal;
        locInsets.x = x;
        locInsets.y = y;
        locInsets.width = width;
        locInsets.height = height;
        if (!this._scale9Enabled)
            return;
        this._buttonNormalRenderer.setCapInsets(locInsets);
    },
    getCapInsetsNormalRenderer:function(){
        return cc.rect(this._capInsetsNormal);
    },
    setCapInsetsPressedRenderer: function (capInsets) {
        if(!capInsets || !this._scale9Enabled)
            return;
        var x = capInsets.x, y = capInsets.y;
        var width = capInsets.width, height = capInsets.height;
        if (this._pressedTextureSize.width < width) {
            x = 0;
            width = 0;
        }
        if (this._pressedTextureSize.height < height) {
            y = 0;
            height = 0;
        }
        var locInsets = this._capInsetsPressed;
        locInsets.x = x;
        locInsets.y = y;
        locInsets.width = width;
        locInsets.height = height;
        this._buttonClickedRenderer.setCapInsets(locInsets);
    },
    getCapInsetsPressedRenderer: function () {
        return cc.rect(this._capInsetsPressed);
    },
    setCapInsetsDisabledRenderer: function (capInsets) {
        if(!capInsets || !this._scale9Enabled)
            return;
        var x = capInsets.x, y = capInsets.y;
        var width = capInsets.width, height = capInsets.height;
        if (this._disabledTextureSize.width < width) {
            x = 0;
            width = 0;
        }
        if (this._disabledTextureSize.height < height) {
            y = 0;
            height = 0;
        }
        var locInsets = this._capInsetsDisabled;
        locInsets.x = x;
        locInsets.y = y;
        locInsets.width = width;
        locInsets.height = height;
        this._buttonDisableRenderer.setCapInsets(locInsets);
    },
    getCapInsetsDisabledRenderer: function () {
        return cc.rect(this._capInsetsDisabled);
    },
    _onPressStateChangedToNormal: function () {
        this._buttonNormalRenderer.setVisible(true);
        this._buttonClickedRenderer.setVisible(false);
        this._buttonDisableRenderer.setVisible(false);
        if (this._scale9Enabled)
            this._buttonNormalRenderer.setState( ccui.Scale9Sprite.state.NORMAL);
        if (this._pressedTextureLoaded) {
            if (this.pressedActionEnabled){
                this._buttonNormalRenderer.stopAllActions();
                this._buttonClickedRenderer.stopAllActions();
                this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
                this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
                this._titleRenderer.stopAllActions();
                if (this._unifySize){
                    var zoomTitleAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1, 1);
                    this._titleRenderer.runAction(zoomTitleAction);
                }else{
                    this._titleRenderer.setScaleX(1);
                    this._titleRenderer.setScaleY(1);
                }
            }
        } else {
            this._buttonNormalRenderer.stopAllActions();
            this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
            this._titleRenderer.stopAllActions();
            if (this._scale9Enabled)
                this._buttonNormalRenderer.setColor(cc.color.WHITE);
            this._titleRenderer.setScaleX(1);
            this._titleRenderer.setScaleY(1);
        }
    },
    _onPressStateChangedToPressed: function () {
        var locNormalRenderer = this._buttonNormalRenderer;
        if (this._scale9Enabled)
            locNormalRenderer.setState(ccui.Scale9Sprite.state.NORMAL);
        if (this._pressedTextureLoaded) {
            locNormalRenderer.setVisible(false);
            this._buttonClickedRenderer.setVisible(true);
            this._buttonDisableRenderer.setVisible(false);
            if (this.pressedActionEnabled) {
                locNormalRenderer.stopAllActions();
                this._buttonClickedRenderer.stopAllActions();
                var zoomAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, this._pressedTextureScaleXInSize + this._zoomScale,
                        this._pressedTextureScaleYInSize + this._zoomScale);
                this._buttonClickedRenderer.runAction(zoomAction);
                locNormalRenderer.setScale(this._pressedTextureScaleXInSize + this._zoomScale, this._pressedTextureScaleYInSize + this._zoomScale);
                this._titleRenderer.stopAllActions();
                this._titleRenderer.runAction(cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1 + this._zoomScale, 1 + this._zoomScale));
            }
        } else {
            locNormalRenderer.setVisible(true);
            this._buttonClickedRenderer.setVisible(true);
            this._buttonDisableRenderer.setVisible(false);
            locNormalRenderer.stopAllActions();
            locNormalRenderer.setScale(this._normalTextureScaleXInSize + this._zoomScale, this._normalTextureScaleYInSize + this._zoomScale);
            this._titleRenderer.stopAllActions();
            this._titleRenderer.setScaleX(1 + this._zoomScale);
            this._titleRenderer.setScaleY(1 + this._zoomScale);
        }
    },
    _onPressStateChangedToDisabled: function () {
        if (!this._disabledTextureLoaded){
            if (this._normalTextureLoaded && this._scale9Enabled)
                this._buttonNormalRenderer.setState(ccui.Scale9Sprite.state.GRAY);
        }else{
            this._buttonNormalRenderer.setVisible(false);
            this._buttonDisableRenderer.setVisible(true);
        }
        this._buttonClickedRenderer.setVisible(false);
        this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
        this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
    },
    _updateContentSize: function(){
        if (this._unifySize){
            if (this._scale9Enabled)
                ccui.ProtectedNode.setContentSize(this._customSize);
            else{
                var s = this._getNormalSize();
                ccui.ProtectedNode.setContentSize(s);
            }
            this._onSizeChanged();
            return;
        }
        if (this._ignoreSize)
            this.setContentSize(this.getVirtualRendererSize());
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._updateTitleLocation();
        this._normalTextureAdaptDirty = true;
        this._pressedTextureAdaptDirty = true;
        this._disabledTextureAdaptDirty = true;
    },
    getVirtualRenderer: function () {
        if (this._bright) {
            switch (this._brightStyle) {
                case ccui.Widget.BRIGHT_STYLE_NORMAL:
                    return this._buttonNormalRenderer;
                case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
                    return this._buttonClickedRenderer;
                default:
                    return null;
            }
        } else
            return this._buttonDisableRenderer;
    },
    _normalTextureScaleChangedWithSize: function () {
        if(this._ignoreSize && !this._unifySize){
            if(!this._scale9Enabled){
                this._buttonNormalRenderer.setScale(1);
                this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
            }
        }else{
            if (this._scale9Enabled){
                this._buttonNormalRenderer.setPreferredSize(this._contentSize);
                this._normalTextureScaleXInSize = this._normalTextureScaleYInSize = 1;
                this._buttonNormalRenderer.setScale(this._normalTextureScaleXInSize, this._normalTextureScaleYInSize);
            }else{
                var textureSize = this._normalTextureSize;
                if (textureSize.width <= 0 || textureSize.height <= 0)
                {
                    this._buttonNormalRenderer.setScale(1);
                    return;
                }
                var scaleX = this._contentSize.width / textureSize.width;
                var scaleY = this._contentSize.height / textureSize.height;
                this._buttonNormalRenderer.setScaleX(scaleX);
                this._buttonNormalRenderer.setScaleY(scaleY);
                this._normalTextureScaleXInSize = scaleX;
                this._normalTextureScaleYInSize = scaleY;
            }
        }
        this._buttonNormalRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
    },
    _pressedTextureScaleChangedWithSize: function () {
        if (this._ignoreSize && !this._unifySize) {
            if (!this._scale9Enabled) {
                this._buttonClickedRenderer.setScale(1);
                this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
            }
        } else {
            if (this._scale9Enabled) {
                this._buttonClickedRenderer.setPreferredSize(this._contentSize);
                this._pressedTextureScaleXInSize = this._pressedTextureScaleYInSize = 1;
                this._buttonClickedRenderer.setScale(this._pressedTextureScaleXInSize, this._pressedTextureScaleYInSize);
            } else {
                var textureSize = this._pressedTextureSize;
                if (textureSize.width <= 0 || textureSize.height <= 0) {
                    this._buttonClickedRenderer.setScale(1);
                    return;
                }
                var scaleX = this._contentSize.width / textureSize.width;
                var scaleY = this._contentSize.height / textureSize.height;
                this._buttonClickedRenderer.setScaleX(scaleX);
                this._buttonClickedRenderer.setScaleY(scaleY);
                this._pressedTextureScaleXInSize = scaleX;
                this._pressedTextureScaleYInSize = scaleY;
            }
        }
        this._buttonClickedRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
    },
    _disabledTextureScaleChangedWithSize: function () {
        if(this._ignoreSize && !this._unifySize){
            if (this._scale9Enabled)
                this._buttonDisableRenderer.setScale(1);
        }else {
            if (this._scale9Enabled){
                this._buttonDisableRenderer.setScale(1);
                this._buttonDisableRenderer.setPreferredSize(this._contentSize);
            }else{
                var textureSize = this._disabledTextureSize;
                if (textureSize.width <= 0 || textureSize.height <= 0) {
                    this._buttonDisableRenderer.setScale(1);
                    return;
                }
                var scaleX = this._contentSize.width / textureSize.width;
                var scaleY = this._contentSize.height / textureSize.height;
                this._buttonDisableRenderer.setScaleX(scaleX);
                this._buttonDisableRenderer.setScaleY(scaleY);
            }
        }
        this._buttonDisableRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
    },
    _adaptRenderers: function(){
        if (this._normalTextureAdaptDirty) {
            this._normalTextureScaleChangedWithSize();
            this._normalTextureAdaptDirty = false;
        }
        if (this._pressedTextureAdaptDirty) {
            this._pressedTextureScaleChangedWithSize();
            this._pressedTextureAdaptDirty = false;
        }
        if (this._disabledTextureAdaptDirty) {
            this._disabledTextureScaleChangedWithSize();
            this._disabledTextureAdaptDirty = false;
        }
    },
    _updateTitleLocation: function(){
        this._titleRenderer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
    },
    setPressedActionEnabled: function (enabled) {
        this.pressedActionEnabled = enabled;
    },
    setTitleText: function (text) {
        if(text === this.getTitleText())
            return;
        this._titleRenderer.setString(text);
        if (this._ignoreSize){
            var s = this.getVirtualRendererSize();
            this.setContentSize(s);
        }else{
            this._titleRenderer._renderCmd._updateTTF();
        }
    },
    getTitleText: function () {
        return this._titleRenderer.getString();
    },
    setTitleColor: function (color) {
        this._titleRenderer.setFontFillColor(color);
    },
    getTitleColor: function () {
        return this._titleRenderer._getFillStyle();
    },
    setTitleFontSize: function (size) {
        this._titleRenderer.setFontSize(size);
        this._fontSize = size;
    },
    getTitleFontSize: function () {
        return this._titleRenderer.getFontSize();
    },
    setZoomScale: function(scale){
        this._zoomScale = scale;
    },
    getZoomScale: function(){
        return this._zoomScale;
    },
    getNormalTextureSize: function(){
        return this._normalTextureSize;
    },
    setTitleFontName: function (fontName) {
        this._titleRenderer.setFontName(fontName);
        this._fontName = fontName;
    },
    getTitleRenderer: function(){
        return this._titleRenderer;
    },
    getTitleFontName: function () {
        return this._titleRenderer.getFontName();
    },
    _setTitleFont: function (font) {
        this._titleRenderer.font = font;
    },
    _getTitleFont: function () {
        return this._titleRenderer.font;
    },
    getDescription: function () {
        return "Button";
    },
    _createCloneInstance: function () {
        return new ccui.Button();
    },
    _copySpecialProperties: function (uiButton) {
        this._prevIgnoreSize = uiButton._prevIgnoreSize;
        this.setScale9Enabled(uiButton._scale9Enabled);
        this.loadTextureNormal(uiButton._normalFileName, uiButton._normalTexType);
        this.loadTexturePressed(uiButton._clickedFileName, uiButton._pressedTexType);
        this.loadTextureDisabled(uiButton._disabledFileName, uiButton._disabledTexType);
        this.setCapInsetsNormalRenderer(uiButton._capInsetsNormal);
        this.setCapInsetsPressedRenderer(uiButton._capInsetsPressed);
        this.setCapInsetsDisabledRenderer(uiButton._capInsetsDisabled);
        this.setTitleText(uiButton.getTitleText());
        this.setTitleFontName(uiButton.getTitleFontName());
        this.setTitleFontSize(uiButton.getTitleFontSize());
        this.setTitleColor(uiButton.getTitleColor());
        this.setPressedActionEnabled(uiButton.pressedActionEnabled);
        this.setZoomScale(uiButton._zoomScale);
    },
    _getNormalSize: function(){
        var titleSize;
        if (this._titleRenderer !== null)
            titleSize = this._titleRenderer.getContentSize();
        var imageSize;
        if (this._buttonNormalRenderer !== null)
            imageSize = this._buttonNormalRenderer.getContentSize();
        var width = titleSize.width > imageSize.width ? titleSize.width : imageSize.width;
        var height = titleSize.height > imageSize.height ? titleSize.height : imageSize.height;
        return cc.size(width,height);
    }
});
var _p = ccui.Button.prototype;
_p.titleText;
cc.defineGetterSetter(_p, "titleText", _p.getTitleText, _p.setTitleText);
_p.titleFont;
cc.defineGetterSetter(_p, "titleFont", _p._getTitleFont, _p._setTitleFont);
_p.titleFontSize;
cc.defineGetterSetter(_p, "titleFontSize", _p.getTitleFontSize, _p.setTitleFontSize);
_p.titleFontName;
cc.defineGetterSetter(_p, "titleFontName", _p.getTitleFontName, _p.setTitleFontName);
_p.titleColor;
cc.defineGetterSetter(_p, "titleColor", _p.getTitleColor, _p.setTitleColor);
_p = null;
ccui.Button.create = function (normalImage, selectedImage, disableImage, texType) {
    return new ccui.Button(normalImage, selectedImage, disableImage, texType);
};
ccui.Button.NORMAL_RENDERER_ZORDER = -2;
ccui.Button.PRESSED_RENDERER_ZORDER = -2;
ccui.Button.DISABLED_RENDERER_ZORDER = -2;
ccui.Button.TITLE_RENDERER_ZORDER = -1;
ccui.Button.ZOOM_ACTION_TIME_STEP = 0.05;
ccui.Button.SYSTEM = 0;
ccui.Button.TTF = 1;
ccui.CheckBox = ccui.Widget.extend({
    _backGroundBoxRenderer: null,
    _backGroundSelectedBoxRenderer: null,
    _frontCrossRenderer: null,
    _backGroundBoxDisabledRenderer: null,
    _frontCrossDisabledRenderer: null,
    _isSelected: true,
    _checkBoxEventListener: null,
    _checkBoxEventSelector:null,
    _backGroundTexType: ccui.Widget.LOCAL_TEXTURE,
    _backGroundSelectedTexType: ccui.Widget.LOCAL_TEXTURE,
    _frontCrossTexType: ccui.Widget.LOCAL_TEXTURE,
    _backGroundDisabledTexType: ccui.Widget.LOCAL_TEXTURE,
    _frontCrossDisabledTexType: ccui.Widget.LOCAL_TEXTURE,
    _backGroundFileName: "",
    _backGroundSelectedFileName: "",
    _frontCrossFileName: "",
    _backGroundDisabledFileName: "",
    _frontCrossDisabledFileName: "",
    _className: "CheckBox",
    _zoomScale: 0.1,
    _backgroundTextureScaleX: 0.1,
    _backgroundTextureScaleY: 0.1,
    _backGroundBoxRendererAdaptDirty:true,
    _backGroundSelectedBoxRendererAdaptDirty:true,
    _frontCrossRendererAdaptDirty: true,
    _backGroundBoxDisabledRendererAdaptDirty: true,
    _frontCrossDisabledRendererAdaptDirty: true,
    ctor: function (backGround, backGroundSelected,cross,backGroundDisabled,frontCrossDisabled,texType) {
        ccui.Widget.prototype.ctor.call(this);
        this.setTouchEnabled(true);
        var strNum = 0;
        for(var i=0; i<arguments.length; i++){
            var type = typeof arguments[i];
            if(type === "string"){
                if(isNaN(arguments[i] - 0))
                    strNum++;
                else{
                    texType = arguments[i];
                    arguments[i] = undefined;
                }
            }else if(type === "number")
                strNum++;
        }
        switch(strNum){
            case 2:
                texType = cross;
                cross = backGroundSelected;
                backGroundSelected = undefined;
        }
        texType = texType === undefined ? 0 : texType;
        this._isSelected = true;
        this.setSelected(false);
        this.loadTextures(backGround, backGroundSelected, cross, backGroundDisabled, frontCrossDisabled, texType);
    },
    _initRenderer: function () {
        this._backGroundBoxRenderer = new cc.Sprite();
        this._backGroundSelectedBoxRenderer = new cc.Sprite();
        this._frontCrossRenderer = new cc.Sprite();
        this._backGroundBoxDisabledRenderer = new cc.Sprite();
        this._frontCrossDisabledRenderer = new cc.Sprite();
        this.addProtectedChild(this._backGroundBoxRenderer, ccui.CheckBox.BOX_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._backGroundSelectedBoxRenderer, ccui.CheckBox.BOX_SELECTED_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._frontCrossRenderer, ccui.CheckBox.FRONT_CROSS_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._backGroundBoxDisabledRenderer, ccui.CheckBox.BOX_DISABLED_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._frontCrossDisabledRenderer, ccui.CheckBox.FRONT_CROSS_DISABLED_RENDERER_ZORDER, -1);
    },
    loadTextures: function (backGround, backGroundSelected, cross, backGroundDisabled, frontCrossDisabled, texType) {
        backGround && this.loadTextureBackGround(backGround, texType);
        backGroundSelected && this.loadTextureBackGroundSelected(backGroundSelected, texType);
        cross && this.loadTextureFrontCross(cross, texType);
        backGroundDisabled && this.loadTextureBackGroundDisabled(backGroundDisabled, texType);
        frontCrossDisabled && this.loadTextureFrontCrossDisabled(frontCrossDisabled, texType);
    },
    loadTextureBackGround: function (backGround, texType) {
        if (!backGround)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._backGroundFileName = backGround;
        this._backGroundTexType = texType;
        var bgBoxRenderer = this._backGroundBoxRenderer;
        if(!bgBoxRenderer._textureLoaded){
            bgBoxRenderer.addEventListener("load", function(){
                this._updateContentSizeWithTextureSize(this._backGroundBoxRenderer.getContentSize());
                this.loadTextureBackGround(this._backGroundFileName, this._backGroundTexType);
            }, this);
        }else{
            this._backGroundBoxRenderer.setContentSize(this._customSize);
        }
        switch (this._backGroundTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                bgBoxRenderer.initWithFile(backGround);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                bgBoxRenderer.initWithSpriteFrameName(backGround);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._updateContentSizeWithTextureSize(this._backGroundBoxRenderer.getContentSize());
        this._backGroundBoxRendererAdaptDirty = true;
        this._findLayout();
    },
    loadTextureBackGroundSelected: function (backGroundSelected, texType) {
        if (!backGroundSelected)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._backGroundSelectedFileName = backGroundSelected;
        this._backGroundSelectedTexType = texType;
        var backGroundSelectedBoxRenderer = this._backGroundSelectedBoxRenderer;
        if(!backGroundSelectedBoxRenderer._textureLoaded){
            backGroundSelectedBoxRenderer.addEventListener("load", function(){
                this.loadTextureBackGroundSelected(this._backGroundSelectedFileName, this._backGroundSelectedTexType);
            }, this);
        }
        switch (this._backGroundSelectedTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                backGroundSelectedBoxRenderer.initWithFile(backGroundSelected);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                backGroundSelectedBoxRenderer.initWithSpriteFrameName(backGroundSelected);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._backGroundSelectedBoxRendererAdaptDirty = true;
        this._findLayout();
    },
    loadTextureFrontCross: function (cross, texType) {
        if (!cross)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._frontCrossFileName = cross;
        this._frontCrossTexType = texType;
        var self = this;
        var frontCrossRenderer = this._frontCrossRenderer;
        if(!frontCrossRenderer._textureLoaded){
            frontCrossRenderer.addEventListener("load", function(){
                this.loadTextureFrontCross(this._frontCrossFileName, this._frontCrossTexType);
            }, this);
        }
        switch (this._frontCrossTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                frontCrossRenderer.initWithFile(cross);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                frontCrossRenderer.initWithSpriteFrameName(cross);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._frontCrossRendererAdaptDirty = true;
        this._findLayout();
    },
    loadTextureBackGroundDisabled: function (backGroundDisabled, texType) {
        if (!backGroundDisabled)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._backGroundDisabledFileName = backGroundDisabled;
        this._backGroundDisabledTexType = texType;
        var self = this;
        var backGroundBoxDisabledRenderer = this._backGroundBoxDisabledRenderer;
        if(!backGroundBoxDisabledRenderer._textureLoaded){
            backGroundBoxDisabledRenderer.addEventListener("load", function(){
                this.loadTextureBackGroundDisabled(this._backGroundDisabledFileName, this._backGroundDisabledTexType);
            }, this);
        }
        switch (this._backGroundDisabledTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                backGroundBoxDisabledRenderer.initWithFile(backGroundDisabled);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                backGroundBoxDisabledRenderer.initWithSpriteFrameName(backGroundDisabled);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._backGroundBoxDisabledRendererAdaptDirty = true;
        this._findLayout();
    },
    loadTextureFrontCrossDisabled: function (frontCrossDisabled, texType) {
        if (!frontCrossDisabled)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._frontCrossDisabledFileName = frontCrossDisabled;
        this._frontCrossDisabledTexType = texType;
        var self = this;
        var frontCrossDisabledRenderer = this._frontCrossDisabledRenderer;
        if(!frontCrossDisabledRenderer._textureLoaded){
            frontCrossDisabledRenderer.addEventListener("load", function(){
                this.loadTextureFrontCrossDisabled(this._frontCrossDisabledFileName, this._frontCrossDisabledTexType);
            }, this);
        }
        switch (this._frontCrossDisabledTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                frontCrossDisabledRenderer.initWithFile(frontCrossDisabled);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                frontCrossDisabledRenderer.initWithSpriteFrameName(frontCrossDisabled);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._frontCrossDisabledRendererAdaptDirty = true;
        this._findLayout();
    },
    _onPressStateChangedToNormal: function () {
        this._backGroundBoxRenderer.setVisible(true);
        this._backGroundSelectedBoxRenderer.setVisible(false);
        this._backGroundBoxDisabledRenderer.setVisible(false);
        this._frontCrossDisabledRenderer.setVisible(false);
        this._backGroundBoxRenderer.setScale(this._backgroundTextureScaleX, this._backgroundTextureScaleY);
        this._frontCrossRenderer.setScale(this._backgroundTextureScaleX, this._backgroundTextureScaleY);
        if (this._isSelected){
            this._frontCrossRenderer.setVisible(true);
            this._frontCrossRendererAdaptDirty = true;
        }
    },
    _onPressStateChangedToPressed: function () {
        if (!this._backGroundSelectedFileName){
            this._backGroundBoxRenderer.setScale(this._backgroundTextureScaleX + this._zoomScale, this._backgroundTextureScaleY + this._zoomScale);
            this._frontCrossRenderer.setScale(this._backgroundTextureScaleX + this._zoomScale, this._backgroundTextureScaleY + this._zoomScale);
        }else{
            this._backGroundBoxRenderer.setVisible(false);
            this._backGroundSelectedBoxRenderer.setVisible(true);
            this._backGroundBoxDisabledRenderer.setVisible(false);
            this._frontCrossDisabledRenderer.setVisible(false);
        }
    },
    _onPressStateChangedToDisabled: function () {
        if (this._backGroundDisabledFileName && this._frontCrossDisabledFileName){
            this._backGroundBoxRenderer.setVisible(false);
            this._backGroundBoxDisabledRenderer.setVisible(true);
        }
        this._backGroundSelectedBoxRenderer.setVisible(false);
        this._frontCrossRenderer.setVisible(false);
        this._backGroundBoxRenderer.setScale(this._backgroundTextureScaleX, this._backgroundTextureScaleY);
        this._frontCrossRenderer.setScale(this._backgroundTextureScaleX, this._backgroundTextureScaleY);
        if (this._isSelected) {
            this._frontCrossDisabledRenderer.setVisible(true);
            this._frontCrossDisabledRendererAdaptDirty = true;
        }
    },
    setZoomScale: function(scale){
        this._zoomScale = scale;
    },
    getZoomScale: function(){
        return this._zoomScale;
    },
    setSelectedState: function(selected){
        this.setSelected(selected);
    },
    setSelected: function (selected) {
        if (selected === this._isSelected)
            return;
        this._isSelected = selected;
        this._frontCrossRenderer.setVisible(this._isSelected);
    },
    getSelectedState: function(){
        return this.isSelected();
    },
    isSelected: function () {
        return this._isSelected;
    },
    _selectedEvent: function () {
        if(this._checkBoxEventSelector){
            if (this._checkBoxEventListener)
                this._checkBoxEventSelector.call(this._checkBoxEventListener, this, ccui.CheckBox.EVENT_SELECTED);
            else
                this._checkBoxEventSelector(this, ccui.CheckBox.EVENT_SELECTED);
        }
    },
    _unSelectedEvent: function () {
        if(this._checkBoxEventSelector){
            if (this._checkBoxEventListener)
                this._checkBoxEventSelector.call(this._checkBoxEventListener, this, ccui.CheckBox.EVENT_UNSELECTED);
            else
                this._checkBoxEventSelector(this, ccui.CheckBox.EVENT_UNSELECTED);
        }
    },
    _releaseUpEvent: function(){
        ccui.Widget.prototype._releaseUpEvent.call(this);
        if (this._isSelected){
            this.setSelected(false);
            this._unSelectedEvent();
        } else {
            this.setSelected(true);
            this._selectedEvent();
        }
    },
    addEventListenerCheckBox: function (selector, target) {
        this.addEventListener(selector, target);
    },
    addEventListener: function(selector, target){
        this._checkBoxEventSelector = selector;
        this._checkBoxEventListener = target;
    },
    getVirtualRendererSize: function(){
        return this._backGroundBoxRenderer.getContentSize();
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._backGroundBoxRendererAdaptDirty = true;
        this._backGroundSelectedBoxRendererAdaptDirty = true;
        this._frontCrossRendererAdaptDirty = true;
        this._backGroundBoxDisabledRendererAdaptDirty = true;
        this._frontCrossDisabledRendererAdaptDirty = true;
    },
    getVirtualRenderer: function () {
        return this._backGroundBoxRenderer;
    },
    _backGroundTextureScaleChangedWithSize: function () {
        var locRenderer = this._backGroundBoxRenderer, locContentSize = this._contentSize;
        if (this._ignoreSize){
            locRenderer.setScale(1.0);
            this._backgroundTextureScaleX = this._backgroundTextureScaleY = 1;
        }else{
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0){
                locRenderer.setScale(1.0);
                this._backgroundTextureScaleX = this._backgroundTextureScaleY = 1;
                return;
            }
            var scaleX = locContentSize.width / textureSize.width;
            var scaleY = locContentSize.height / textureSize.height;
            this._backgroundTextureScaleX = scaleX;
            this._backgroundTextureScaleY = scaleY;
            locRenderer.setScaleX(scaleX);
            locRenderer.setScaleY(scaleY);
        }
        locRenderer.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
    },
    _backGroundSelectedTextureScaleChangedWithSize: function () {
        var locRenderer = this._backGroundSelectedBoxRenderer, locContentSize = this._contentSize;
        if (this._ignoreSize)
            locRenderer.setScale(1.0);
        else {
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                locRenderer.setScale(1.0);
                return;
            }
            var scaleX = locContentSize.width / textureSize.width;
            var scaleY = locContentSize.height / textureSize.height;
            locRenderer.setScaleX(scaleX);
            locRenderer.setScaleY(scaleY);
        }
        locRenderer.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
    },
    _frontCrossTextureScaleChangedWithSize: function () {
        var locRenderer = this._frontCrossRenderer, locContentSize = this._contentSize;
        if (this._ignoreSize)
            locRenderer.setScale(1.0);
        else {
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                locRenderer.setScale(1.0);
                return;
            }
            var scaleX = locContentSize.width / textureSize.width;
            var scaleY = locContentSize.height / textureSize.height;
            locRenderer.setScaleX(scaleX);
            locRenderer.setScaleY(scaleY);
        }
        locRenderer.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
    },
    _backGroundDisabledTextureScaleChangedWithSize: function () {
        var locRenderer = this._backGroundBoxDisabledRenderer, locContentSize = this._contentSize;
        if (this._ignoreSize)
            locRenderer.setScale(1.0);
        else {
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                locRenderer.setScale(1.0);
                return;
            }
            var scaleX = locContentSize.width / textureSize.width;
            var scaleY = locContentSize.height / textureSize.height;
            locRenderer.setScaleX(scaleX);
            locRenderer.setScaleY(scaleY);
        }
        locRenderer.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
    },
    _frontCrossDisabledTextureScaleChangedWithSize: function () {
        var locRenderer = this._frontCrossDisabledRenderer, locContentSize = this._contentSize;
        if (this._ignoreSize) {
            locRenderer.setScale(1.0);
        } else {
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                locRenderer.setScale(1.0);
                return;
            }
            var scaleX = locContentSize.width / textureSize.width;
            var scaleY = locContentSize.height / textureSize.height;
            locRenderer.setScaleX(scaleX);
            locRenderer.setScaleY(scaleY);
        }
        locRenderer.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
    },
    getDescription: function () {
        return "CheckBox";
    },
    _createCloneInstance: function () {
        return new ccui.CheckBox();
    },
    _copySpecialProperties: function (uiCheckBox) {
        if (uiCheckBox instanceof ccui.CheckBox) {
            this.loadTextureBackGround(uiCheckBox._backGroundFileName, uiCheckBox._backGroundTexType);
            this.loadTextureBackGroundSelected(uiCheckBox._backGroundSelectedFileName, uiCheckBox._backGroundSelectedTexType);
            this.loadTextureFrontCross(uiCheckBox._frontCrossFileName, uiCheckBox._frontCrossTexType);
            this.loadTextureBackGroundDisabled(uiCheckBox._backGroundDisabledFileName, uiCheckBox._backGroundDisabledTexType);
            this.loadTextureFrontCrossDisabled(uiCheckBox._frontCrossDisabledFileName, uiCheckBox._frontCrossDisabledTexType);
            this.setSelected(uiCheckBox._isSelected);
            this._checkBoxEventListener = uiCheckBox._checkBoxEventListener;
            this._checkBoxEventSelector = uiCheckBox._checkBoxEventSelector;
            this._ccEventCallback = uiCheckBox._ccEventCallback;
            this._zoomScale = uiCheckBox._zoomScale;
            this._backgroundTextureScaleX = uiCheckBox._backgroundTextureScaleX;
            this._backgroundTextureScaleY = uiCheckBox._backgroundTextureScaleY;
        }
    },
    _adaptRenderers: function(){
        if (this._backGroundBoxRendererAdaptDirty){
            this._backGroundTextureScaleChangedWithSize();
            this._backGroundBoxRendererAdaptDirty = false;
        }
        if (this._backGroundSelectedBoxRendererAdaptDirty) {
            this._backGroundSelectedTextureScaleChangedWithSize();
            this._backGroundSelectedBoxRendererAdaptDirty = false;
        }
        if (this._frontCrossRendererAdaptDirty){
            this._frontCrossTextureScaleChangedWithSize();
            this._frontCrossRendererAdaptDirty = false;
        }
        if (this._backGroundBoxDisabledRendererAdaptDirty) {
            this._backGroundDisabledTextureScaleChangedWithSize();
            this._backGroundBoxDisabledRendererAdaptDirty = false;
        }
        if (this._frontCrossDisabledRendererAdaptDirty) {
            this._frontCrossDisabledTextureScaleChangedWithSize();
            this._frontCrossDisabledRendererAdaptDirty = false;
        }
    }
});
var _p = ccui.CheckBox.prototype;
_p.selected;
cc.defineGetterSetter(_p, "selected", _p.isSelected, _p.setSelected);
_p = null;
ccui.CheckBox.create = function (backGround, backGroundSeleted, cross, backGroundDisabled, frontCrossDisabled, texType) {
    return new ccui.CheckBox(backGround, backGroundSeleted,cross,backGroundDisabled,frontCrossDisabled,texType);
};
ccui.CheckBox.EVENT_SELECTED = 0;
ccui.CheckBox.EVENT_UNSELECTED = 1;
ccui.CheckBox.BOX_RENDERER_ZORDER = -1;
ccui.CheckBox.BOX_SELECTED_RENDERER_ZORDER = -1;
ccui.CheckBox.BOX_DISABLED_RENDERER_ZORDER = -1;
ccui.CheckBox.FRONT_CROSS_RENDERER_ZORDER = -1;
ccui.CheckBox.FRONT_CROSS_DISABLED_RENDERER_ZORDER = -1;
ccui.ImageView = ccui.Widget.extend({
    _scale9Enabled: false,
    _prevIgnoreSize: true,
    _capInsets: null,
    _imageRenderer: null,
    _textureFile: "",
    _imageTexType: ccui.Widget.LOCAL_TEXTURE,
    _imageTextureSize: null,
    _className:"ImageView",
    _imageRendererAdaptDirty: true,
    ctor: function (imageFileName, texType) {
        this._capInsets = cc.rect(0,0,0,0);
        this._imageTextureSize = cc.size(this._capInsets.width, this._capInsets.height);
        ccui.Widget.prototype.ctor.call(this);
        texType = texType === undefined ? 0 : texType;
        if(imageFileName) {
            this.loadTexture(imageFileName, texType);
        }
        else {
            this._imageTexType = ccui.Widget.LOCAL_TEXTURE;
        }
    },
    _initRenderer: function () {
        this._imageRenderer = new cc.Sprite();
        this.addProtectedChild(this._imageRenderer, ccui.ImageView.RENDERER_ZORDER, -1);
    },
    loadTexture: function (fileName, texType) {
        if (!fileName) {
            return;
        }
        var self = this;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._textureFile = fileName;
        this._imageTexType = texType;
        var imageRenderer = self._imageRenderer;
        if(!imageRenderer._textureLoaded){
            imageRenderer.addEventListener("load", function(){
                self.loadTexture(self._textureFile, self._imageTexType);
            });
        }
        switch (self._imageTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                if(self._scale9Enabled){
                    imageRenderer.initWithFile(fileName);
                    imageRenderer.setCapInsets(self._capInsets);
                }else{
                    imageRenderer.initWithFile(fileName);
                }
                break;
            case ccui.Widget.PLIST_TEXTURE:
                if(self._scale9Enabled){
                    imageRenderer.initWithSpriteFrameName(fileName);
                    imageRenderer.setCapInsets(self._capInsets);
                }else{
                    imageRenderer.initWithSpriteFrameName(fileName);
                }
                break;
            default:
                break;
        }
        self._imageTextureSize = imageRenderer.getContentSize();
        this._updateChildrenDisplayedRGBA();
        self._updateContentSizeWithTextureSize(self._imageTextureSize);
        self._imageRendererAdaptDirty = true;
        self._findLayout();
    },
    setTextureRect: function (rect) {
        if (!this._scale9Enabled)
            this._imageRenderer.setTextureRect(rect);
    },
    setScale9Enabled: function (able) {
        if (this._scale9Enabled === able)
            return;
        this._scale9Enabled = able;
        this.removeProtectedChild(this._imageRenderer);
        this._imageRenderer = null;
        if (this._scale9Enabled) {
            this._imageRenderer = new ccui.Scale9Sprite();
        } else {
            this._imageRenderer = new cc.Sprite();
        }
        this.loadTexture(this._textureFile, this._imageTexType);
        this.addProtectedChild(this._imageRenderer, ccui.ImageView.RENDERER_ZORDER, -1);
        if (this._scale9Enabled) {
            var ignoreBefore = this._ignoreSize;
            this.ignoreContentAdaptWithSize(false);
            this._prevIgnoreSize = ignoreBefore;
        } else
            this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
        this.setCapInsets(this._capInsets);
        this._imageRendererAdaptDirty = true;
    },
    isScale9Enabled:function(){
        return this._scale9Enabled;
    },
    ignoreContentAdaptWithSize: function (ignore) {
        if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
            ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
            this._prevIgnoreSize = ignore;
        }
    },
    setCapInsets: function (capInsets) {
        if(!capInsets)
            return;
        var locInsets = this._capInsets;
        locInsets.x = capInsets.x;
        locInsets.y = capInsets.y;
        locInsets.width = capInsets.width;
        locInsets.height = capInsets.height;
        if (!this._scale9Enabled)
            return;
        this._imageRenderer.setCapInsets(capInsets);
    },
    getCapInsets:function(){
        return cc.rect(this._capInsets);
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._imageRendererAdaptDirty = true;
    },
    _adaptRenderers: function(){
        if (this._imageRendererAdaptDirty){
            this._imageTextureScaleChangedWithSize();
            this._imageRendererAdaptDirty = false;
        }
    },
    getVirtualRendererSize: function(){
        return cc.size(this._imageTextureSize);
    },
    getVirtualRenderer: function () {
        return this._imageRenderer;
    },
    _imageTextureScaleChangedWithSize: function () {
        if (this._ignoreSize) {
            if (!this._scale9Enabled)
                this._imageRenderer.setScale(1.0);
        } else {
            if (this._scale9Enabled){
                this._imageRenderer.setPreferredSize(this._contentSize);
                this._imageRenderer.setScale(1);
            } else {
                var textureSize = this._imageTextureSize;
                if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                    this._imageRenderer.setScale(1.0);
                    return;
                }
                this._imageRenderer.setScaleX(this._contentSize.width / textureSize.width);
                this._imageRenderer.setScaleY(this._contentSize.height / textureSize.height);
            }
        }
        this._imageRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
    },
    getDescription: function () {
        return "ImageView";
    },
    _createCloneInstance:function(){
        return new ccui.ImageView();
    },
    _copySpecialProperties: function (imageView) {
        if(imageView instanceof ccui.ImageView){
            this._prevIgnoreSize = imageView._prevIgnoreSize;
            this.setScale9Enabled(imageView._scale9Enabled);
            this.loadTexture(imageView._textureFile, imageView._imageTexType);
            this.setCapInsets(imageView._capInsets);
        }
    },
    setContentSize: function(contentSize, height){
        if(height != null)
            contentSize = cc.size(contentSize, height);
        ccui.Widget.prototype.setContentSize.call(this, contentSize);
        if(!this._scale9Enabled){
            var iContentSize = this._imageRenderer.getContentSize();
            this._imageRenderer.setScaleX(contentSize.width / iContentSize.width);
            this._imageRenderer.setScaleY(contentSize.height / iContentSize.height);
        }else{
            this._imageRenderer.setContentSize(contentSize);
        }
    }
});
ccui.ImageView.create = function (imageFileName, texType) {
    return new ccui.ImageView(imageFileName, texType);
};
ccui.ImageView.RENDERER_ZORDER = -1;
ccui.LoadingBar = ccui.Widget.extend({
    _direction: null,
    _percent: 100,
    _totalLength: 0,
    _barRenderer: null,
    _renderBarTexType: ccui.Widget.LOCAL_TEXTURE,
    _barRendererTextureSize: null,
    _scale9Enabled: false,
    _prevIgnoreSize: true,
    _capInsets: null,
    _textureFile: "",
    _isTextureLoaded: false,
    _className: "LoadingBar",
    _barRendererAdaptDirty: true,
    ctor: function (textureName, percentage) {
        this._direction = ccui.LoadingBar.TYPE_LEFT;
        this._barRendererTextureSize = cc.size(0, 0);
        this._capInsets = cc.rect(0, 0, 0, 0);
        ccui.Widget.prototype.ctor.call(this);
        if(textureName !== undefined)
            this.loadTexture(textureName);
        if(percentage !== undefined)
            this.setPercent(percentage);
    },
    _initRenderer: function () {
        this._barRenderer = new cc.Sprite();
        this.addProtectedChild(this._barRenderer, ccui.LoadingBar.RENDERER_ZORDER, -1);
        this._barRenderer.setAnchorPoint(0.0, 0.5);
    },
    setDirection: function (dir) {
        if (this._direction === dir)
            return;
        this._direction = dir;
        switch (this._direction) {
            case ccui.LoadingBar.TYPE_LEFT:
                this._barRenderer.setAnchorPoint(0, 0.5);
                this._barRenderer.setPosition(0, this._contentSize.height*0.5);
                if (!this._scale9Enabled)
                    this._barRenderer.setFlippedX(false);
                break;
            case ccui.LoadingBar.TYPE_RIGHT:
                this._barRenderer.setAnchorPoint(1, 0.5);
                this._barRenderer.setPosition(this._totalLength,this._contentSize.height*0.5);
                if (!this._scale9Enabled)
                    this._barRenderer.setFlippedX(true);
                break;
        }
    },
    getDirection: function () {
        return this._direction;
    },
    loadTexture: function (texture, texType) {
        if (!texture)
            return;
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._renderBarTexType = texType;
        this._textureFile = texture;
        var barRenderer = this._barRenderer;
        var self = this;
        if(!barRenderer._textureLoaded){
            barRenderer.addEventListener("load", function(){
                self.loadTexture(self._textureFile, self._renderBarTexType);
                self._setPercent(self._percent);
            });
        }
        switch (this._renderBarTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                barRenderer.initWithFile(texture);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                barRenderer.initWithSpriteFrameName(texture);
                break;
            default:
                break;
        }
        var bz = barRenderer.getContentSize();
        this._barRendererTextureSize.width = bz.width;
        this._barRendererTextureSize.height = bz.height;
        switch (this._direction) {
            case ccui.LoadingBar.TYPE_LEFT:
                barRenderer.setAnchorPoint(0,0.5);
                if (!this._scale9Enabled)
                    barRenderer.setFlippedX(false);
                break;
            case ccui.LoadingBar.TYPE_RIGHT:
                barRenderer.setAnchorPoint(1,0.5);
                if (!this._scale9Enabled)
                    barRenderer.setFlippedX(true);
                break;
        }
        if (this._scale9Enabled)
            barRenderer.setCapInsets(this._capInsets);
        this._updateChildrenDisplayedRGBA();
        this._barRendererScaleChangedWithSize();
        this._updateContentSizeWithTextureSize(this._barRendererTextureSize);
        this._barRendererAdaptDirty = true;
        this._findLayout();
    },
    setScale9Enabled: function (enabled) {
        if (this._scale9Enabled === enabled)
            return;
        this._scale9Enabled = enabled;
        this.removeProtectedChild(this._barRenderer);
        this._barRenderer = this._scale9Enabled ? new ccui.Scale9Sprite() : new cc.Sprite();
        this.loadTexture(this._textureFile, this._renderBarTexType);
        this.addProtectedChild(this._barRenderer, ccui.LoadingBar.RENDERER_ZORDER, -1);
        if (this._scale9Enabled) {
            var ignoreBefore = this._ignoreSize;
            this.ignoreContentAdaptWithSize(false);
            this._prevIgnoreSize = ignoreBefore;
        } else
            this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
        this.setCapInsets(this._capInsets);
        this.setPercent(this._percent);
        this._barRendererAdaptDirty = true;
    },
    isScale9Enabled: function () {
        return this._scale9Enabled;
    },
    setCapInsets: function (capInsets) {
        if(!capInsets)
            return;
        var locInsets = this._capInsets;
        locInsets.x = capInsets.x;
        locInsets.y = capInsets.y;
        locInsets.width = capInsets.width;
        locInsets.height = capInsets.height;
        if (this._scale9Enabled)
            this._barRenderer.setCapInsets(capInsets);
    },
    getCapInsets: function () {
        return cc.rect(this._capInsets);
    },
    setPercent: function (percent) {
        if(percent > 100)
            percent = 100;
        if(percent < 0)
            percent = 0;
        if (percent === this._percent)
            return;
        this._percent = percent;
        this._setPercent(percent);
    },
    _setPercent: function(){
        var res, rect, spriteRenderer, spriteTextureRect;
        if (this._totalLength <= 0)
            return;
        res = this._percent / 100.0;
        if (this._scale9Enabled)
            this._setScale9Scale();
        else {
            spriteRenderer = this._barRenderer;
            spriteTextureRect = this._barRendererTextureSize;
            rect = spriteRenderer.getTextureRect();
            rect.width = spriteTextureRect.width * res;
            spriteRenderer.setTextureRect(
                cc.rect(
                    rect.x,
                    rect.y,
                    spriteTextureRect.width * res,
                    spriteTextureRect.height
                ),
                spriteRenderer._rectRotated
            );
        }
    },
    setContentSize: function(contentSize, height){
        ccui.Widget.prototype.setContentSize.call(this, contentSize, height);
        this._totalLength = (height === undefined) ? contentSize.width : contentSize;
    },
    getPercent: function () {
        return this._percent;
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._barRendererAdaptDirty = true;
    },
    _adaptRenderers: function(){
        if (this._barRendererAdaptDirty){
            this._barRendererScaleChangedWithSize();
            this._barRendererAdaptDirty = false;
        }
    },
    ignoreContentAdaptWithSize: function (ignore) {
        if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
            ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
            this._prevIgnoreSize = ignore;
        }
    },
    getVirtualRendererSize:function(){
        return cc.size(this._barRendererTextureSize);
    },
    getVirtualRenderer: function () {
        return this._barRenderer;
    },
    _barRendererScaleChangedWithSize: function () {
        var locBarRender = this._barRenderer, locContentSize = this._contentSize;
        if(this._unifySize){
            this._totalLength = this._contentSize.width;
            this.setPercent(this._percent);
        }else if (this._ignoreSize) {
            if (!this._scale9Enabled) {
                this._totalLength = this._barRendererTextureSize.width;
                locBarRender.setScale(1.0);
            }
        } else {
            this._totalLength = locContentSize.width;
            if (this._scale9Enabled){
                this._setScale9Scale();
                locBarRender.setScale(1.0);
            } else {
                var textureSize = this._barRendererTextureSize;
                if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                    locBarRender.setScale(1.0);
                    return;
                }
                var scaleX = locContentSize.width / textureSize.width;
                var scaleY = locContentSize.height / textureSize.height;
                locBarRender.setScaleX(scaleX);
                locBarRender.setScaleY(scaleY);
            }
        }
        switch (this._direction) {
            case ccui.LoadingBar.TYPE_LEFT:
                locBarRender.setPosition(0, locContentSize.height * 0.5);
                break;
            case ccui.LoadingBar.TYPE_RIGHT:
                locBarRender.setPosition(this._totalLength, locContentSize.height * 0.5);
                break;
            default:
                break;
        }
    },
    _setScale9Scale: function () {
        var width = (this._percent) / 100 * this._totalLength;
        this._barRenderer.setPreferredSize(cc.size(width, this._contentSize.height));
    },
    getDescription: function () {
        return "LoadingBar";
    },
    _createCloneInstance: function () {
        return new ccui.LoadingBar();
    },
    _copySpecialProperties: function (loadingBar) {
        if(loadingBar instanceof ccui.LoadingBar){
            this._prevIgnoreSize = loadingBar._prevIgnoreSize;
            this.setScale9Enabled(loadingBar._scale9Enabled);
            this.loadTexture(loadingBar._textureFile, loadingBar._renderBarTexType);
            this.setCapInsets(loadingBar._capInsets);
            this.setPercent(loadingBar._percent);
            this.setDirection(loadingBar._direction);
        }
    }
});
var _p = ccui.LoadingBar.prototype;
_p.direction;
cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
_p.percent;
cc.defineGetterSetter(_p, "percent", _p.getPercent, _p.setPercent);
_p = null;
ccui.LoadingBar.create = function (textureName, percentage) {
    return new ccui.LoadingBar(textureName, percentage);
};
ccui.LoadingBar.TYPE_LEFT = 0;
ccui.LoadingBar.TYPE_RIGHT = 1;
ccui.LoadingBar.RENDERER_ZORDER = -1;
ccui.Slider = ccui.Widget.extend({
    _barRenderer: null,
    _progressBarRenderer: null,
    _barTextureSize: null,
    _progressBarTextureSize: null,
    _slidBallNormalRenderer: null,
    _slidBallPressedRenderer: null,
    _slidBallDisabledRenderer: null,
    _slidBallRenderer: null,
    _barLength: 0,
    _percent: 0,
    _scale9Enabled: false,
    _prevIgnoreSize: true,
    _textureFile: "",
    _progressBarTextureFile: "",
    _slidBallNormalTextureFile: "",
    _slidBallPressedTextureFile: "",
    _slidBallDisabledTextureFile: "",
    _capInsetsBarRenderer: null,
    _capInsetsProgressBarRenderer: null,
    _sliderEventListener: null,
    _sliderEventSelector: null,
    _barTexType: ccui.Widget.LOCAL_TEXTURE,
    _progressBarTexType: ccui.Widget.LOCAL_TEXTURE,
    _ballNTexType: ccui.Widget.LOCAL_TEXTURE,
    _ballPTexType: ccui.Widget.LOCAL_TEXTURE,
    _ballDTexType: ccui.Widget.LOCAL_TEXTURE,
    _isTextureLoaded: false,
    _className: "Slider",
    _barRendererAdaptDirty: true,
    _progressBarRendererDirty: true,
    _unifySize: false,
    _zoomScale: 0.1,
    _sliderBallNormalTextureScaleX: 1,
    _sliderBallNormalTextureScaleY: 1,
    ctor: function (barTextureName, normalBallTextureName, resType) {
        this._barTextureSize = cc.size(0,0);
        this._progressBarTextureSize = cc.size(0, 0);
        this._capInsetsBarRenderer = cc.rect(0, 0, 0, 0);
        this._capInsetsProgressBarRenderer = cc.rect(0, 0, 0, 0);
        ccui.Widget.prototype.ctor.call(this);
        resType = resType || 0;
        this.setTouchEnabled(true);
        if (barTextureName) {
            this.loadBarTexture(barTextureName, resType);
        }
        if (normalBallTextureName) {
            this.loadSlidBallTextures(normalBallTextureName, resType);
        }
    },
    _initRenderer: function () {
        this._barRenderer = new cc.Sprite();
        this._progressBarRenderer = new cc.Sprite();
        this._progressBarRenderer.setAnchorPoint(0.0, 0.5);
        this.addProtectedChild(this._barRenderer, ccui.Slider.BASEBAR_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._progressBarRenderer, ccui.Slider.PROGRESSBAR_RENDERER_ZORDER, -1);
        this._slidBallNormalRenderer = new cc.Sprite();
        this._slidBallPressedRenderer = new cc.Sprite();
        this._slidBallPressedRenderer.setVisible(false);
        this._slidBallDisabledRenderer = new cc.Sprite();
        this._slidBallDisabledRenderer.setVisible(false);
        this._slidBallRenderer = new cc.Node();
        this._slidBallRenderer.addChild(this._slidBallNormalRenderer);
        this._slidBallRenderer.addChild(this._slidBallPressedRenderer);
        this._slidBallRenderer.addChild(this._slidBallDisabledRenderer);
        this._slidBallRenderer.setCascadeColorEnabled(true);
        this._slidBallRenderer.setCascadeOpacityEnabled(true);
        this.addProtectedChild(this._slidBallRenderer, ccui.Slider.BALL_RENDERER_ZORDER, -1);
    },
    loadBarTexture: function (fileName, texType) {
        if (!fileName) {
            return;
        }
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._textureFile = fileName;
        this._barTexType = texType;
        var barRenderer = this._barRenderer;
        var self = this;
        if(!barRenderer._textureLoaded){
            barRenderer.addEventListener("load", function(){
                self.loadBarTexture(self._textureFile, self._barTexType);
            });
        }
        switch (this._barTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                barRenderer.initWithFile(fileName);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                barRenderer.initWithSpriteFrameName(fileName);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._barRendererAdaptDirty = true;
        this._progressBarRendererDirty = true;
        this._updateContentSizeWithTextureSize(this._barRenderer.getContentSize());
        this._findLayout();
        this._barTextureSize = this._barRenderer.getContentSize();
    },
    loadProgressBarTexture: function (fileName, texType) {
        if (!fileName) {
            return;
        }
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._progressBarTextureFile = fileName;
        this._progressBarTexType = texType;
        var progressBarRenderer = this._progressBarRenderer;
        var self = this;
        if(!progressBarRenderer._textureLoaded){
            progressBarRenderer.addEventListener("load", function(){
                self.loadProgressBarTexture(self._progressBarTextureFile, self._progressBarTexType);
            });
        }
        switch (this._progressBarTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                progressBarRenderer.initWithFile(fileName);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                progressBarRenderer.initWithSpriteFrameName(fileName);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._progressBarRenderer.setAnchorPoint(cc.p(0, 0.5));
        var tz = this._progressBarRenderer.getContentSize();
        this._progressBarTextureSize = {width: tz.width, height: tz.height};
        this._progressBarRendererDirty = true;
        this._findLayout();
    },
    setScale9Enabled: function (able) {
        if (this._scale9Enabled === able)
            return;
        this._scale9Enabled = able;
        this.removeProtectedChild(this._barRenderer, true);
        this.removeProtectedChild(this._progressBarRenderer, true);
        this._barRenderer = null;
        this._progressBarRenderer = null;
        if (this._scale9Enabled) {
            this._barRenderer = new ccui.Scale9Sprite();
            this._progressBarRenderer = new ccui.Scale9Sprite();
        } else {
            this._barRenderer = new cc.Sprite();
            this._progressBarRenderer = new cc.Sprite();
        }
        this.loadBarTexture(this._textureFile, this._barTexType);
        this.loadProgressBarTexture(this._progressBarTextureFile, this._progressBarTexType);
        this.addProtectedChild(this._barRenderer, ccui.Slider.BASEBAR_RENDERER_ZORDER, -1);
        this.addProtectedChild(this._progressBarRenderer, ccui.Slider.PROGRESSBAR_RENDERER_ZORDER, -1);
        if (this._scale9Enabled) {
            var ignoreBefore = this._ignoreSize;
            this.ignoreContentAdaptWithSize(false);
            this._prevIgnoreSize = ignoreBefore;
        } else {
            this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
        }
        this.setCapInsetsBarRenderer(this._capInsetsBarRenderer);
        this.setCapInsetProgressBarRenderer(this._capInsetsProgressBarRenderer);
        this._barRendererAdaptDirty = true;
        this._progressBarRendererDirty = true;
    },
    isScale9Enabled: function () {
        return this._scale9Enabled;
    },
    ignoreContentAdaptWithSize: function (ignore) {
        if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
            ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
            this._prevIgnoreSize = ignore;
        }
    },
    setCapInsets: function (capInsets) {
        this.setCapInsetsBarRenderer(capInsets);
        this.setCapInsetProgressBarRenderer(capInsets);
    },
    setCapInsetsBarRenderer: function (capInsets) {
        if(!capInsets)
            return;
        var locInsets = this._capInsetsBarRenderer;
        locInsets.x = capInsets.x;
        locInsets.y = capInsets.y;
        locInsets.width = capInsets.width;
        locInsets.height = capInsets.height;
        if (!this._scale9Enabled)
            return;
        this._barRenderer.setCapInsets(capInsets);
    },
    getCapInsetsBarRenderer: function () {
        return cc.rect(this._capInsetsBarRenderer);
    },
    setCapInsetProgressBarRenderer: function (capInsets) {
        if(!capInsets)
            return;
        var locInsets = this._capInsetsProgressBarRenderer;
        locInsets.x = capInsets.x;
        locInsets.y = capInsets.y;
        locInsets.width = capInsets.width;
        locInsets.height = capInsets.height;
        if (!this._scale9Enabled)
            return;
        this._progressBarRenderer.setCapInsets(capInsets);
    },
    getCapInsetsProgressBarRenderer: function () {
        return cc.rect(this._capInsetsProgressBarRenderer);
    },
    loadSlidBallTextures: function (normal, pressed, disabled, texType) {
        this.loadSlidBallTextureNormal(normal, texType);
        this.loadSlidBallTexturePressed(pressed, texType);
        this.loadSlidBallTextureDisabled(disabled, texType);
    },
    loadSlidBallTextureNormal: function (normal, texType) {
        if (!normal) {
            return;
        }
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._slidBallNormalTextureFile = normal;
        this._ballNTexType = texType;
        var self = this;
        if(!this._slidBallNormalRenderer._textureLoaded){
            this._slidBallNormalRenderer.addEventListener("load", function(){
                self.loadSlidBallTextureNormal(self._slidBallNormalTextureFile, self._ballNTexType);
            });
        }
        switch (this._ballNTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                this._slidBallNormalRenderer.initWithFile(normal);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                this._slidBallNormalRenderer.initWithSpriteFrameName(normal);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._findLayout();
    },
    loadSlidBallTexturePressed: function (pressed, texType) {
        if (!pressed) {
            return;
        }
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._slidBallPressedTextureFile = pressed;
        this._ballPTexType = texType;
        var self = this;
        if(!this._slidBallPressedRenderer._textureLoaded){
            this._slidBallPressedRenderer.addEventListener("load", function(){
                self.loadSlidBallTexturePressed(self._slidBallPressedTextureFile, self._ballPTexType);
            });
        }
        switch (this._ballPTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                this._slidBallPressedRenderer.initWithFile(pressed);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                this._slidBallPressedRenderer.initWithSpriteFrameName(pressed);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._findLayout();
    },
    loadSlidBallTextureDisabled: function (disabled, texType) {
        if (!disabled) {
            return;
        }
        texType = texType || ccui.Widget.LOCAL_TEXTURE;
        this._slidBallDisabledTextureFile = disabled;
        this._ballDTexType = texType;
        var self = this;
        if(!this._slidBallDisabledRenderer._textureLoaded){
            this._slidBallDisabledRenderer.addEventListener("load", function(){
                self.loadSlidBallTextureDisabled(self._slidBallDisabledTextureFile, self._ballDTexType);
            });
        }
        switch (this._ballDTexType) {
            case ccui.Widget.LOCAL_TEXTURE:
                this._slidBallDisabledRenderer.initWithFile(disabled);
                break;
            case ccui.Widget.PLIST_TEXTURE:
                this._slidBallDisabledRenderer.initWithSpriteFrameName(disabled);
                break;
            default:
                break;
        }
        this._updateChildrenDisplayedRGBA();
        this._findLayout();
    },
    setPercent: function (percent) {
        if (percent > 100)
            percent = 100;
        if (percent < 0)
            percent = 0;
        this._percent = percent;
        var res = percent / 100.0;
        var dis = this._barLength * res;
        this._slidBallRenderer.setPosition(dis, this._contentSize.height / 2);
        if (this._scale9Enabled)
            this._progressBarRenderer.setPreferredSize(cc.size(dis, this._contentSize.height));
        else {
            var spriteRenderer = this._progressBarRenderer;
            var rect = spriteRenderer.getTextureRect();
            spriteRenderer.setTextureRect(
                cc.rect(rect.x, rect.y, dis / spriteRenderer._scaleX, rect.height),
                spriteRenderer.isTextureRectRotated()
            );
        }
    },
    hitTest: function(pt){
        var nsp = this._slidBallNormalRenderer.convertToNodeSpace(pt);
        var ballSize = this._slidBallNormalRenderer.getContentSize();
        var ballRect = cc.rect(0,0, ballSize.width, ballSize.height);
        return (nsp.x >= ballRect.x &&
            nsp.x <= (ballRect.x + ballRect.width) &&
            nsp.y >= ballRect.y &&
            nsp.y <= (ballRect.y +ballRect.height));
    },
    onTouchBegan: function (touch, event) {
        var pass = ccui.Widget.prototype.onTouchBegan.call(this, touch, event);
        if (this._hit) {
            var nsp = this.convertToNodeSpace(this._touchBeganPosition);
            this.setPercent(this._getPercentWithBallPos(nsp.x));
            this._percentChangedEvent();
        }
        return pass;
    },
    onTouchMoved: function (touch, event) {
        var touchPoint = touch.getLocation();
        var nsp = this.convertToNodeSpace(touchPoint);
        this.setPercent(this._getPercentWithBallPos(nsp.x));
        this._percentChangedEvent();
    },
    onTouchEnded: function (touch, event) {
        ccui.Widget.prototype.onTouchEnded.call(this, touch, event);
    },
    onTouchCancelled: function (touch, event) {
        ccui.Widget.prototype.onTouchCancelled.call(this, touch, event);
    },
    _getPercentWithBallPos: function (px) {
        return ((px/this._barLength)*100);
    },
    addEventListenerSlider: function (selector, target) {
        this.addEventListener(selector, target);
    },
    addEventListener: function(selector, target){
        this._sliderEventSelector = selector;
        this._sliderEventListener = target;
    },
    _percentChangedEvent: function () {
        if(this._sliderEventSelector){
            if (this._sliderEventListener)
                this._sliderEventSelector.call(this._sliderEventListener, this, ccui.Slider.EVENT_PERCENT_CHANGED);
            else
                this._sliderEventSelector(this, ccui.Slider.EVENT_PERCENT_CHANGED);
        }
        if (this._ccEventCallback)
            this._ccEventCallback(this, ccui.Slider.EVENT_PERCENT_CHANGED);
    },
    getPercent: function () {
        return this._percent;
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._barRendererAdaptDirty = true;
        this._progressBarRendererDirty = true;
    },
    _adaptRenderers: function(){
        if (this._barRendererAdaptDirty)
        {
            this._barRendererScaleChangedWithSize();
            this._barRendererAdaptDirty = false;
        }
        if (this._progressBarRendererDirty)
        {
            this._progressBarRendererScaleChangedWithSize();
            this._progressBarRendererDirty = false;
        }
    },
    getVirtualRendererSize: function(){
        return this._barRenderer.getContentSize();
    },
    getVirtualRenderer: function () {
        return this._barRenderer;
    },
    _barRendererScaleChangedWithSize: function () {
        if (this._unifySize){
            this._barLength = this._contentSize.width;
            this._barRenderer.setPreferredSize(this._contentSize);
        }else if(this._ignoreSize) {
            this._barRenderer.setScale(1.0);
            this._barLength = this._contentSize.width;
        }else {
            this._barLength = this._contentSize.width;
            if (this._scale9Enabled) {
                this._barRenderer.setPreferredSize(this._contentSize);
                this._barRenderer.setScale(1.0);
            } else {
                var btextureSize = this._barTextureSize;
                if (btextureSize.width <= 0.0 || btextureSize.height <= 0.0) {
                    this._barRenderer.setScale(1.0);
                }else{
                    var bscaleX = this._contentSize.width / btextureSize.width;
                    var bscaleY = this._contentSize.height / btextureSize.height;
                    this._barRenderer.setScaleX(bscaleX);
                    this._barRenderer.setScaleY(bscaleY);
                }
            }
        }
        this._barRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
        this.setPercent(this._percent);
    },
    _progressBarRendererScaleChangedWithSize: function () {
        if(this._unifySize){
            this._progressBarRenderer.setPreferredSize(this._contentSize);
        }else if(this._ignoreSize) {
            if (!this._scale9Enabled) {
                var ptextureSize = this._progressBarTextureSize;
                var pscaleX = this._contentSize.width / ptextureSize.width;
                var pscaleY = this._contentSize.height / ptextureSize.height;
                this._progressBarRenderer.setScaleX(pscaleX);
                this._progressBarRenderer.setScaleY(pscaleY);
            }
        }
        else {
            if (this._scale9Enabled) {
                this._progressBarRenderer.setPreferredSize(this._contentSize);
                this._progressBarRenderer.setScale(1);
            }
            else {
                var ptextureSize = this._progressBarTextureSize;
                if (ptextureSize.width <= 0.0 || ptextureSize.height <= 0.0) {
                    this._progressBarRenderer.setScale(1.0);
                    return;
                }
                var pscaleX = this._contentSize.width / ptextureSize.width;
                var pscaleY = this._contentSize.height / ptextureSize.height;
                this._progressBarRenderer.setScaleX(pscaleX);
                this._progressBarRenderer.setScaleY(pscaleY);
            }
        }
        this._progressBarRenderer.setPosition(0.0, this._contentSize.height / 2.0);
        this.setPercent(this._percent);
    },
    _onPressStateChangedToNormal: function () {
        this._slidBallNormalRenderer.setVisible(true);
        this._slidBallPressedRenderer.setVisible(false);
        this._slidBallDisabledRenderer.setVisible(false);
        this._slidBallNormalRenderer.setScale(this._sliderBallNormalTextureScaleX, this._sliderBallNormalTextureScaleY);
    },
    _onPressStateChangedToPressed: function () {
        if (!this._slidBallPressedTextureFile){
            this._slidBallNormalRenderer.setScale(this._sliderBallNormalTextureScaleX + this._zoomScale, this._sliderBallNormalTextureScaleY + this._zoomScale);
        }else{
            this._slidBallNormalRenderer.setVisible(false);
            this._slidBallPressedRenderer.setVisible(true);
            this._slidBallDisabledRenderer.setVisible(false);
        }
    },
    _onPressStateChangedToDisabled: function () {
        if (this._slidBallDisabledTextureFile){
            this._slidBallNormalRenderer.setVisible(false);
            this._slidBallDisabledRenderer.setVisible(true);
        }
        this._slidBallNormalRenderer.setScale(this._sliderBallNormalTextureScaleX, this._sliderBallNormalTextureScaleY);
        this._slidBallPressedRenderer.setVisible(false);
    },
    setZoomScale: function(scale){
        this._zoomScale = scale;
    },
    getZoomScale: function(){
        return this._zoomScale;
    },
    getDescription: function () {
        return "Slider";
    },
    _createCloneInstance: function () {
        return new ccui.Slider();
    },
    _copySpecialProperties: function (slider) {
        this._prevIgnoreSize = slider._prevIgnoreSize;
        this.setScale9Enabled(slider._scale9Enabled);
        this.loadBarTexture(slider._textureFile, slider._barTexType);
        this.loadProgressBarTexture(slider._progressBarTextureFile, slider._progressBarTexType);
        this.loadSlidBallTextureNormal(slider._slidBallNormalTextureFile, slider._ballNTexType);
        this.loadSlidBallTexturePressed(slider._slidBallPressedTextureFile, slider._ballPTexType);
        this.loadSlidBallTextureDisabled(slider._slidBallDisabledTextureFile, slider._ballDTexType);
        this.setPercent(slider.getPercent());
        this._sliderEventListener = slider._sliderEventListener;
        this._sliderEventSelector = slider._sliderEventSelector;
        this._zoomScale = slider._zoomScale;
        this._ccEventCallback = slider._ccEventCallback;
    }
});
var _p = ccui.Slider.prototype;
_p.percent;
cc.defineGetterSetter(_p, "percent", _p.getPercent, _p.setPercent);
_p = null;
ccui.Slider.create = function (barTextureName, normalBallTextureName, resType) {
    return new ccui.Slider(barTextureName, normalBallTextureName, resType);
};
ccui.Slider.EVENT_PERCENT_CHANGED = 0;
ccui.Slider.BASEBAR_RENDERER_ZORDER = -3;
ccui.Slider.PROGRESSBAR_RENDERER_ZORDER = -2;
ccui.Slider.BALL_RENDERER_ZORDER = -1;
ccui.Text = ccui.Widget.extend({
    _touchScaleChangeEnabled: false,
    _normalScaleValueX: 1,
    _normalScaleValueY: 1,
    _fontName: "Arial",
    _fontSize: 16,
    _onSelectedScaleOffset:0.5,
    _labelRenderer: null,
    _textAreaSize: null,
    _textVerticalAlignment: 0,
    _textHorizontalAlignment: 0,
    _className: "Text",
    _type: null,
    _labelRendererAdaptDirty: true,
    ctor: function (textContent, fontName, fontSize) {
        this._type = ccui.Text.Type.SYSTEM;
        this._textAreaSize = cc.size(0, 0);
        ccui.Widget.prototype.ctor.call(this);
        if (fontSize !== undefined) {
            this.setFontName(fontName);
            this.setFontSize(fontSize);
            this.setString(textContent);
        } else {
            this.setFontName(this._fontName);
        }
    },
    _initRenderer: function () {
        this._labelRenderer = new cc.LabelTTF();
        this.addProtectedChild(this._labelRenderer, ccui.Text.RENDERER_ZORDER, -1);
    },
    setText: function (text) {
        cc.log("Please use the setString");
        this.setString(text);
    },
    setString: function (text) {
        if(text === this._labelRenderer.getString())
            return;
        this._labelRenderer.setString(text);
        this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
        this._labelRendererAdaptDirty = true;
    },
    getStringValue: function () {
        cc.log("Please use the getString");
        return this._labelRenderer.getString();
    },
    getString: function () {
        return this._labelRenderer.getString();
    },
    getStringLength: function () {
        return this._labelRenderer.getStringLength();
    },
    setFontSize: function (size) {
        this._labelRenderer.setFontSize(size);
        this._fontSize = size;
        this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
        this._labelRendererAdaptDirty = true;
    },
    getFontSize: function () {
        return this._fontSize;
    },
    setFontName: function (name) {
        this._fontName = name;
        this._labelRenderer.setFontName(name);
        this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
        this._labelRendererAdaptDirty = true;
    },
    getFontName: function () {
        return this._fontName;
    },
    _setFont: function (font) {
        var res = cc.LabelTTF._fontStyleRE.exec(font);
        if (res) {
            this._fontSize = parseInt(res[1]);
            this._fontName = res[2];
            this._labelRenderer._setFont(font);
            this._labelScaleChangedWithSize();
        }
    },
    _getFont: function () {
        return this._labelRenderer._getFont();
    },
    getType: function(){
        return  this._type;
    },
    setTextAreaSize: function (size) {
        this._labelRenderer.setDimensions(size);
        if (!this._ignoreSize){
            this._customSize = size;
        }
        this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
        this._labelRendererAdaptDirty = true;
    },
    getTextAreaSize: function(){
        return this._labelRenderer.getDimensions();
    },
    setTextHorizontalAlignment: function (alignment) {
        this._labelRenderer.setHorizontalAlignment(alignment);
        this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
        this._labelRendererAdaptDirty = true;
    },
    getTextHorizontalAlignment: function () {
        return this._labelRenderer.getHorizontalAlignment();
    },
    setTextVerticalAlignment: function (alignment) {
        this._labelRenderer.setVerticalAlignment(alignment);
        this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
        this._labelRendererAdaptDirty = true;
    },
    getTextVerticalAlignment: function () {
        return this._labelRenderer.getVerticalAlignment();
    },
    setTouchScaleChangeEnabled: function (enable) {
        this._touchScaleChangeEnabled = enable;
    },
    isTouchScaleChangeEnabled: function () {
        return this._touchScaleChangeEnabled;
    },
    _onPressStateChangedToNormal: function () {
        if (!this._touchScaleChangeEnabled)
            return;
        this._labelRenderer.setScaleX(this._normalScaleValueX);
        this._labelRenderer.setScaleY(this._normalScaleValueY);
    },
    _onPressStateChangedToPressed: function () {
        if (!this._touchScaleChangeEnabled)
            return;
        this._labelRenderer.setScaleX(this._normalScaleValueX + this._onSelectedScaleOffset);
        this._labelRenderer.setScaleY(this._normalScaleValueY + this._onSelectedScaleOffset);
    },
    _onPressStateChangedToDisabled: function () {
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._labelRendererAdaptDirty = true;
    },
    _adaptRenderers: function(){
        if (this._labelRendererAdaptDirty) {
            this._labelScaleChangedWithSize();
            this._labelRendererAdaptDirty = false;
        }
    },
    getVirtualRendererSize: function(){
        return this._labelRenderer.getContentSize();
    },
    getVirtualRenderer: function () {
        return this._labelRenderer;
    },
    getAutoRenderSize: function(){
        var virtualSize = this._labelRenderer.getContentSize();
        if (!this._ignoreSize) {
            this._labelRenderer.setDimensions(0, 0);
            virtualSize = this._labelRenderer.getContentSize();
            this._labelRenderer.setDimensions(this._contentSize.width, this._contentSize.height);
        }
        return virtualSize;
    },
    _labelScaleChangedWithSize: function () {
        var locContentSize = this._contentSize;
        if (this._ignoreSize) {
            this._labelRenderer.setDimensions(0,0);
            this._labelRenderer.setScale(1.0);
            this._normalScaleValueX = this._normalScaleValueY = 1;
        } else {
            this._labelRenderer.setDimensions(cc.size(locContentSize.width, locContentSize.height));
            var textureSize = this._labelRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                this._labelRenderer.setScale(1.0);
                return;
            }
            var scaleX = locContentSize.width / textureSize.width;
            var scaleY = locContentSize.height / textureSize.height;
            this._labelRenderer.setScaleX(scaleX);
            this._labelRenderer.setScaleY(scaleY);
            this._normalScaleValueX = scaleX;
            this._normalScaleValueY = scaleY;
        }
        this._labelRenderer.setPosition(locContentSize.width / 2.0, locContentSize.height / 2.0);
    },
    getDescription: function () {
        return "Label";
    },
    enableShadow: function(shadowColor, offset, blurRadius){
        this._labelRenderer.enableShadow(shadowColor, offset, blurRadius);
    },
    enableOutline: function(outlineColor, outlineSize){
        this._labelRenderer.enableStroke(outlineColor, outlineSize);
    },
    enableGlow: function(glowColor){
        if (this._type === ccui.Text.Type.TTF)
            this._labelRenderer.enableGlow(glowColor);
    },
    disableEffect: function(){
        if(this._labelRenderer.disableEffect)
            this._labelRenderer.disableEffect();
    },
    _createCloneInstance: function () {
        return new ccui.Text();
    },
    _copySpecialProperties: function (uiLabel) {
        if(uiLabel instanceof ccui.Text){
            this.setFontName(uiLabel._fontName);
            this.setFontSize(uiLabel.getFontSize());
            this.setString(uiLabel.getString());
            this.setTouchScaleChangeEnabled(uiLabel.touchScaleEnabled);
            this.setTextAreaSize(uiLabel._textAreaSize);
            this.setTextHorizontalAlignment(uiLabel._labelRenderer.getHorizontalAlignment());
            this.setTextVerticalAlignment(uiLabel._labelRenderer.getVerticalAlignment());
            this.setContentSize(uiLabel.getContentSize());
            this.setTextColor(uiLabel.getTextColor());
        }
    },
    _setBoundingWidth: function (value) {
        this._textAreaSize.width = value;
        this._labelRenderer._setBoundingWidth(value);
        this._labelScaleChangedWithSize();
    },
    _setBoundingHeight: function (value) {
        this._textAreaSize.height = value;
        this._labelRenderer._setBoundingHeight(value);
        this._labelScaleChangedWithSize();
    },
    _getBoundingWidth: function () {
        return this._textAreaSize.width;
    },
    _getBoundingHeight: function () {
        return this._textAreaSize.height;
    },
    _changePosition: function(){
        this._adaptRenderers();
    },
    setColor: function(color){
        cc.ProtectedNode.prototype.setColor.call(this, color);
        this._labelRenderer.setColor(color);
    },
    setTextColor: function(color){
        this._labelRenderer.setFontFillColor(color);
    },
    getTextColor: function(){
        return this._labelRenderer._getFillStyle();
    }
});
var _p = ccui.Text.prototype;
_p.boundingWidth;
cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
_p.boundingHeight;
cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
_p.string;
cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
_p.stringLength;
cc.defineGetterSetter(_p, "stringLength", _p.getStringLength);
_p.font;
cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
_p.fontSize;
cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
_p.fontName;
cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
_p.textAlign;
cc.defineGetterSetter(_p, "textAlign", _p.getTextHorizontalAlignment, _p.setTextHorizontalAlignment);
_p.verticalAlign;
cc.defineGetterSetter(_p, "verticalAlign", _p.getTextVerticalAlignment, _p.setTextVerticalAlignment);
_p = null;
ccui.Label = ccui.Text.create = function (textContent, fontName, fontSize) {
    return new ccui.Text(textContent, fontName, fontSize);
};
ccui.Text.RENDERER_ZORDER = -1;
ccui.Text.Type = {
    SYSTEM: 0,
    TTF: 1
};
ccui.TextAtlas = ccui.Widget.extend({
    _labelAtlasRenderer: null,
    _stringValue: "",
    _charMapFileName: "",
    _itemWidth: 0,
    _itemHeight: 0,
    _startCharMap: "",
    _className: "TextAtlas",
    _labelAtlasRendererAdaptDirty: null,
    ctor: function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap) {
        ccui.Widget.prototype.ctor.call(this);
        if (startCharMap !== undefined) {
            this.setProperty(stringValue, charMapFile, itemWidth, itemHeight, startCharMap);
        }
    },
    _initRenderer: function () {
        this._labelAtlasRenderer = new cc.LabelAtlas();
        this._labelAtlasRenderer.setAnchorPoint(cc.p(0.5, 0.5));
        this.addProtectedChild(this._labelAtlasRenderer, ccui.TextAtlas.RENDERER_ZORDER, -1);
    },
    setProperty: function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap) {
        this._stringValue = stringValue;
        this._charMapFileName = charMapFile;
        this._itemWidth = itemWidth;
        this._itemHeight = itemHeight;
        this._startCharMap = startCharMap;
        this._labelAtlasRenderer.initWithString(
            stringValue,
            this._charMapFileName,
            this._itemWidth,
            this._itemHeight,
            this._startCharMap[0]
        );
        this._updateContentSizeWithTextureSize(this._labelAtlasRenderer.getContentSize());
        this._labelAtlasRendererAdaptDirty = true;
    },
    setString: function (value) {
        if(value === this._labelAtlasRenderer.getString())
            return;
        this._stringValue = value;
        this._labelAtlasRenderer.setString(value);
        this._updateContentSizeWithTextureSize(this._labelAtlasRenderer.getContentSize());
        this._labelAtlasRendererAdaptDirty = true;
    },
    setStringValue: function (value) {
        cc.log("Please use the setString");
        this.setString(value);
    },
    getStringValue: function () {
        cc.log("Please use the getString");
        return this.getString();
    },
    getString: function () {
        return this._labelAtlasRenderer.getString();
    },
    getStringLength: function(){
        return this._labelAtlasRenderer.getStringLength();
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._labelAtlasRendererAdaptDirty = true;
    },
    _adaptRenderers: function(){
        if (this._labelAtlasRendererAdaptDirty){
            this._labelAtlasScaleChangedWithSize();
            this._labelAtlasRendererAdaptDirty = false;
        }
    },
    getVirtualRendererSize: function(){
        return this._labelAtlasRenderer.getContentSize();
    },
    getVirtualRenderer: function () {
        return this._labelAtlasRenderer;
    },
    _labelAtlasScaleChangedWithSize: function () {
        var locRenderer = this._labelAtlasRenderer;
        if (this._ignoreSize) {
            locRenderer.setScale(1.0);
        } else {
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                locRenderer.setScale(1.0);
                return;
            }
            locRenderer.setScaleX(this._contentSize.width / textureSize.width);
            locRenderer.setScaleY(this._contentSize.height / textureSize.height);
        }
        locRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
    },
    getDescription: function () {
        return "LabelAtlas";
    },
    _copySpecialProperties: function (labelAtlas) {
        if (labelAtlas){
            this.setProperty(labelAtlas._stringValue, labelAtlas._charMapFileName, labelAtlas._itemWidth, labelAtlas._itemHeight, labelAtlas._startCharMap);
        }
    },
    _createCloneInstance: function () {
        return new ccui.TextAtlas();
    }
});
var _p = ccui.TextAtlas.prototype;
_p.string;
cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
_p = null;
ccui.TextAtlas.create = function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap) {
    return new ccui.TextAtlas(stringValue, charMapFile, itemWidth, itemHeight, startCharMap);
};
ccui.TextAtlas.RENDERER_ZORDER = -1;
ccui.LabelBMFont = ccui.TextBMFont = ccui.Widget.extend({
    _labelBMFontRenderer: null,
    _fntFileHasInit: false,
    _fntFileName: "",
    _stringValue: "",
    _className: "TextBMFont",
    _labelBMFontRendererAdaptDirty: true,
    ctor: function (text, filename) {
        ccui.Widget.prototype.ctor.call(this);
        if (filename !== undefined) {
            this.setFntFile(filename);
            this.setString(text);
        }
    },
    _initRenderer: function () {
        this._labelBMFontRenderer = new cc.LabelBMFont();
        this.addProtectedChild(this._labelBMFontRenderer, ccui.TextBMFont.RENDERER_ZORDER, -1);
    },
    setFntFile: function (fileName) {
        if (!fileName)
            return;
        this._fntFileName = fileName;
        this._fntFileHasInit = true;
        this._labelBMFontRenderer.initWithString(this._stringValue, fileName);
        this._updateContentSizeWithTextureSize(this._labelBMFontRenderer.getContentSize());
        this._labelBMFontRendererAdaptDirty = true;
        var _self = this;
        var locRenderer = _self._labelBMFontRenderer;
        if(!locRenderer._textureLoaded){
             locRenderer.addEventListener("load", function(){
                 _self.setFntFile(_self._fntFileName);
                 var parent = _self.parent;
                 while (parent) {
                     if (parent.requestDoLayout) {
                         parent.requestDoLayout();
                         break;
                     }
                     parent = parent.parent;
                 }
             });
        }
    },
    setText: function (value) {
        cc.log("Please use the setString");
        this.setString(value);
    },
    setString: function (value) {
        if(value === this._labelBMFontRenderer.getString())
            return;
        this._stringValue = value;
        this._labelBMFontRenderer.setString(value);
        if (!this._fntFileHasInit)
            return;
        this._updateContentSizeWithTextureSize(this._labelBMFontRenderer.getContentSize());
        this._labelBMFontRendererAdaptDirty = true;
    },
    getString: function () {
        return this._stringValue;
    },
    getStringLength: function(){
        return this._labelBMFontRenderer.getStringLength();
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._labelBMFontRendererAdaptDirty = true;
    },
    _adaptRenderers: function(){
        if (this._labelBMFontRendererAdaptDirty){
            this._labelBMFontScaleChangedWithSize();
            this._labelBMFontRendererAdaptDirty = false;
        }
    },
    getVirtualRendererSize: function(){
        return this._labelBMFontRenderer.getContentSize();
    },
    getVirtualRenderer: function () {
        return this._labelBMFontRenderer;
    },
    _labelBMFontScaleChangedWithSize: function () {
        var locRenderer = this._labelBMFontRenderer;
        if (this._ignoreSize)
            locRenderer.setScale(1.0);
        else {
            var textureSize = locRenderer.getContentSize();
            if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
                locRenderer.setScale(1.0);
                return;
            }
            locRenderer.setScaleX(this._contentSize.width / textureSize.width);
            locRenderer.setScaleY(this._contentSize.height / textureSize.height);
        }
        locRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
    },
    getDescription: function () {
        return "TextBMFont";
    },
    _createCloneInstance: function () {
        return new ccui.TextBMFont();
    },
    _copySpecialProperties: function (labelBMFont) {
        this.setFntFile(labelBMFont._fntFileName);
        this.setString(labelBMFont._stringValue);
    }
});
var _p = ccui.TextBMFont.prototype;
_p.string;
cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
_p = null;
ccui.TextBMFont.create = function (text, filename) {
    return new ccui.TextBMFont(text, filename);
};
ccui.TextBMFont.RENDERER_ZORDER = -1;
ccui._TextFieldRenderer = cc.TextFieldTTF.extend({
    _maxLengthEnabled: false,
    _maxLength: 0,
    _passwordEnabled: false,
    _passwordStyleText: "",
    _attachWithIME: false,
    _detachWithIME: false,
    _insertText: false,
    _deleteBackward: false,
    _className: "_TextFieldRenderer",
    ctor: function () {
        cc.TextFieldTTF.prototype.ctor.call(this);
        this._maxLengthEnabled = false;
        this._maxLength = 0;
        this._passwordEnabled = false;
        this._passwordStyleText = "*";
        this._attachWithIME = false;
        this._detachWithIME = false;
        this._insertText = false;
        this._deleteBackward = false;
    },
    onEnter: function () {
        cc.TextFieldTTF.prototype.onEnter.call(this);
        cc.TextFieldTTF.prototype.setDelegate.call(this, this);
    },
    onTextFieldAttachWithIME: function (sender) {
        this.setAttachWithIME(true);
        return false;
    },
    onTextFieldInsertText: function (sender, text, len) {
        if (len === 1 && text === "\n")
            return false;
        this.setInsertText(true);
        return (this._maxLengthEnabled) && (cc.TextFieldTTF.prototype.getCharCount.call(this) >= this._maxLength);
    },
    onTextFieldDeleteBackward: function (sender, delText, nLen) {
        this.setDeleteBackward(true);
        return false;
    },
    onTextFieldDetachWithIME: function (sender) {
        this.setDetachWithIME(true);
        return false;
    },
    insertText: function (text, len) {
        var input_text = text;
        if (text !== "\n"){
            if (this._maxLengthEnabled){
                var text_count = this.getString().length;
                if (text_count >= this._maxLength){
                    if (this._passwordEnabled)
                        this.setPasswordText(this.getString());
                    return;
                }
            }
        }
        cc.TextFieldTTF.prototype.insertText.call(this, input_text, len);
        if (this._passwordEnabled && cc.TextFieldTTF.prototype.getCharCount.call(this) > 0)
            this.setPasswordText(this.getString());
    },
    deleteBackward: function () {
        cc.TextFieldTTF.prototype.deleteBackward.call(this);
        if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0 && this._passwordEnabled)
            this.setPasswordText(this._inputText);
    },
    openIME: function () {
        cc.TextFieldTTF.prototype.attachWithIME.call(this);
    },
    closeIME: function () {
        cc.TextFieldTTF.prototype.detachWithIME.call(this);
    },
    setMaxLengthEnabled: function (enable) {
        this._maxLengthEnabled = enable;
    },
    isMaxLengthEnabled: function () {
        return this._maxLengthEnabled;
    },
    setMaxLength: function (length) {
        this._maxLength = length;
    },
    getMaxLength: function () {
        return this._maxLength;
    },
    getCharCount: function () {
        return cc.TextFieldTTF.prototype.getCharCount.call(this);
    },
    setPasswordEnabled: function (enable) {
        this._passwordEnabled = enable;
    },
    isPasswordEnabled: function () {
        return this._passwordEnabled;
    },
    setPasswordStyleText: function (styleText) {
        if (styleText.length > 1)
            return;
        var header = styleText.charCodeAt(0);
        if (header < 33 || header > 126)
            return;
        this._passwordStyleText = styleText;
    },
    setPasswordText: function (text) {
        var tempStr = "";
        var text_count = text.length;
        var max = text_count;
        if (this._maxLengthEnabled && text_count > this._maxLength)
            max = this._maxLength;
        for (var i = 0; i < max; ++i)
            tempStr += this._passwordStyleText;
        cc.LabelTTF.prototype.setString.call(this, tempStr);
    },
    setAttachWithIME: function (attach) {
        this._attachWithIME = attach;
    },
    getAttachWithIME: function () {
        return this._attachWithIME;
    },
    setDetachWithIME: function (detach) {
        this._detachWithIME = detach;
    },
    getDetachWithIME: function () {
        return this._detachWithIME;
    },
    setInsertText: function (insert) {
        this._insertText = insert;
    },
    getInsertText: function () {
        return this._insertText;
    },
    setDeleteBackward: function (deleteBackward) {
        this._deleteBackward = deleteBackward;
    },
    getDeleteBackward: function () {
        return this._deleteBackward;
    },
    onDraw: function (sender) {
        return false;
    }
});
ccui._TextFieldRenderer.create = function (placeholder, fontName, fontSize) {
    var ret = new ccui._TextFieldRenderer();
    if (ret && ret.initWithString("", fontName, fontSize)) {
        if (placeholder)
            ret.setPlaceHolder(placeholder);
        return ret;
    }
    return null;
};
ccui.TextField = ccui.Widget.extend({
    _textFieldRenderer: null,
    _touchWidth: 0,
    _touchHeight: 0,
    _useTouchArea: false,
    _textFieldEventListener: null,
    _textFieldEventSelector: null,
    _passwordStyleText: "",
    _textFieldRendererAdaptDirty: true,
    _fontName: "",
    _fontSize: 12,
    _ccEventCallback: null,
    ctor: function (placeholder, fontName, fontSize) {
        ccui.Widget.prototype.ctor.call(this);
        this.setTouchEnabled(true);
        if (fontName)
            this.setFontName(fontName);
        if (fontSize)
            this.setFontSize(fontSize);
        if (placeholder)
            this.setPlaceHolder(placeholder);
    },
    onEnter: function () {
        ccui.Widget.prototype.onEnter.call(this);
        this.scheduleUpdate();
    },
    _initRenderer: function () {
        this._textFieldRenderer = ccui._TextFieldRenderer.create("input words here", "Thonburi", 20);
        this.addProtectedChild(this._textFieldRenderer, ccui.TextField.RENDERER_ZORDER, -1);
    },
    setTouchSize: function (size) {
        this._touchWidth = size.width;
        this._touchHeight = size.height;
    },
    setTouchAreaEnabled: function(enable){
        this._useTouchArea = enable;
    },
    hitTest: function(pt){
        if (this._useTouchArea) {
            var nsp = this.convertToNodeSpace(pt);
            var bb = cc.rect(
                -this._touchWidth * this._anchorPoint.x,
                -this._touchHeight * this._anchorPoint.y,
                this._touchWidth, this._touchHeight
            );
            return ( nsp.x >= bb.x && nsp.x <= bb.x + bb.width &&
                nsp.y >= bb.y && nsp.y <= bb.y + bb.height );
        } else
            return ccui.Widget.prototype.hitTest.call(this, pt);
    },
    getTouchSize: function () {
        return cc.size(this._touchWidth, this._touchHeight);
    },
    setText: function (text) {
        cc.log("Please use the setString");
        this.setString(text);
    },
    setString: function (text) {
        if (text == null)
            return;
        text = String(text);
        if (this.isMaxLengthEnabled())
            text = text.substr(0, this.getMaxLength());
        if (this.isPasswordEnabled()) {
            this._textFieldRenderer.setPasswordText(text);
            this._textFieldRenderer.setString("");
            this._textFieldRenderer.insertText(text, text.length);
        } else
            this._textFieldRenderer.setString(text);
        this._textFieldRendererAdaptDirty = true;
        this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
    },
    setPlaceHolder: function (value) {
        this._textFieldRenderer.setPlaceHolder(value);
        this._textFieldRendererAdaptDirty = true;
        this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
    },
    getPlaceHolder: function () {
        return this._textFieldRenderer.getPlaceHolder();
    },
    getPlaceHolderColor: function(){
        return this._textFieldRenderer.getPlaceHolderColor();
    },
    setPlaceHolderColor: function(color){
        this._textFieldRenderer.setColorSpaceHolder(color);
    },
    setTextColor: function(textColor){
        this._textFieldRenderer.setTextColor(textColor);
    },
    setFontSize: function (size) {
        this._textFieldRenderer.setFontSize(size);
        this._fontSize = size;
        this._textFieldRendererAdaptDirty = true;
        this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
    },
    getFontSize: function () {
        return this._fontSize;
    },
    setFontName: function (name) {
        this._textFieldRenderer.setFontName(name);
        this._fontName = name;
        this._textFieldRendererAdaptDirty = true;
        this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
    },
    getFontName: function () {
        return this._fontName;
    },
    didNotSelectSelf: function () {
        this._textFieldRenderer.detachWithIME();
    },
    getStringValue: function () {
        cc.log("Please use the getString");
        return this.getString();
    },
    getString: function () {
        return this._textFieldRenderer.getString();
    },
    getStringLength: function(){
        return this._textFieldRenderer.getStringLength();
    },
    onTouchBegan: function (touchPoint, unusedEvent) {
        var self = this;
        var pass = ccui.Widget.prototype.onTouchBegan.call(self, touchPoint, unusedEvent);
        if (self._hit) {
            setTimeout(function(){
                self._textFieldRenderer.attachWithIME();
            }, 0);
        }else{
            setTimeout(function(){
                self._textFieldRenderer.detachWithIME();
            }, 0);
        }
        return pass;
    },
    setMaxLengthEnabled: function (enable) {
        this._textFieldRenderer.setMaxLengthEnabled(enable);
    },
    isMaxLengthEnabled: function () {
        return this._textFieldRenderer.isMaxLengthEnabled();
    },
    setMaxLength: function (length) {
        this._textFieldRenderer.setMaxLength(length);
        this.setString(this.getString());
    },
    getMaxLength: function () {
        return this._textFieldRenderer.getMaxLength();
    },
    setPasswordEnabled: function (enable) {
        this._textFieldRenderer.setPasswordEnabled(enable);
    },
    isPasswordEnabled: function () {
        return this._textFieldRenderer.isPasswordEnabled();
    },
    setPasswordStyleText: function(styleText){
        this._textFieldRenderer.setPasswordStyleText(styleText);
        this._passwordStyleText = styleText;
        this.setString(this.getString());
    },
    getPasswordStyleText: function () {
        return this._passwordStyleText;
    },
    update: function (dt) {
        if (this.getDetachWithIME()) {
            this._detachWithIMEEvent();
            this.setDetachWithIME(false);
        }
        if (this.getAttachWithIME()) {
            this._attachWithIMEEvent();
            this.setAttachWithIME(false);
        }
        if (this.getInsertText()) {
            this._textFieldRendererAdaptDirty = true;
            this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
            this._insertTextEvent();
            this.setInsertText(false);
        }
        if (this.getDeleteBackward()) {
            this._textFieldRendererAdaptDirty = true;
            this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
            this._deleteBackwardEvent();
            this.setDeleteBackward(false);
        }
    },
    getAttachWithIME: function () {
        return this._textFieldRenderer.getAttachWithIME();
    },
    setAttachWithIME: function (attach) {
        this._textFieldRenderer.setAttachWithIME(attach);
    },
    getDetachWithIME: function () {
        return this._textFieldRenderer.getDetachWithIME();
    },
    setDetachWithIME: function (detach) {
        this._textFieldRenderer.setDetachWithIME(detach);
    },
    getInsertText: function () {
        return this._textFieldRenderer.getInsertText();
    },
    setInsertText: function (insertText) {
        this._textFieldRenderer.setInsertText(insertText);
    },
    getDeleteBackward: function () {
        return this._textFieldRenderer.getDeleteBackward();
    },
    setDeleteBackward: function (deleteBackward) {
        this._textFieldRenderer.setDeleteBackward(deleteBackward);
    },
    _attachWithIMEEvent: function () {
        if(this._textFieldEventSelector){
            if (this._textFieldEventListener)
                this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_ATTACH_WITH_IME);
            else
                this._textFieldEventSelector(this, ccui.TextField.EVENT_ATTACH_WITH_IME);
        }
        if (this._ccEventCallback){
            this._ccEventCallback(this, ccui.TextField.EVENT_ATTACH_WITH_IME);
        }
    },
    _detachWithIMEEvent: function () {
        if(this._textFieldEventSelector){
            if (this._textFieldEventListener)
                this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DETACH_WITH_IME);
            else
                this._textFieldEventSelector(this, ccui.TextField.EVENT_DETACH_WITH_IME);
        }
        if (this._ccEventCallback)
            this._ccEventCallback(this, ccui.TextField.EVENT_DETACH_WITH_IME);
    },
    _insertTextEvent: function () {
        if(this._textFieldEventSelector){
            if (this._textFieldEventListener)
                this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_INSERT_TEXT);
            else
                this._textFieldEventSelector(this, ccui.TextField.EVENT_INSERT_TEXT);
        }
        if (this._ccEventCallback)
            this._ccEventCallback(this, ccui.TextField.EVENT_INSERT_TEXT);
    },
    _deleteBackwardEvent: function () {
        if(this._textFieldEventSelector){
            if (this._textFieldEventListener)
                this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DELETE_BACKWARD);
            else
                this._textFieldEventSelector(this, ccui.TextField.EVENT_DELETE_BACKWARD);
        }
        if (this._ccEventCallback)
            this._ccEventCallback(this, ccui.TextField.EVENT_DELETE_BACKWARD);
    },
    addEventListenerTextField: function (selector, target) {
        this.addEventListener(selector, target);
    },
    addEventListener: function(selector, target){
        this._textFieldEventSelector = selector;
        this._textFieldEventListener = target;
    },
    _onSizeChanged: function () {
        ccui.Widget.prototype._onSizeChanged.call(this);
        this._textFieldRendererAdaptDirty = true;
    },
    _adaptRenderers: function(){
        if (this._textFieldRendererAdaptDirty) {
            this._textfieldRendererScaleChangedWithSize();
            this._textFieldRendererAdaptDirty = false;
        }
    },
    _textfieldRendererScaleChangedWithSize: function () {
        if (!this._ignoreSize)
            this._textFieldRenderer.setDimensions(this._contentSize);
        this._textFieldRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
    },
    getAutoRenderSize: function(){
        var virtualSize = this._textFieldRenderer.getContentSize();
        if (!this._ignoreSize) {
            this._textFieldRenderer.setDimensions(0, 0);
            virtualSize = this._textFieldRenderer.getContentSize();
            this._textFieldRenderer.setDimensions(this._contentSize.width, this._contentSize.height);
        }
        return virtualSize;
    },
    getVirtualRendererSize: function(){
        return this._textFieldRenderer.getContentSize();
    },
    getVirtualRenderer: function () {
        return this._textFieldRenderer;
    },
    getDescription: function () {
        return "TextField";
    },
    attachWithIME: function () {
        this._textFieldRenderer.attachWithIME();
    },
    _createCloneInstance: function () {
        return new ccui.TextField();
    },
    _copySpecialProperties: function (textField) {
        this.setString(textField._textFieldRenderer.getString());
        this.setPlaceHolder(textField.getString());
        this.setFontSize(textField._textFieldRenderer.getFontSize());
        this.setFontName(textField._textFieldRenderer.getFontName());
        this.setMaxLengthEnabled(textField.isMaxLengthEnabled());
        this.setMaxLength(textField.getMaxLength());
        this.setPasswordEnabled(textField.isPasswordEnabled());
        this.setPasswordStyleText(textField._passwordStyleText);
        this.setAttachWithIME(textField.getAttachWithIME());
        this.setDetachWithIME(textField.getDetachWithIME());
        this.setInsertText(textField.getInsertText());
        this.setDeleteBackward(textField.getDeleteBackward());
        this._ccEventCallback = textField._ccEventCallback;
        this._textFieldEventListener = textField._textFieldEventListener;
        this._textFieldEventSelector = textField._textFieldEventSelector;
    },
    setTextAreaSize: function(size){
        this.setContentSize(size);
    },
    setTextHorizontalAlignment: function(alignment){
        this._textFieldRenderer.setHorizontalAlignment(alignment);
    },
    setTextVerticalAlignment: function(alignment){
        this._textFieldRenderer.setVerticalAlignment(alignment);
    },
    _setFont: function (font) {
        this._textFieldRenderer._setFont(font);
        this._textFieldRendererAdaptDirty = true;
    },
    _getFont: function () {
        return this._textFieldRenderer._getFont();
    },
    _changePosition: function(){
        this._adaptRenderers();
    }
});
ccui.TextField.create = function(placeholder, fontName, fontSize){
    return new ccui.TextField(placeholder, fontName, fontSize);
};
var _p = ccui.TextField.prototype;
_p.string;
cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
_p.placeHolder;
cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
_p.font;
cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
_p.fontSize;
cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
_p.fontName;
cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
_p.maxLengthEnabled;
cc.defineGetterSetter(_p, "maxLengthEnabled", _p.isMaxLengthEnabled, _p.setMaxLengthEnabled);
_p.maxLength;
cc.defineGetterSetter(_p, "maxLength", _p.getMaxLength, _p.setMaxLength);
_p.passwordEnabled;
cc.defineGetterSetter(_p, "passwordEnabled", _p.isPasswordEnabled, _p.setPasswordEnabled);
_p = null;
ccui.TextField.EVENT_ATTACH_WITH_IME = 0;
ccui.TextField.EVENT_DETACH_WITH_IME = 1;
ccui.TextField.EVENT_INSERT_TEXT = 2;
ccui.TextField.EVENT_DELETE_BACKWARD = 3;
ccui.TextField.RENDERER_ZORDER = -1;
ccui.RichElement = ccui.Class.extend({
    _type: 0,
    _tag: 0,
    _color: null,
    _opacity:0,
    ctor: function (tag, color, opacity) {
        this._type = 0;
        this._tag = tag || 0;
        this._color = cc.color(255, 255, 255, 255);
        if (color) {
            this._color.r = color.r;
            this._color.g = color.g;
            this._color.b = color.b;
        }
        this._opacity = opacity || 0;
        if(opacity === undefined) {
            this._color.a = color.a;
        }
        else {
            this._color.a = opacity;
        }
    }
});
ccui.RichElementText = ccui.RichElement.extend({
    _text: "",
    _fontName: "",
    _fontSize: 0,
    _fontDefinition: null,
    ctor: function (tag, colorOrFontDef, opacity, text, fontName, fontSize) {
        var color = colorOrFontDef;
        if (colorOrFontDef && colorOrFontDef instanceof cc.FontDefinition) {
            color = colorOrFontDef.fillStyle;
            fontName = colorOrFontDef.fontName;
            fontSize = colorOrFontDef.fontSize;
            this._fontDefinition = colorOrFontDef;
        }
        ccui.RichElement.prototype.ctor.call(this, tag, color, opacity);
        this._type = ccui.RichElement.TEXT;
        this._text = text;
        this._fontName = fontName;
        this._fontSize = fontSize;
    }
});
ccui.RichElementText.create = function (tag, color, opacity, text, fontName, fontSize) {
    return new ccui.RichElementText(tag, color, opacity, text, fontName, fontSize);
};
ccui.RichElementImage = ccui.RichElement.extend({
    _filePath: "",
    _textureRect: null,
    _textureType: 0,
    ctor: function (tag, color, opacity, filePath) {
        ccui.RichElement.prototype.ctor.call(this, tag, color, opacity);
        this._type = ccui.RichElement.IMAGE;
        this._filePath = filePath || "";
        this._textureRect = cc.rect(0, 0, 0, 0);
        this._textureType = 0;
    }
});
ccui.RichElementImage.create = function (tag, color, opacity, filePath) {
    return new ccui.RichElementImage(tag, color, opacity, filePath);
};
ccui.RichElementCustomNode = ccui.RichElement.extend({
    _customNode: null,
    ctor: function (tag, color, opacity, customNode) {
        ccui.RichElement.prototype.ctor.call(this, tag, color, opacity);
        this._type = ccui.RichElement.CUSTOM;
        this._customNode = customNode || null;
    }
});
ccui.RichElementCustomNode.create = function (tag, color, opacity, customNode) {
    return new ccui.RichElementCustomNode(tag, color, opacity, customNode);
};
ccui.RichText = ccui.Widget.extend({
    _formatTextDirty: false,
    _richElements: null,
    _elementRenders: null,
    _leftSpaceWidth: 0,
    _verticalSpace: 0,
    _elementRenderersContainer: null,
    _lineBreakOnSpace: false,
    _textHorizontalAlignment: null,
    _textVerticalAlignment: null,
    ctor: function () {
        ccui.Widget.prototype.ctor.call(this);
        this._formatTextDirty = false;
        this._richElements = [];
        this._elementRenders = [];
        this._leftSpaceWidth = 0;
        this._verticalSpace = 0;
        this._textHorizontalAlignment = cc.TEXT_ALIGNMENT_LEFT;
        this._textVerticalAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
    },
    _initRenderer: function () {
        this._elementRenderersContainer = new cc.Node();
        this._elementRenderersContainer.setAnchorPoint(0.5, 0.5);
        this.addProtectedChild(this._elementRenderersContainer, 0, -1);
    },
    insertElement: function (element, index) {
        this._richElements.splice(index, 0, element);
        this._formatTextDirty = true;
    },
    pushBackElement: function (element) {
        this._richElements.push(element);
        this._formatTextDirty = true;
    },
    removeElement: function (element) {
        if (cc.isNumber(element))
            this._richElements.splice(element, 1);
         else
            cc.arrayRemoveObject(this._richElements, element);
        this._formatTextDirty = true;
    },
    formatText: function () {
        if (this._formatTextDirty) {
            this._elementRenderersContainer.removeAllChildren();
            this._elementRenders.length = 0;
            var i, element, locRichElements = this._richElements;
            if (this._ignoreSize) {
                this._addNewLine();
                for (i = 0; i < locRichElements.length; i++) {
                    element = locRichElements[i];
                    var elementRenderer = null;
                    switch (element._type) {
                        case ccui.RichElement.TEXT:
                            if( element._fontDefinition)
                                elementRenderer = new cc.LabelTTF(element._text, element._fontDefinition);
                            else
                                elementRenderer = new cc.LabelTTF(element._text, element._fontName, element._fontSize);
                            break;
                        case ccui.RichElement.IMAGE:
                            elementRenderer = new cc.Sprite(element._filePath);
                            break;
                        case ccui.RichElement.CUSTOM:
                            elementRenderer = element._customNode;
                            break;
                        default:
                            break;
                    }
                    elementRenderer.setColor(element._color);
                    elementRenderer.setOpacity(element._color.a);
                    this._pushToContainer(elementRenderer);
                }
            } else {
                this._addNewLine();
                for (i = 0; i < locRichElements.length; i++) {
                    element = locRichElements[i];
                    switch (element._type) {
                        case ccui.RichElement.TEXT:
                            if( element._fontDefinition)
                                this._handleTextRenderer(element._text, element._fontDefinition, element._fontDefinition.fontSize, element._fontDefinition.fillStyle);
                            else
                                this._handleTextRenderer(element._text, element._fontName, element._fontSize, element._color);
                            break;
                        case ccui.RichElement.IMAGE:
                            this._handleImageRenderer(element._filePath, element._color, element._color.a);
                            break;
                        case ccui.RichElement.CUSTOM:
                            this._handleCustomRenderer(element._customNode);
                            break;
                        default:
                            break;
                    }
                }
            }
            this.formatRenderers();
            this._formatTextDirty = false;
        }
    },
    _handleTextRenderer: function (text, fontNameOrFontDef, fontSize, color) {
        if(text === "")
            return;
        if(text === "\n"){
            this._addNewLine();
            return;
        }
        var textRenderer = fontNameOrFontDef instanceof cc.FontDefinition ? new cc.LabelTTF(text, fontNameOrFontDef) : new cc.LabelTTF(text, fontNameOrFontDef, fontSize);
        var textRendererWidth = textRenderer.getContentSize().width;
        this._leftSpaceWidth -= textRendererWidth;
        if (this._leftSpaceWidth < 0) {
            var overstepPercent = (-this._leftSpaceWidth) / textRendererWidth;
            var curText = text;
            var stringLength = curText.length;
            var leftLength = stringLength * (1 - overstepPercent);
            var leftWords = curText.substr(0, leftLength);
            var cutWords = curText.substr(leftLength, curText.length - 1);
            var validLeftLength = leftLength > 0;
            if(this._lineBreakOnSpace){
                var lastSpaceIndex = leftWords.lastIndexOf(' ');
                leftLength = lastSpaceIndex === -1 ? leftLength : lastSpaceIndex+1 ;
                cutWords = curText.substr(leftLength, curText.length - 1);
                validLeftLength = leftLength > 0 && cutWords !== " ";
            }
            if (validLeftLength) {
                var leftRenderer = null;
                if( fontNameOrFontDef instanceof cc.FontDefinition)
                {
                    leftRenderer = new cc.LabelTTF(leftWords.substr(0, leftLength), fontNameOrFontDef);
                    leftRenderer.setOpacity(fontNameOrFontDef.fillStyle.a);
                }else{
                    leftRenderer =  new cc.LabelTTF(leftWords.substr(0, leftLength), fontNameOrFontDef, fontSize);
                    leftRenderer.setColor(color);
                    leftRenderer.setOpacity(color.a);
                }
                this._pushToContainer(leftRenderer);
            }
            this._addNewLine();
            this._handleTextRenderer(cutWords, fontNameOrFontDef, fontSize, color);
        } else {
            if( fontNameOrFontDef instanceof cc.FontDefinition) {
                textRenderer.setOpacity(fontNameOrFontDef.fillStyle.a);
            }else {
                textRenderer.setColor(color);
                textRenderer.setOpacity(color.a);
            }
            this._pushToContainer(textRenderer);
        }
    },
    _handleImageRenderer: function (filePath, color, opacity) {
        var imageRenderer = new cc.Sprite(filePath);
        this._handleCustomRenderer(imageRenderer);
    },
    _handleCustomRenderer: function (renderer) {
        var imgSize = renderer.getContentSize();
        this._leftSpaceWidth -= imgSize.width;
        if (this._leftSpaceWidth < 0) {
            this._addNewLine();
            this._pushToContainer(renderer);
            this._leftSpaceWidth -= imgSize.width;
        } else
            this._pushToContainer(renderer);
    },
    _addNewLine: function () {
        this._leftSpaceWidth = this._customSize.width;
        this._elementRenders.push([]);
    },
    formatRenderers: function () {
        var newContentSizeHeight = 0, locRenderersContainer = this._elementRenderersContainer;
        var locElementRenders = this._elementRenders;
        var i, j, row, nextPosX, l;
        var lineHeight, offsetX;
        if (this._ignoreSize) {
            var newContentSizeWidth = 0;
            row = locElementRenders[0];
            nextPosX = 0;
            for (j = 0; j < row.length; j++) {
                l = row[j];
                l.setAnchorPoint(cc.p(0, 0));
                l.setPosition(nextPosX, 0);
                locRenderersContainer.addChild(l, 1, j);
                lineHeight = l.getLineHeight ? l.getLineHeight() : newContentSizeHeight;
                var iSize = l.getContentSize();
                newContentSizeWidth += iSize.width;
                newContentSizeHeight = Math.max(Math.min(newContentSizeHeight, lineHeight), iSize.height);
                nextPosX += iSize.width;
            }
            if(this._textHorizontalAlignment !== cc.TEXT_ALIGNMENT_LEFT) {
                offsetX = 0;
                if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_RIGHT)
                    offsetX = this._contentSize.width - nextPosX;
                else if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_CENTER)
                    offsetX = (this._contentSize.width - nextPosX) / 2;
                for (j = 0; j < row.length; j++)
                    row[j].x += offsetX;
            }
            locRenderersContainer.setContentSize(newContentSizeWidth, newContentSizeHeight);
        } else {
            var maxHeights = [];
            for (i = 0; i < locElementRenders.length; i++) {
                row = locElementRenders[i];
                var maxHeight = 0;
                for (j = 0; j < row.length; j++) {
                    l = row[j];
                    lineHeight = l.getLineHeight ? l.getLineHeight() : l.getContentSize().height;
                    maxHeight = Math.max(Math.min(l.getContentSize().height, lineHeight), maxHeight);
                }
                maxHeights[i] = maxHeight;
                newContentSizeHeight += maxHeights[i];
            }
            var nextPosY = this._customSize.height;
            for (i = 0; i < locElementRenders.length; i++) {
                row = locElementRenders[i];
                nextPosX = 0;
                nextPosY -= (maxHeights[i] + this._verticalSpace);
                for (j = 0; j < row.length; j++) {
                    l = row[j];
                    l.setAnchorPoint(cc.p(0, 0));
                    l.setPosition(cc.p(nextPosX, nextPosY));
                    locRenderersContainer.addChild(l, 1);
                    nextPosX += l.getContentSize().width;
                }
                if( this._textHorizontalAlignment !== cc.TEXT_ALIGNMENT_LEFT || this._textVerticalAlignment !== cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
                    offsetX = 0;
                    if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_RIGHT)
                        offsetX = this._contentSize.width - nextPosX;
                    else if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_CENTER)
                        offsetX = (this._contentSize.width - nextPosX) / 2;
                    var offsetY = 0;
                    if (this._textVerticalAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM)
                        offsetY = this._customSize.height - newContentSizeHeight;
                    else if (this._textVerticalAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
                        offsetY = (this._customSize.height - newContentSizeHeight) / 2;
                    for (j = 0; j < row.length; j++) {
                        l = row[j];
                        l.x += offsetX;
                        l.y -= offsetY;
                    }
                }
            }
            locRenderersContainer.setContentSize(this._contentSize);
        }
        var length = locElementRenders.length;
        for (i = 0; i<length; i++){
            locElementRenders[i].length = 0;
        }
        this._elementRenders.length = 0;
        this.setContentSize(this._ignoreSize?this.getVirtualRendererSize():this._customSize);
        this._updateContentSizeWithTextureSize(this._contentSize);
        locRenderersContainer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
    },
    _pushToContainer: function (renderer) {
        if (this._elementRenders.length <= 0)
            return;
        this._elementRenders[this._elementRenders.length - 1].push(renderer);
    },
    _adaptRenderers: function(){
        this.formatText();
    },
    setVerticalSpace: function (space) {
        this._verticalSpace = space;
    },
    setAnchorPoint: function (pt) {
        ccui.Widget.prototype.setAnchorPoint.call(this, pt);
        this._elementRenderersContainer.setAnchorPoint(pt);
    },
    _setAnchorX: function (x) {
        ccui.Widget.prototype._setAnchorX.call(this, x);
        this._elementRenderersContainer._setAnchorX(x);
    },
    _setAnchorY: function (y) {
        ccui.Widget.prototype._setAnchorY.call(this, y);
        this._elementRenderersContainer._setAnchorY(y);
    },
    getVirtualRendererSize: function(){
        return this._elementRenderersContainer.getContentSize();
    },
    ignoreContentAdaptWithSize: function (ignore) {
        if (this._ignoreSize !== ignore) {
            this._formatTextDirty = true;
            ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
        }
    },
    getContentSize: function(){
        this.formatText();
        return cc.Node.prototype.getContentSize.call(this);
    },
    _getWidth: function() {
        this.formatText();
        return cc.Node.prototype._getWidth.call(this);
    },
    _getHeight: function() {
        this.formatText();
        return cc.Node.prototype._getHeight.call(this);
    },
    setContentSize: function(contentSize, height){
        var locWidth = (height === undefined) ? contentSize.width : contentSize;
        var locHeight = (height === undefined) ? contentSize.height : height;
        ccui.Widget.prototype.setContentSize.call(this, locWidth, locHeight);
        this._formatTextDirty = true;
    },
    getDescription: function(){
        return "RichText";
    },
    setCascadeOpacityEnabled: function(value) {
        this._super(value);
        this._elementRenderersContainer.setCascadeOpacityEnabled(value);
    },
    setLineBreakOnSpace: function(value){
        this._lineBreakOnSpace = value;
        this._formatTextDirty = true;
        this.formatText();
    },
    setTextHorizontalAlignment: function(value){
        if(value !== this._textHorizontalAlignment) {
            this._textHorizontalAlignment = value;
            this.formatText();
        }
    },
    setTextVerticalAlignment: function(value){
        if(value !== this._textVerticalAlignment) {
            this._textVerticalAlignment = value;
            this.formatText();
        }
    }
});
ccui.RichText.create = function(){
    return new ccui.RichText();
};
ccui.RichElement.TEXT = 0;
ccui.RichElement.IMAGE = 1;
ccui.RichElement.CUSTOM = 2;
ccui.ScrollViewBar = ccui.ProtectedNode.extend({
    _parentScroll: null,
    _direction: null,
    _upperHalfCircle: null,
    _lowerHalfCircle: null,
    _body: null,
    _opacity : 255,
    _marginFromBoundary : 0,
    _marginForLength: 0,
    _touching: false,
    _autoHideEnabled: true,
    autoHideTime : 0,
    _autoHideRemainingTime : 0,
    _className: "ScrollViewBar",
    ctor: function (parent, direction) {
        cc.ProtectedNode.prototype.ctor.call(this);
        this._direction = direction;
        this._parentScroll  = parent;
        this._marginFromBoundary = ccui.ScrollViewBar.DEFAULT_MARGIN;
        this._marginForLength = ccui.ScrollViewBar.DEFAULT_MARGIN;
        this.opacity = 255 * ccui.ScrollViewBar.DEFAULT_SCROLLBAR_OPACITY;
        this.autoHideTime = ccui.ScrollViewBar.DEFAULT_AUTO_HIDE_TIME;
        this._autoHideEnabled = true;
        ccui.ScrollViewBar.prototype.init.call(this);
        this.setCascadeColorEnabled(true);
        this.setCascadeOpacityEnabled(true);
    },
    init: function () {
        this._upperHalfCircle = ccui.helper._createSpriteFromBase64(ccui.ScrollViewBar.HALF_CIRCLE_IMAGE, ccui.ScrollViewBar.HALF_CIRCLE_IMAGE_KEY);
        this._upperHalfCircle.setAnchorPoint(cc.p(0.5, 0));
        this._lowerHalfCircle = ccui.helper._createSpriteFromBase64(ccui.ScrollViewBar.HALF_CIRCLE_IMAGE, ccui.ScrollViewBar.HALF_CIRCLE_IMAGE_KEY);
        this._lowerHalfCircle.setAnchorPoint(cc.p(0.5, 0));
        this._lowerHalfCircle.setScaleY(-1);
        this.addProtectedChild(this._upperHalfCircle);
        this.addProtectedChild(this._lowerHalfCircle);
        this._body =  ccui.helper._createSpriteFromBase64(ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT, ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT_KEY);
        this._body.setAnchorPoint(cc.p(0.5, 0));
        this.addProtectedChild(this._body);
        this.setColor(ccui.ScrollViewBar.DEFAULT_COLOR);
        this.onScrolled(cc.p(0, 0));
        cc.ProtectedNode.prototype.setOpacity.call(this, 0);
        this._autoHideRemainingTime = 0;
        if(this._direction === ccui.ScrollView.DIR_HORIZONTAL)
        {
            this.setRotation(90);
        }
    },
    setPositionFromCorner: function(positionFromCorner)
    {
        if(this._direction === ccui.ScrollView.DIR_VERTICAL)
        {
            this._marginForLength = positionFromCorner.y;
            this._marginFromBoundary = positionFromCorner.x;
        }
        else
        {
            this._marginForLength = positionFromCorner.x;
            this._marginFromBoundary = positionFromCorner.y;
        }
    },
    onEnter: function()
    {
        cc.ProtectedNode.prototype.onEnter.call(this);
        this.scheduleUpdate();
    },
    getPositionFromCorner: function()
    {
        if(this._direction === ccui.ScrollView.DIR_VERTICAL)
        {
            return cc.p(this._marginFromBoundary, this._marginForLength);
        }
        else
        {
            return cc.p(this._marginForLength, this._marginFromBoundary);
        }
    },
    setWidth: function(width)
    {
        var scale = width / this._body.width;
        this._body.setScaleX(scale);
        this._upperHalfCircle.setScale(scale);
        this._lowerHalfCircle.setScale(-scale);
    },
    getWidth: function()
    {
        return this._body.getBoundingBox().width;
    },
    setAutoHideEnabled: function(autoHideEnabled)
    {
        this._autoHideEnabled = autoHideEnabled;
        if(!this._autoHideEnabled && !this._touching && this._autoHideRemainingTime <= 0)
            cc.ProtectedNode.prototype.setOpacity.call(this, this.opacity);
        else
            cc.ProtectedNode.prototype.setOpacity.call(this, 0);
    },
    isAutoHideEnabled: function()
    {
        return this._autoHideEnabled;
    },
    setOpacity: function(opacity)
    {
        this._opacity = opacity;
    },
    getOpacity: function()
    {
        return this._opacity;
    },
    _updateLength: function(length)
    {
        var ratio = length / this._body.getTextureRect().height;
        this._body.setScaleY(ratio);
        this._upperHalfCircle.setPositionY(this._body.getPositionY() + length);
    },
    _processAutoHide: function(dt)
    {
        if(!this._autoHideEnabled || this._autoHideRemainingTime <= 0)
        {
            return;
        }
        else if(this._touching)
        {
            return;
        }
        this._autoHideRemainingTime -= dt;
        if(this._autoHideRemainingTime <= this.autoHideTime)
        {
            this. _autoHideRemainingTime = Math.max(0, this._autoHideRemainingTime);
            cc.ProtectedNode.prototype.setOpacity.call(this, this._opacity * (this._autoHideRemainingTime / this.autoHideTime));
        }
    },
    update: function(dt)
    {
        this._processAutoHide(dt);
    },
    onTouchBegan: function()
    {
        if(!this._autoHideEnabled)
        {
            return;
        }
        this._touching = true;
    },
    onTouchEnded: function()
    {
        if(!this._autoHideEnabled)
        {
            return;
        }
        this._touching = false;
        if(this._autoHideRemainingTime <= 0)
        {
            return;
        }
        this._autoHideRemainingTime = this.autoHideTime;
    },
    onScrolled: function(outOfBoundary)
    {
        if(this._autoHideEnabled)
        {
            this._autoHideRemainingTime = this.autoHideTime;
            cc.ProtectedNode.prototype.setOpacity.call(this, this.opacity);
        }
        var innerContainer = this._parentScroll.getInnerContainer();
        var innerContainerMeasure = 0;
        var scrollViewMeasure = 0;
        var outOfBoundaryValue = 0;
        var innerContainerPosition = 0;
        if(this._direction === ccui.ScrollView.DIR_VERTICAL)
        {
            innerContainerMeasure = innerContainer.height;
            scrollViewMeasure = this._parentScroll.height;
            outOfBoundaryValue = outOfBoundary.y;
            innerContainerPosition = -innerContainer.getPositionY();
        }
        else if(this._direction === ccui.ScrollView.DIR_HORIZONTAL)
        {
            innerContainerMeasure = innerContainer.width;
            scrollViewMeasure = this._parentScroll.width;
            outOfBoundaryValue = outOfBoundary.x;
            innerContainerPosition = -innerContainer.getPositionX();
        }
        var length = this._calculateLength(innerContainerMeasure, scrollViewMeasure, outOfBoundaryValue);
        var position = this._calculatePosition(innerContainerMeasure, scrollViewMeasure, innerContainerPosition, outOfBoundaryValue, length);
        this._updateLength(length);
        this.setPosition(position);
    },
    _calculateLength: function(innerContainerMeasure, scrollViewMeasure, outOfBoundaryValue)
    {
        var denominatorValue = innerContainerMeasure;
        if(outOfBoundaryValue !== 0)
        {
            var GETTING_SHORTER_FACTOR = 20;
            denominatorValue += (outOfBoundaryValue > 0 ? outOfBoundaryValue : -outOfBoundaryValue) * GETTING_SHORTER_FACTOR;
        }
        var lengthRatio = scrollViewMeasure / denominatorValue;
        return Math.abs(scrollViewMeasure - 2 * this._marginForLength) * lengthRatio;
    },
    _calculatePosition: function(innerContainerMeasure, scrollViewMeasure, innerContainerPosition, outOfBoundaryValue, length)
    {
        var denominatorValue = innerContainerMeasure - scrollViewMeasure;
        if(outOfBoundaryValue !== 0)
        {
            denominatorValue += Math.abs(outOfBoundaryValue);
        }
        var positionRatio = 0;
        if(denominatorValue !== 0)
        {
            positionRatio = innerContainerPosition / denominatorValue;
            positionRatio = Math.max(positionRatio, 0);
            positionRatio = Math.min(positionRatio, 1);
        }
        var position = (scrollViewMeasure - length - 2 * this._marginForLength) * positionRatio + this._marginForLength;
        if(this._direction === ccui.ScrollView.DIR_VERTICAL)
        {
            return cc.p(this._parentScroll.width - this._marginFromBoundary, position);
        }
        else
        {
            return cc.p(position, this._marginFromBoundary);
        }
    }
});
var _p = ccui.ScrollViewBar.prototype;
_p.opacity;
cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
_p.autoHideEnabled;
cc.defineGetterSetter(_p, "autoHideEnabled", _p.isAutoHideEnabled, _p.setAutoHideEnabled);
ccui.ScrollViewBar.DEFAULT_COLOR = cc.color(52, 65, 87);
ccui.ScrollViewBar.DEFAULT_MARGIN = 20;
ccui.ScrollViewBar.DEFAULT_AUTO_HIDE_TIME = 0.2;
ccui.ScrollViewBar.DEFAULT_SCROLLBAR_OPACITY = 0.4;
ccui.ScrollViewBar.HALF_CIRCLE_IMAGE_KEY = "/__half_circle_image";
ccui.ScrollViewBar.HALF_CIRCLE_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAGCAMAAADAMI+zAAAAJ1BMVEX///////////////////////////////////////////////////9Ruv0SAAAADHRSTlMABgcbbW7Hz9Dz+PmlcJP5AAAAMElEQVR4AUXHwQ2AQAhFwYcLH1H6r1djzDK3ASxUpTBeK/uTCyz7dx54b44m4p5cD1MwAooEJyk3AAAAAElFTkSuQmCC";
ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT_KEY = "/__body_image_height";
ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAABCAMAAADdNb8LAAAAA1BMVEX///+nxBvIAAAACklEQVR4AWNABgAADQABYc2cpAAAAABJRU5ErkJggg==";
ccui.ScrollView = ccui.Layout.extend({
    _innerContainer: null,
    _direction: null,
    _topBoundary: 0,
    _bottomBoundary: 0,
    _leftBoundary: 0,
    _rightBoundary: 0,
    _touchMoveDisplacements: null,
    _touchMoveTimeDeltas: null,
    _touchMovePreviousTimestamp: 0,
    _touchTotalTimeThreshold : 0.5,
    _autoScrolling: false,
    _autoScrollTargetDelta: null,
    _autoScrollAttenuate: true,
    _autoScrollStartPosition : null,
    _autoScrollTotalTime: 0,
    _autoScrollAccumulatedTime: 0,
    _autoScrollCurrentlyOutOfBoundary: false,
    _autoScrollBraking: false,
    _autoScrollBrakingStartPosition: null,
    _bePressed: false,
    _childFocusCancelOffset: 0,
    bounceEnabled: false,
    _outOfBoundaryAmount: null,
    _outOfBoundaryAmountDirty: true,
    inertiaScrollEnabled: false,
    _scrollBarEnabled: true,
    _verticalScrollBar: null,
    _horizontalScrollBar: null,
    _scrollViewEventListener: null,
    _scrollViewEventSelector: null,
    _className: "ScrollView",
    ctor: function () {
        ccui.Layout.prototype.ctor.call(this);
        this.setClippingEnabled(true);
        this._innerContainer.setTouchEnabled(false);
        this._direction = ccui.ScrollView.DIR_NONE;
        this._childFocusCancelOffset = 5;
        this.inertiaScrollEnabled = true;
        this._outOfBoundaryAmount = cc.p(0, 0);
        this._autoScrollTargetDelta = cc.p(0, 0);
        this._autoScrollStartPosition = cc.p(0, 0);
        this._autoScrollBrakingStartPosition = cc.p(0, 0);
        this._touchMoveDisplacements = [];
        this._touchMoveTimeDeltas = [];
        this._touchMovePreviousTimestamp = 0;
        this._scrollBarEnabled = true;
        this._initScrollBar();
        this.setTouchEnabled(true);
    },
    init: function () {
        if (ccui.Layout.prototype.init.call(this)) {
            return true;
        }
        return false;
    },
    onEnter: function () {
        ccui.Layout.prototype.onEnter.call(this);
        this.scheduleUpdate();
    },
    onExit: function () {
        cc.renderer._removeCache(this.__instanceId);
        ccui.Layout.prototype.onExit.call(this);
    },
    findNextFocusedWidget: function(direction, current){
        if (this.getLayoutType() === ccui.Layout.LINEAR_VERTICAL
            || this.getLayoutType() === ccui.Layout.LINEAR_HORIZONTAL) {
            return this._innerContainer.findNextFocusedWidget(direction, current);
        } else
            return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, current);
    },
    _initRenderer: function () {
        ccui.Layout.prototype._initRenderer.call(this);
        this._innerContainer = new ccui.Layout();
        this._innerContainer.setColor(cc.color(255,255,255));
        this._innerContainer.setOpacity(255);
        this._innerContainer.setCascadeColorEnabled(true);
        this._innerContainer.setCascadeOpacityEnabled(true);
        this.addProtectedChild(this._innerContainer, 1, 1);
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            return new ccui.ScrollView.WebGLRenderCmd(this);
        else
            return new ccui.ScrollView.CanvasRenderCmd(this);
    },
    _onSizeChanged: function () {
        ccui.Layout.prototype._onSizeChanged.call(this);
        var locSize = this._contentSize;
        this._topBoundary = locSize.height;
        this._rightBoundary = locSize.width;
        var innerSize = this._innerContainer.getContentSize();
        this._innerContainer.setContentSize(cc.size(Math.max(innerSize.width, locSize.width), Math.max(innerSize.height, locSize.height)));
        this._innerContainer.setPosition(0, locSize.height - this._innerContainer.getContentSize().height);
        if(this._verticalScrollBar)
            this._verticalScrollBar.onScrolled(this._getHowMuchOutOfBoundary());
        if(this._horizontalScrollBar)
            this._horizontalScrollBar.onScrolled(this._getHowMuchOutOfBoundary());
    },
    setInnerContainerSize: function (size) {
        var innerContainer = this._innerContainer,
            locSize = this._contentSize,
            innerSizeWidth = locSize.width, innerSizeHeight = locSize.height;
        if (size.width < locSize.width)
            cc.log("Inner width <= ScrollView width, it will be force sized!");
        else
            innerSizeWidth = size.width;
        if (size.height < locSize.height)
            cc.log("Inner height <= ScrollView height, it will be force sized!");
        else
            innerSizeHeight = size.height;
        innerContainer.setContentSize(cc.size(innerSizeWidth, innerSizeHeight));
        var pos = this._innerContainer.getPosition();
        var contAP = this._innerContainer.getAnchorPoint();
        if (this._innerContainer.getLeftBoundary() != 0.0)
        {
            pos.x = contAP.x * innerSizeWidth;
        }
        if (this._innerContainer.getTopBoundary() != this._contentSize.height)
        {
            pos.y = this._contentSize.height - (1.0 - contAP.y) * innerSizeHeight;
        }
        this.setInnerContainerPosition(pos);
        this._updateScrollBar(cc.p(0 ,0));
    },
    _setInnerWidth: function (width) {
        var locW = this._contentSize.width,
            innerWidth = locW,
            container = this._innerContainer,
            oldInnerWidth = container.width;
        if (width < locW)
            cc.log("Inner width <= scrollview width, it will be force sized!");
        else
            innerWidth = width;
        container.width = innerWidth;
        switch (this._direction) {
            case ccui.ScrollView.DIR_HORIZONTAL:
            case ccui.ScrollView.DIR_BOTH:
                if (container.getRightBoundary() <= locW) {
                    var newInnerWidth = container.width;
                    var offset = oldInnerWidth - newInnerWidth;
                    this._scrollChildren(offset, 0);
                }
                break;
        }
        var innerAX = container.anchorX;
        if (container.getLeftBoundary() > 0.0)
            container.x = innerAX * innerWidth;
        if (container.getRightBoundary() < locW)
            container.x = locW - ((1.0 - innerAX) * innerWidth);
    },
    _setInnerHeight: function (height) {
        var locH = this._contentSize.height,
            innerHeight = locH,
            container = this._innerContainer,
            oldInnerHeight = container.height;
        if (height < locH)
            cc.log("Inner height <= scrollview height, it will be force sized!");
        else
            innerHeight = height;
        container.height = innerHeight;
        switch (this._direction) {
            case ccui.ScrollView.DIR_VERTICAL:
            case ccui.ScrollView.DIR_BOTH:
                var newInnerHeight = innerHeight;
                var offset = oldInnerHeight - newInnerHeight;
                this._scrollChildren(0, offset);
                break;
        }
        var innerAY = container.anchorY;
        if (container.getLeftBoundary() > 0.0)
            container.y = innerAY * innerHeight;
        if (container.getRightBoundary() < locH)
            container.y = locH - ((1.0 - innerAY) * innerHeight);
    },
    setInnerContainerPosition: function(position)
    {
        if(position.x === this._innerContainer.getPositionX() && position.y === this._innerContainer.getPositionY())
        {
            return;
        }
        this._innerContainer.setPosition(position);
        this._outOfBoundaryAmountDirty = true;
        if(this.bounceEnabled)
        {
            for(var _direction = ccui.ScrollView.MOVEDIR_TOP; _direction < ccui.ScrollView.MOVEDIR_RIGHT; ++_direction)
            {
                if(this._isOutOfBoundary(_direction))
                {
                   this._processScrollEvent(_direction, true);
                }
            }
        }
        this._dispatchEvent(ccui.ScrollView.EVENT_CONTAINER_MOVED);
    },
    getInnerContainerPosition: function()
    {
        return this._innerContainer.getPosition();
    },
    getInnerContainerSize: function () {
        return this._innerContainer.getContentSize();
    },
    _getInnerWidth: function () {
        return this._innerContainer.width;
    },
    _getInnerHeight: function () {
        return this._innerContainer.height;
    },
    _isInContainer: function (widget) {
       if(!this._clippingEnabled)
            return true;
        var wPos = widget._position,
            wSize = widget._contentSize,
            wAnchor = widget._anchorPoint,
            size = this._customSize,
            pos = this._innerContainer._position,
            bottom = 0, left = 0;
        if (
        (bottom = wPos.y - wAnchor.y * wSize.height) >= size.height - pos.y ||
        bottom + wSize.height <= -pos.y ||
        (left = wPos.x - wAnchor.x * wSize.width) >= size.width - pos.x ||
        left + wSize.width <= -pos.x
        )
            return false;
        else return true;
    },
    updateChildren: function () {
        var child, i, l;
        var childrenArray = this._innerContainer._children;
        for(i = 0, l = childrenArray.length; i < l; i++) {
            child = childrenArray[i];
            if(child._inViewRect === true && this._isInContainer(child) === false)
                child._inViewRect = false;
            else if (child._inViewRect === false && this._isInContainer(child) === true)
                child._inViewRect = true;
        }
    },
    addChild: function (widget, zOrder, tag) {
        if(!widget)
            return false;
        if(this._isInContainer(widget) === false)
            widget._inViewRect = false;
        zOrder = zOrder || widget.getLocalZOrder();
        tag = tag || widget.getTag();
        return this._innerContainer.addChild(widget, zOrder, tag);
    },
    removeAllChildren: function () {
        this.removeAllChildrenWithCleanup(true);
    },
    removeAllChildrenWithCleanup: function(cleanup){
        this._innerContainer.removeAllChildrenWithCleanup(cleanup);
    },
    removeChild: function (child, cleanup) {
        return this._innerContainer.removeChild(child, cleanup);
    },
    getChildren: function () {
        return this._innerContainer.getChildren();
    },
    getChildrenCount: function () {
        return this._innerContainer.getChildrenCount();
    },
    getChildByTag: function (tag) {
        return this._innerContainer.getChildByTag(tag);
    },
    getChildByName: function (name) {
        return this._innerContainer.getChildByName(name);
    },
    _flattenVectorByDirection: function(vector)
    {
        var result = cc.p(0 ,0);
        result.x = (this._direction === ccui.ScrollView.DIR_VERTICAL ? 0 : vector.x);
        result.y = (this._direction === ccui.ScrollView.DIR_HORIZONTAL ? 0 : vector.y);
        return result;
    },
    _getHowMuchOutOfBoundary: function(addition)
    {
        if(addition === undefined)
            addition = cc.p(0, 0);
        if(addition.x === 0 && addition.y === 0 && !this._outOfBoundaryAmountDirty)
        {
            return this._outOfBoundaryAmount;
        }
        var outOfBoundaryAmount = cc.p(0, 0);
        if(this._innerContainer.getLeftBoundary() + addition.x > this._leftBoundary)
        {
            outOfBoundaryAmount.x = this._leftBoundary - (this._innerContainer.getLeftBoundary() + addition.x);
        }
        else if(this._innerContainer.getRightBoundary() + addition.x < this._rightBoundary)
        {
            outOfBoundaryAmount.x = this._rightBoundary - (this._innerContainer.getRightBoundary() + addition.x);
        }
        if(this._innerContainer.getTopBoundary() + addition.y < this._topBoundary)
        {
            outOfBoundaryAmount.y = this._topBoundary - (this._innerContainer.getTopBoundary() + addition.y);
        }
        else if(this._innerContainer.getBottomBoundary() + addition.y > this._bottomBoundary)
        {
            outOfBoundaryAmount.y = this._bottomBoundary - (this._innerContainer.getBottomBoundary() + addition.y);
        }
        if(addition.x === 0 && addition.y === 0 )
        {
            this._outOfBoundaryAmount = outOfBoundaryAmount;
            this._outOfBoundaryAmountDirty = false;
        }
        return outOfBoundaryAmount;
    },
    _isOutOfBoundary: function(dir)
    {
        var outOfBoundary = this._getHowMuchOutOfBoundary();
        if(dir !== undefined)
        {
            switch (dir)
            {
                case ccui.ScrollView.MOVEDIR_TOP:
                    return outOfBoundary.y > 0;
                case ccui.ScrollView.MOVEDIR_BOTTOM:
                    return outOfBoundary.y < 0;
                case ccui.ScrollView.MOVEDIR_LEFT:
                    return outOfBoundary.x < 0;
                case ccui.ScrollView.MOVEDIR_RIGHT:
                    return outOfBoundary.x > 0;
            }
        }
        else
        {
            return !this._fltEqualZero(outOfBoundary);
        }
        return false;
    },
    _moveInnerContainer: function(deltaMove, canStartBounceBack)
    {
        var adjustedMove = this._flattenVectorByDirection(deltaMove);
        this.setInnerContainerPosition(cc.pAdd(this.getInnerContainerPosition(), adjustedMove));
        var outOfBoundary =this._getHowMuchOutOfBoundary();
        this._updateScrollBar(outOfBoundary);
        if(this.bounceEnabled && canStartBounceBack)
        {
            this._startBounceBackIfNeeded();
        }
    },
    _updateScrollBar: function(outOfBoundary)
    {
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.onScrolled(outOfBoundary);
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.onScrolled(outOfBoundary);
        }
    },
    _calculateTouchMoveVelocity: function()
    {
        var totalTime = 0;
        for(var i = 0; i < this._touchMoveTimeDeltas.length; ++i)
        {
            totalTime += this._touchMoveTimeDeltas[i];
        }
        if(totalTime == 0 || totalTime >= this._touchTotalTimeThreshold)
        {
            return cc.p(0, 0);
        }
        var totalMovement = cc.p(0 ,0);
        for(var i = 0; i < this._touchMoveDisplacements.length; ++i)
        {
            totalMovement.x += this._touchMoveDisplacements[i].x;
            totalMovement.y += this._touchMoveDisplacements[i].y;
        }
        return cc.pMult(totalMovement, 1 / totalTime);
    },
    setTouchTotalTimeThreshold: function(touchTotalTimeThreshold)
    {
        this._touchTotalTimeThreshold = touchTotalTimeThreshold;
    },
    getTouchTotalTimeThreshold: function()
    {
        return this._touchTotalTimeThreshold;
    },
    _startInertiaScroll: function(touchMoveVelocity)
    {
        var MOVEMENT_FACTOR = 0.7;
        var inertiaTotalMovement = cc.pMult(touchMoveVelocity, MOVEMENT_FACTOR);
        this._startAttenuatingAutoScroll(inertiaTotalMovement, touchMoveVelocity);
    },
    _startBounceBackIfNeeded: function()
    {
        if (!this.bounceEnabled)
        {
            return false;
        }
        var bounceBackAmount = this._getHowMuchOutOfBoundary();
        if(this._fltEqualZero(bounceBackAmount))
        {
            return false;
        }
        var BOUNCE_BACK_DURATION = 1.0;
        this._startAutoScroll(bounceBackAmount, BOUNCE_BACK_DURATION, true);
        return true;
    },
    _startAutoScrollToDestination: function(destination, timeInSec, attenuated)
    {
        this._startAutoScroll(cc.pSub(destination , this._innerContainer.getPosition()), timeInSec, attenuated);
    },
    _calculateAutoScrollTimeByInitialSpeed: function(initialSpeed)
    {
        return Math.sqrt(Math.sqrt(initialSpeed / 5));
    },
    _startAttenuatingAutoScroll: function(deltaMove, initialVelocity)
    {
        var  time = this._calculateAutoScrollTimeByInitialSpeed(cc.pLength(initialVelocity));
        this._startAutoScroll(deltaMove, time, true);
    },
    _startAutoScroll: function(deltaMove, timeInSec, attenuated)
    {
        var adjustedDeltaMove = this._flattenVectorByDirection(deltaMove);
        this._autoScrolling = true;
        this._autoScrollTargetDelta = adjustedDeltaMove;
        this._autoScrollAttenuate = attenuated;
        this._autoScrollStartPosition = this._innerContainer.getPosition();
        this._autoScrollTotalTime = timeInSec;
        this._autoScrollAccumulatedTime = 0;
        this._autoScrollBraking = false;
        this._autoScrollBrakingStartPosition = cc.p(0,0 );
        var currentOutOfBoundary = this._getHowMuchOutOfBoundary();
        if(!this._fltEqualZero(currentOutOfBoundary))
        {
            this._autoScrollCurrentlyOutOfBoundary = true;
            var afterOutOfBoundary = this._getHowMuchOutOfBoundary(adjustedDeltaMove);
            if(currentOutOfBoundary.x * afterOutOfBoundary.x > 0 || currentOutOfBoundary.y * afterOutOfBoundary.y > 0)
            {
                this._autoScrollBraking = true;
            }
        }
    },
    stopAutoScroll: function()
    {
        this._autoScrolling = false;
        this._autoScrollAttenuate = true;
        this._autoScrollTotalTime = 0;
        this._autoScrollAccumulatedTime = 0;
    },
    _isNecessaryAutoScrollBrake: function()
    {
        if(this._autoScrollBraking)
        {
            return true;
        }
        if(this._isOutOfBoundary())
        {
            if(!this._autoScrollCurrentlyOutOfBoundary)
            {
                this._autoScrollCurrentlyOutOfBoundary = true;
                this._autoScrollBraking = true;
                this._autoScrollBrakingStartPosition = this.getInnerContainerPosition();
                return true;
            }
        }
        else
        {
            this._autoScrollCurrentlyOutOfBoundary = false;
        }
        return false;
    },
    _getAutoScrollStopEpsilon: function()
    {
        return 0.0001;
    },
    _fltEqualZero: function(point)
    {
        return (Math.abs(point.x) <=  0.0001 && Math.abs(point.y) <=  0.0001);
    },
    _processAutoScrolling: function(deltaTime)
    {
        var OUT_OF_BOUNDARY_BREAKING_FACTOR = 0.05;
        var brakingFactor = (this._isNecessaryAutoScrollBrake() ? OUT_OF_BOUNDARY_BREAKING_FACTOR : 1);
        this._autoScrollAccumulatedTime += deltaTime * (1 / brakingFactor);
        var percentage = Math.min(1, this._autoScrollAccumulatedTime / this._autoScrollTotalTime);
        if(this._autoScrollAttenuate)
        {
            percentage -= 1;
            percentage = percentage * percentage * percentage * percentage * percentage + 1;
        }
        var newPosition = cc.pAdd(this._autoScrollStartPosition, cc.pMult(this._autoScrollTargetDelta,percentage));
        var reachedEnd = Math.abs(percentage - 1) <= this._getAutoScrollStopEpsilon();
        if(this.bounceEnabled)
        {
            newPosition = cc.pAdd(this._autoScrollBrakingStartPosition, cc.pMult(cc.pSub(newPosition, this._autoScrollBrakingStartPosition), brakingFactor));
        }
        else
        {
            var moveDelta = cc.pSub(newPosition, this.getInnerContainerPosition());
            var outOfBoundary = this._getHowMuchOutOfBoundary(moveDelta);
            if(!this._fltEqualZero(outOfBoundary))
            {
                newPosition.x += outOfBoundary.x;
                newPosition.y += outOfBoundary.y;
                reachedEnd = true;
            }
        }
        if(reachedEnd)
        {
            this._autoScrolling = false;
            this._dispatchEvent(ccui.ScrollView.EVENT_AUTOSCROLL_ENDED);
        }
        this._moveInnerContainer(cc.pSub(newPosition, this.getInnerContainerPosition()), reachedEnd);
    },
    _jumpToDestination: function (desOrX, y)
    {
        if(desOrX.x === undefined)
        {
            desOrX = cc.p(desOrX, y);
        }
        this._autoScrolling = false;
        this._moveInnerContainer(cc.pSub(desOrX, this.getInnerContainerPosition()), true);
    },
    _scrollChildren: function(deltaMove)
    {
        var realMove = deltaMove;
        if(this.bounceEnabled)
        {
            var outOfBoundary = this._getHowMuchOutOfBoundary();
            realMove.x *= (outOfBoundary.x == 0 ? 1 : 0.5);
            realMove.y *= (outOfBoundary.y == 0 ? 1 : 0.5);
        }
        if(!this.bounceEnabled)
        {
            var outOfBoundary = this._getHowMuchOutOfBoundary(realMove);
            realMove.x += outOfBoundary.x;
            realMove.y += outOfBoundary.y;
        }
        var scrolledToLeft = false;
        var scrolledToRight = false;
        var scrolledToTop = false;
        var scrolledToBottom = false;
        if (realMove.y > 0.0)
        {
            var icBottomPos = this._innerContainer.getBottomBoundary();
            if (icBottomPos + realMove.y >= this._bottomBoundary)
            {
                scrolledToBottom = true;
            }
        }
        else if (realMove.y < 0.0)
        {
            var icTopPos = this._innerContainer.getTopBoundary();
            if (icTopPos + realMove.y <= this._topBoundary)
            {
                scrolledToTop = true;
            }
        }
        if (realMove.x < 0.0)
        {
            var icRightPos = this._innerContainer.getRightBoundary();
            if (icRightPos + realMove.x <= this._rightBoundary)
            {
                scrolledToRight = true;
            }
        }
        else if (realMove.x > 0.0)
        {
            var icLeftPos = this._innerContainer.getLeftBoundary();
            if (icLeftPos + realMove.x >= this._leftBoundary)
            {
                scrolledToLeft = true;
            }
        }
        this._moveInnerContainer(realMove, false);
        if(realMove.x != 0 || realMove.y != 0)
        {
            this._processScrollingEvent();
        }
        if(scrolledToBottom)
        {
            this._processScrollEvent(ccui.ScrollView.MOVEDIR_BOTTOM, false);
        }
        if(scrolledToTop)
        {
            this._processScrollEvent(ccui.ScrollView.MOVEDIR_TOP, false);
        }
        if(scrolledToLeft)
        {
            this._processScrollEvent(ccui.ScrollView.MOVEDIR_LEFT, false);
        }
        if(scrolledToRight)
        {
            this._processScrollEvent(ccui.ScrollView.MOVEDIR_RIGHT, false);
        }
    },
    scrollToBottom: function (time, attenuated) {
        this._startAutoScrollToDestination(cc.p(this._innerContainer.getPositionX(), 0), time, attenuated);
    },
    scrollToTop: function (time, attenuated) {
        this._startAutoScrollToDestination(
            cc.p(this._innerContainer.getPositionX(), this._contentSize.height - this._innerContainer.getContentSize().height), time, attenuated);
    },
    scrollToLeft: function (time, attenuated) {
        this._startAutoScrollToDestination(cc.p(0, this._innerContainer.getPositionY()), time, attenuated);
    },
    scrollToRight: function (time, attenuated) {
        this._startAutoScrollToDestination(
            cc.p(this._contentSize.width - this._innerContainer.getContentSize().width, this._innerContainer.getPositionY()), time, attenuated);
    },
    scrollToTopLeft: function (time, attenuated) {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll direction is not both!");
            return;
        }
        this._startAutoScrollToDestination(cc.p(0, this._contentSize.height - this._innerContainer.getContentSize().height), time, attenuated);
    },
    scrollToTopRight: function (time, attenuated) {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll direction is not both!");
            return;
        }
        var inSize = this._innerContainer.getContentSize();
        this._startAutoScrollToDestination(cc.p(this._contentSize.width - inSize.width,
                this._contentSize.height - inSize.height), time, attenuated);
    },
    scrollToBottomLeft: function (time, attenuated) {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll direction is not both!");
            return;
        }
        this._startAutoScrollToDestination(cc.p(0, 0), time, attenuated);
    },
    scrollToBottomRight: function (time, attenuated) {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll direction is not both!");
            return;
        }
        this._startAutoScrollToDestination(cc.p(this._contentSize.width - this._innerContainer.getContentSize().width, 0), time, attenuated);
    },
    scrollToPercentVertical: function (percent, time, attenuated) {
        var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
        var h = -minY;
        this._startAutoScrollToDestination(cc.p(this._innerContainer.getPositionX(), minY + percent * h / 100), time, attenuated);
    },
    scrollToPercentHorizontal: function (percent, time, attenuated) {
        var w = this._innerContainer.getContentSize().width - this._contentSize.width;
        this._startAutoScrollToDestination(cc.p(-(percent * w / 100), this._innerContainer.getPositionY()), time, attenuated);
    },
    scrollToPercentBothDirection: function (percent, time, attenuated) {
        if (this._direction !== ccui.ScrollView.DIR_BOTH)
            return;
        var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
        var h = -minY;
        var w = this._innerContainer.getContentSize().width - this._contentSize.width;
        this._startAutoScrollToDestination(cc.p(-(percent.x * w / 100), minY + percent.y * h / 100), time, attenuated);
    },
    jumpToBottom: function () {
        this._jumpToDestination(this._innerContainer.getPositionX(), 0);
    },
    jumpToTop: function () {
        this._jumpToDestination(this._innerContainer.getPositionX(), this._contentSize.height - this._innerContainer.getContentSize().height);
    },
    jumpToLeft: function () {
        this._jumpToDestination(0, this._innerContainer.getPositionY());
    },
    jumpToRight: function () {
        this._jumpToDestination(this._contentSize.width - this._innerContainer.getContentSize().width, this._innerContainer.getPositionY());
    },
    jumpToTopLeft: function () {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll _direction is not both!");
            return;
        }
        this._jumpToDestination(0, this._contentSize.height - this._innerContainer.getContentSize().height);
    },
    jumpToTopRight: function () {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll _direction is not both!");
            return;
        }
        var inSize = this._innerContainer.getContentSize();
        this._jumpToDestination(this._contentSize.width - inSize.width, this._contentSize.height - inSize.height);
    },
    jumpToBottomLeft: function () {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll _direction is not both!");
            return;
        }
        this._jumpToDestination(0, 0);
    },
    jumpToBottomRight: function () {
        if (this._direction !== ccui.ScrollView.DIR_BOTH) {
            cc.log("Scroll _direction is not both!");
            return;
        }
        this._jumpToDestination(this._contentSize.width - this._innerContainer.getContentSize().width, 0);
    },
    jumpToPercentVertical: function (percent) {
        var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
        var h = -minY;
        this._jumpToDestination(this._innerContainer.getPositionX(), minY + percent * h / 100);
    },
    jumpToPercentHorizontal: function (percent) {
        var w = this._innerContainer.getContentSize().width - this._contentSize.width;
        this._jumpToDestination(-(percent * w / 100), this._innerContainer.getPositionY());
    },
    jumpToPercentBothDirection: function (percent) {
        if (this._direction !== ccui.ScrollView.DIR_BOTH)
            return;
        var inSize = this._innerContainer.getContentSize();
        var minY = this._contentSize.height - inSize.height;
        var h = -minY;
        var w = inSize.width - this._contentSize.width;
        this._jumpToDestination(-(percent.x * w / 100), minY + percent.y * h / 100);
    },
    _gatherTouchMove: function(delta)
    {
        var NUMBER_OF_GATHERED_TOUCHES_FOR_MOVE_SPEED = 5;
        while(this._touchMoveDisplacements.length  >= NUMBER_OF_GATHERED_TOUCHES_FOR_MOVE_SPEED)
        {
            this._touchMoveDisplacements.splice(0,1);
            this._touchMoveTimeDeltas.splice(0,1)
        }
        this._touchMoveDisplacements.push(delta);
        var timestamp = (new Date()).getTime();
        this._touchMoveTimeDeltas.push((timestamp - this._touchMovePreviousTimestamp) / 1000);
        this._touchMovePreviousTimestamp = timestamp;
    },
    _handlePressLogic: function (touch) {
        this._bePressed = true;
        this._autoScrolling = false;
        this._touchMovePreviousTimestamp = (new Date()).getTime();
        this._touchMoveDisplacements.length = 0;
        this._touchMoveTimeDeltas.length = 0;
        if(this._verticalScrollBar)
        {
           this._verticalScrollBar.onTouchBegan();
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.onTouchBegan();
        }
    },
    _handleMoveLogic: function (touch) {
        var touchPositionInNodeSpace = this.convertToNodeSpace(touch.getLocation()),
            previousTouchPositionInNodeSpace = this.convertToNodeSpace(touch.getPreviousLocation());
        var delta = cc.pSub(touchPositionInNodeSpace, previousTouchPositionInNodeSpace);
        this._scrollChildren(delta);
        this._gatherTouchMove(delta);
    },
    _handleReleaseLogic: function (touch) {
        var touchPositionInNodeSpace = this.convertToNodeSpace(touch.getLocation()),
            previousTouchPositionInNodeSpace = this.convertToNodeSpace(touch.getPreviousLocation());
        var delta = cc.pSub(touchPositionInNodeSpace, previousTouchPositionInNodeSpace);
        this._gatherTouchMove(delta);
        this._bePressed = false;
        var bounceBackStarted = this._startBounceBackIfNeeded();
        if(!bounceBackStarted && this.inertiaScrollEnabled)
        {
            var touchMoveVelocity = this._calculateTouchMoveVelocity();
            if(touchMoveVelocity.x !== 0 || touchMoveVelocity.y !== 0)
            {
                this._startInertiaScroll(touchMoveVelocity);
            }
        }
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.onTouchEnded();
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.onTouchEnded();
        }
    },
    onTouchBegan: function (touch, event) {
        var pass = ccui.Layout.prototype.onTouchBegan.call(this, touch, event);
        if(!this._isInterceptTouch){
            if (this._hit)
                this._handlePressLogic(touch);
        }
        return pass;
    },
    onTouchMoved: function (touch, event) {
        ccui.Layout.prototype.onTouchMoved.call(this, touch, event);
        if(!this._isInterceptTouch)
            this._handleMoveLogic(touch);
    },
    onTouchEnded: function (touch, event) {
        ccui.Layout.prototype.onTouchEnded.call(this, touch, event);
        if(!this._isInterceptTouch)
            this._handleReleaseLogic(touch);
        this._isInterceptTouch = false;
    },
    onTouchCancelled: function (touch, event) {
        ccui.Layout.prototype.onTouchCancelled.call(this, touch, event);
        if (!this._isInterceptTouch)
            this._handleReleaseLogic(touch);
        this._isInterceptTouch = false;
    },
    update: function (dt) {
        if (this._autoScrolling)
            this._processAutoScrolling(dt);
    },
    interceptTouchEvent: function (event, sender, touch) {
        if (!this._touchEnabled) {
            ccui.Layout.prototype.interceptTouchEvent.call(this, event, sender, touch);
            return;
        }
        if(this._direction === ccui.ScrollView.DIR_NONE)
            return;
        var touchPoint = touch.getLocation();
        switch (event) {
            case ccui.Widget.TOUCH_BEGAN:
                this._isInterceptTouch = true;
                this._touchBeganPosition.x = touchPoint.x;
                this._touchBeganPosition.y = touchPoint.y;
                this._handlePressLogic(touch);
                break;
            case ccui.Widget.TOUCH_MOVED:
                var offset = cc.pLength(cc.pSub(sender.getTouchBeganPosition(), touchPoint));
                this._touchMovePosition.x = touchPoint.x;
                this._touchMovePosition.y = touchPoint.y;
                if (offset > this._childFocusCancelOffset) {
                    sender.setHighlighted(false);
                    this._handleMoveLogic(touch);
                }
                break;
            case ccui.Widget.TOUCH_CANCELED:
            case ccui.Widget.TOUCH_ENDED:
                this._touchEndPosition.x = touchPoint.x;
                this._touchEndPosition.y = touchPoint.y;
                this._handleReleaseLogic(touch);
                if (sender.isSwallowTouches())
                    this._isInterceptTouch = false;
                break;
        }
    },
    _processScrollEvent: function(_directionEvent, bounce)
    {
        var event = 0;
        switch(_directionEvent)
        {
            case ccui.ScrollView.MOVEDIR_TOP:
                event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_TOP : ccui.ScrollView.EVENT_SCROLL_TO_TOP);
                break;
            case ccui.ScrollView.MOVEDIR_BOTTOM:
                event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_BOTTOM : ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM);
                break;
            case ccui.ScrollView.MOVEDIR_LEFT:
                event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_LEFT : ccui.ScrollView.EVENT_SCROLL_TO_LEFT);
                break;
            case ccui.ScrollView.MOVEDIR_RIGHT:
                event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_RIGHT : ccui.ScrollView.EVENT_SCROLL_TO_RIGHT);
                break;
        }
        this._dispatchEvent(event);
    },
    _processScrollingEvent: function()
    {
        this._dispatchEvent( ccui.ScrollView.EVENT_SCROLLING);
    },
    _dispatchEvent: function(event)
    {
        if(this._scrollViewEventSelector){
            if (this._scrollViewEventListener)
                this._scrollViewEventSelector.call(this._scrollViewEventListener, this, event);
            else
                this._scrollViewEventSelector(this, event);
        }
        if(this._ccEventCallback)
            this._ccEventCallback(this, event);
    },
    addEventListenerScrollView: function (selector, target) {
        this._scrollViewEventSelector = selector;
        this._scrollViewEventListener = target;
    },
    addEventListener: function(selector){
        this._ccEventCallback = selector;
    },
    setDirection: function (dir) {
        this._direction = dir;
        if(this._scrollBarEnabled)
        {
            this._removeScrollBar();
            this._initScrollBar();
        }
    },
    getDirection: function () {
        return this._direction;
    },
    setBounceEnabled: function (enabled) {
        this.bounceEnabled = enabled;
    },
    isBounceEnabled: function () {
        return this.bounceEnabled;
    },
    setInertiaScrollEnabled: function (enabled) {
        this.inertiaScrollEnabled = enabled;
    },
    isInertiaScrollEnabled: function () {
        return this.inertiaScrollEnabled;
    },
    setScrollBarEnabled: function(enabled)
    {
        if(this._scrollBarEnabled === enabled)
        {
            return;
        }
        if(this._scrollBarEnabled)
        {
            this._removeScrollBar();
        }
        this._scrollBarEnabled = enabled;
        if(this._scrollBarEnabled)
        {
            this._initScrollBar();
        }
    },
    isScrollBarEnabled: function()
    {
        return this._scrollBarEnabled;
    },
    setScrollBarPositionFromCorner: function(positionFromCorner)
    {
        if(this._direction !== ccui.ScrollView.DIR_HORIZONTAL)
        {
            this.setScrollBarPositionFromCornerForVertical(positionFromCorner);
        }
        if(this._direction !== ccui.ScrollView.DIR_VERTICAL)
        {
            this.setScrollBarPositionFromCornerForHorizontal(positionFromCorner);
        }
    },
    setScrollBarPositionFromCornerForVertical: function(positionFromCorner)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        cc.assert(this._direction !== ccui.ScrollView.DIR_HORIZONTAL, "Scroll view doesn't have a vertical scroll bar!");
        this._verticalScrollBar.setPositionFromCorner(positionFromCorner);
    },
    getScrollBarPositionFromCornerForVertical: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        cc.assert(this._direction !== ccui.ScrollView.DIR_HORIZONTAL, "Scroll view doesn't have a vertical scroll bar!");
        return this._verticalScrollBar.getPositionFromCorner();
    },
    setScrollBarPositionFromCornerForHorizontal: function(positionFromCorner)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        cc.assert(this._direction !== ccui.ScrollView.DIR_VERTICAL, "Scroll view doesn't have a horizontal scroll bar!");
        this._horizontalScrollBar.setPositionFromCorner(positionFromCorner);
    },
    getScrollBarPositionFromCornerForHorizontal: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        cc.assert(this._direction !== ccui.ScrollView.DIR_VERTICAL, "Scroll view doesn't have a horizontal scroll bar!");
        return this._horizontalScrollBar.getPositionFromCorner();
    },
    setScrollBarWidth: function(width)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.setWidth(width);
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.setWidth(width);
        }
    },
    getScrollBarWidth: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            return this._verticalScrollBar.getWidth();
        }
        if(this._horizontalScrollBar)
        {
            return this._horizontalScrollBar.getWidth();
        }
        return 0;
    },
    setScrollBarColor: function(color)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.setColor(color);
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.setColor(color);
        }
    },
    getScrollBarColor: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.getColor();
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.getColor();
        }
        return cc.color.WHITE;
    },
    setScrollBarOpacity: function(opacity)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.opacity = opacity;
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.opacity = opacity;
        }
    },
    getScrollBarOpacity: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            return this._verticalScrollBar.opacity;
        }
        if(this._horizontalScrollBar)
        {
            return this._horizontalScrollBar.opacity;
        }
        return -1;
    },
    setScrollBarAutoHideEnabled: function(autoHideEnabled)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.autoHideEnabled = autoHideEnabled;
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.autoHideEnabled = autoHideEnabled;
        }
    },
    isScrollBarAutoHideEnabled: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            return this._verticalScrollBar.autoHideEnabled;
        }
        if(this._horizontalScrollBar)
        {
            return this._horizontalScrollBar.autoHideEnabled;
        }
        return false;
    },
    setScrollBarAutoHideTime: function(autoHideTime)
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            this._verticalScrollBar.autoHideTime = autoHideTime;
        }
        if(this._horizontalScrollBar)
        {
            this._horizontalScrollBar.autoHideTime = autoHideTime;
        }
    },
    getScrollBarAutoHideTime: function()
    {
        cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
        if(this._verticalScrollBar)
        {
            return this._verticalScrollBar.autoHideTime;
        }
        if(this._horizontalScrollBar)
        {
            return this._horizontalScrollBar.autoHideTime;
        }
        return 0;
    },
    getInnerContainer: function () {
        return this._innerContainer;
    },
    setLayoutType: function (type) {
        this._innerContainer.setLayoutType(type);
    },
    getLayoutType: function () {
        return this._innerContainer.getLayoutType();
    },
    _doLayout: function () {
        if (!this._doLayoutDirty)
            return;
        this._doLayoutDirty = false;
    },
    getDescription: function () {
        return "ScrollView";
    },
    _createCloneInstance: function(){
        return new ccui.ScrollView();
    },
    _copyClonedWidgetChildren: function (model) {
        ccui.Layout.prototype._copyClonedWidgetChildren.call(this, model);
    },
    _copySpecialProperties: function (scrollView) {
        if(scrollView instanceof ccui.ScrollView) {
            ccui.Layout.prototype._copySpecialProperties.call(this, scrollView);
            this.setInnerContainerSize(scrollView.getInnerContainerSize());
            this.setInnerContainerPosition(scrollView.getInnerContainerPosition());
            this.setDirection(scrollView._direction);
            this._topBoundary = scrollView._topBoundary;
            this._bottomBoundary = scrollView._bottomBoundary;
            this._leftBoundary = scrollView._leftBoundary;
            this._rightBoundary = scrollView._rightBoundary;
            this._bePressed = scrollView._bePressed;
            this._childFocusCancelOffset = scrollView._childFocusCancelOffset;
            this._touchMoveDisplacements = scrollView._touchMoveDisplacements;
            this._touchMoveTimeDeltas = scrollView._touchMoveTimeDeltas;
            this._touchMovePreviousTimestamp = scrollView._touchMovePreviousTimestamp;
            this._autoScrolling = scrollView._autoScrolling;
            this._autoScrollAttenuate = scrollView._autoScrollAttenuate;
            this._autoScrollStartPosition = scrollView._autoScrollStartPosition;
            this._autoScrollTargetDelta = scrollView._autoScrollTargetDelta;
            this._autoScrollTotalTime = scrollView._autoScrollTotalTime;
            this._autoScrollAccumulatedTime = scrollView._autoScrollAccumulatedTime;
            this._autoScrollCurrentlyOutOfBoundary = scrollView._autoScrollCurrentlyOutOfBoundary;
            this._autoScrollBraking = scrollView._autoScrollBraking;
            this._autoScrollBrakingStartPosition = scrollView._autoScrollBrakingStartPosition;
            this.setBounceEnabled(scrollView.bounceEnabled);
            this.setInertiaScrollEnabled(scrollView.inertiaScrollEnabled);
            this._scrollViewEventListener = scrollView._scrollViewEventListener;
            this._scrollViewEventSelector = scrollView._scrollViewEventSelector;
            this._ccEventCallback = scrollView._ccEventCallback;
            this.setScrollBarEnabled(scrollView.isScrollBarEnabled());
            if(this.isScrollBarEnabled())
            {
                if(this._direction !== ccui.ScrollView.DIR_HORIZONTAL)
                {
                    this.setScrollBarPositionFromCornerForVertical(scrollView.getScrollBarPositionFromCornerForVertical());
                }
                if(this._direction !== ccui.ScrollView.DIR_VERTICAL)
                {
                    this.setScrollBarPositionFromCornerForHorizontal(scrollView.getScrollBarPositionFromCornerForHorizontal());
                }
                this.setScrollBarWidth(scrollView.getScrollBarWidth());
                this.setScrollBarColor(scrollView.getScrollBarColor());
                this.setScrollBarAutoHideEnabled(scrollView.isScrollBarAutoHideEnabled());
                this.setScrollBarAutoHideTime(scrollView.getScrollBarAutoHideTime());
            }
        }
    },
    _initScrollBar: function()
    {
        if(this._direction !== ccui.ScrollView.DIR_HORIZONTAL && !this._verticalScrollBar)
        {
            this._verticalScrollBar = new ccui.ScrollViewBar(this, ccui.ScrollView.DIR_VERTICAL);
            this.addProtectedChild(this._verticalScrollBar, 2);
        }
        if(this._direction !== ccui.ScrollView.DIR_VERTICAL && !this._horizontalScrollBar)
        {
            this._horizontalScrollBar = new ccui.ScrollViewBar(this, ccui.ScrollView.DIR_HORIZONTAL);
            this.addProtectedChild(this._horizontalScrollBar, 2);
        }
    },
    _removeScrollBar: function()
    {
        if(this._verticalScrollBar)
        {
            this.removeProtectedChild(this._verticalScrollBar);
            this._verticalScrollBar = null;
        }
        if(this._horizontalScrollBar)
        {
            this.removeProtectedChild(this._horizontalScrollBar);
            this._horizontalScrollBar = null;
        }
    },
    getNodeByTag: function (tag) {
        return this._innerContainer.getNodeByTag(tag);
    },
    getNodes: function () {
        return this._innerContainer.getNodes();
    },
    removeNode: function (node) {
        this._innerContainer.removeNode(node);
    },
    removeNodeByTag: function (tag) {
        this._innerContainer.removeNodeByTag(tag);
    },
    removeAllNodes: function () {
        this._innerContainer.removeAllNodes();
    },
    addNode: function (node, zOrder, tag) {
        this._innerContainer.addNode(node, zOrder, tag);
    }
});
var _p = ccui.ScrollView.prototype;
_p.innerWidth;
cc.defineGetterSetter(_p, "innerWidth", _p._getInnerWidth, _p._setInnerWidth);
_p.innerHeight;
cc.defineGetterSetter(_p, "innerHeight", _p._getInnerHeight, _p._setInnerHeight);
_p.direction;
cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
_p.touchTotalTimeThreshold;
cc.defineGetterSetter(_p, "touchTotalTimeThreshold", _p.getTouchTotalTimeThreshold, _p.setTouchTotalTimeThreshold);
_p = null;
ccui.ScrollView.create = function () {
    return new ccui.ScrollView();
};
ccui.ScrollView.DIR_NONE = 0;
ccui.ScrollView.DIR_VERTICAL = 1;
ccui.ScrollView.DIR_HORIZONTAL = 2;
ccui.ScrollView.DIR_BOTH = 3;
ccui.ScrollView.EVENT_SCROLL_TO_TOP = 0;
ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM = 1;
ccui.ScrollView.EVENT_SCROLL_TO_LEFT = 2;
ccui.ScrollView.EVENT_SCROLL_TO_RIGHT = 3;
ccui.ScrollView.EVENT_SCROLLING = 4;
ccui.ScrollView.EVENT_BOUNCE_TOP = 5;
ccui.ScrollView.EVENT_BOUNCE_BOTTOM = 6;
ccui.ScrollView.EVENT_BOUNCE_LEFT = 7;
ccui.ScrollView.EVENT_BOUNCE_RIGHT = 8;
ccui.ScrollView.EVENT_CONTAINER_MOVED = 9;
ccui.ScrollView.EVENT_AUTOSCROLL_ENDED = 10;
ccui.ScrollView.MOVEDIR_TOP = 0;
ccui.ScrollView.MOVEDIR_BOTTOM = 1;
ccui.ScrollView.MOVEDIR_LEFT = 2;
ccui.ScrollView.MOVEDIR_RIGHT = 3;
(function(){
    if(!ccui.ProtectedNode.CanvasRenderCmd)
        return;
    ccui.ScrollView.CanvasRenderCmd = function(renderable){
        ccui.Layout.CanvasRenderCmd.call(this, renderable);
        this._dirty = false;
    };
    var proto = ccui.ScrollView.CanvasRenderCmd.prototype = Object.create(ccui.Layout.CanvasRenderCmd.prototype);
    proto.constructor = ccui.ScrollView.CanvasRenderCmd;
    proto.visit = function(parentCmd) {
        var node = this._node;
        if (!node._visible)
            return;
        var currentID = node.__instanceId;
        cc.renderer.pushRenderCommand(this);
        this.layoutVisit(parentCmd);
        this._dirtyFlag = 0;
    };
    proto.rendering = function (ctx) {
        var currentID = this._node.__instanceId;
        var locCmds = cc.renderer._cacheToCanvasCmds[currentID], i, len,
            scaleX = cc.view.getScaleX(),
            scaleY = cc.view.getScaleY();
        var context = ctx || cc._renderContext;
        context.computeRealOffsetY();
        this._node.updateChildren();
        for (i = 0, len = locCmds.length; i < len; i++) {
            var checkNode = locCmds[i]._node;
            if(checkNode instanceof ccui.ScrollView)
                continue;
            if(checkNode && checkNode._parent && checkNode._parent._inViewRect === false)
                continue;
            locCmds[i].rendering(context, scaleX, scaleY);
        }
    };
})();
(function(){
    if(!ccui.ProtectedNode.WebGLRenderCmd)
        return;
    ccui.ScrollView.WebGLRenderCmd = function(renderable){
        ccui.Layout.WebGLRenderCmd.call(this, renderable);
        this._needDraw = true;
        this._dirty = false;
    };
    var proto = ccui.ScrollView.WebGLRenderCmd.prototype = Object.create(ccui.Layout.WebGLRenderCmd.prototype);
    proto.constructor = ccui.ScrollView.WebGLRenderCmd;
    proto.visit = function(parentCmd) {
        var node = this._node;
        if (!node._visible)
            return;
        var currentID = this._node.__instanceId;
        cc.renderer.pushRenderCommand(this);
        cc.renderer._turnToCacheMode(currentID);
        this.layoutVisit(parentCmd);
        node.updateChildren();
        this._dirtyFlag = 0;
        cc.renderer._turnToNormalMode();
    };
    proto.rendering = function(ctx){
        var currentID = this._node.__instanceId,
            locCmds = cc.renderer._cacheToBufferCmds[currentID],
            i, len, checkNode, cmd,
            context = ctx || cc._renderContext;
        if (!locCmds) {
            return;
        }
        this._node.updateChildren();
        context.bindBuffer(gl.ARRAY_BUFFER, null);
        for (i = 0, len = locCmds.length; i < len; i++) {
            cmd = locCmds[i];
            checkNode = cmd._node;
            if(checkNode instanceof ccui.ScrollView)
                continue;
            if(checkNode && checkNode._parent && checkNode._parent._inViewRect === false)
                continue;
            if (cmd.uploadData) {
                cc.renderer._uploadBufferData(cmd);
            }
            else {
                if (cmd._batchingSize > 0) {
                    cc.renderer._batchRendering();
                }
                cmd.rendering(context);
            }
            cc.renderer._batchRendering();
        }
    };
})();
ccui.ListView = ccui.ScrollView.extend({
    _model: null,
    _items: null,
    _gravity: null,
    _itemsMargin: 0,
    _curSelectedIndex: 0,
    _refreshViewDirty: true,
    _listViewEventListener: null,
    _listViewEventSelector: null,
    _ccListViewEventCallback: null,
    _magneticAllowedOutOfBoundary: true,
    _magneticType: 0,
    _className:"ListView",
    ctor: function () {
        this._items = [];
        ccui.ScrollView.prototype.ctor.call(this);
        this._gravity = ccui.ListView.GRAVITY_CENTER_VERTICAL;
        this.setTouchEnabled(true);
        this.setDirection(ccui.ScrollView.DIR_VERTICAL);
    },
    setItemModel: function (model) {
        if (!model){
            cc.log("Can't set a null to item model!");
            return;
        }
        this._model = model;
    },
    _handleReleaseLogic: function(touch)
    {
        ccui.ScrollView.prototype._handleReleaseLogic.call(this, touch);
        if(!this._autoScrolling)
        {
            this._startMagneticScroll();
        }
    },
    _onItemListChanged: function()
    {
        this._outOfBoundaryAmountDirty = true;
    },
    _updateInnerContainerSize: function () {
        var locItems = this._items, length, i;
        switch (this.direction) {
            case ccui.ScrollView.DIR_VERTICAL:
                length = locItems.length;
                var totalHeight = (length - 1) * this._itemsMargin;
                for (i = 0; i < length; i++) {
                    totalHeight += locItems[i].getContentSize().height;
                }
                this.setInnerContainerSize(cc.size(this._contentSize.width, totalHeight));
                break;
            case ccui.ScrollView.DIR_HORIZONTAL:
                length = locItems.length;
                var totalWidth = (length - 1) * this._itemsMargin;
                for (i = 0; i < length; i++) {
                    totalWidth += locItems[i].getContentSize().width;
                }
                this.setInnerContainerSize(cc.size(totalWidth, this._contentSize.height));
                break;
            default:
                break;
        }
    },
    _remedyLayoutParameter: function (item) {
        cc.assert(null != item, "ListView Item can't be nil!");
        var linearLayoutParameter = item.getLayoutParameter(ccui.LayoutParameter.LINEAR);
        var isLayoutParameterExists = true;
        if (!linearLayoutParameter) {
            linearLayoutParameter = new ccui.LinearLayoutParameter();
            isLayoutParameterExists = false;
        }
        var itemIndex = this.getIndex(item);
        switch (this.direction) {
            case ccui.ScrollView.DIR_VERTICAL:
                this._remedyVerticalLayoutParameter(linearLayoutParameter, itemIndex);
                break;
            case ccui.ScrollView.DIR_HORIZONTAL:
                this._remedyHorizontalLayoutParameter(linearLayoutParameter, itemIndex);
                break;
            default:
                break;
        }
        if (!isLayoutParameterExists)
            item.setLayoutParameter(linearLayoutParameter);
    },
    _remedyVerticalLayoutParameter: function (layoutParameter, itemIndex) {
        cc.assert(null != layoutParameter, "Layout parameter can't be nil!");
        switch (this._gravity) {
            case ccui.ListView.GRAVITY_LEFT:
                layoutParameter.setGravity(ccui.LinearLayoutParameter.LEFT);
                break;
            case ccui.ListView.GRAVITY_RIGHT:
                layoutParameter.setGravity(ccui.LinearLayoutParameter.RIGHT);
                break;
            case ccui.ListView.GRAVITY_CENTER_HORIZONTAL:
                layoutParameter.setGravity(ccui.LinearLayoutParameter.CENTER_HORIZONTAL);
                break;
            default:
                break;
        }
        if (0 === itemIndex)
            layoutParameter.setMargin(ccui.MarginZero());
        else
            layoutParameter.setMargin(new ccui.Margin(0.0, this._itemsMargin, 0.0, 0.0));
    },
    _remedyHorizontalLayoutParameter: function (layoutParameter, itemIndex) {
        cc.assert(null != layoutParameter, "Layout parameter can't be nil!");
        switch (this._gravity) {
            case ccui.ListView.GRAVITY_TOP:
                layoutParameter.setGravity(ccui.LinearLayoutParameter.TOP);
                break;
            case ccui.ListView.GRAVITY_BOTTOM:
                layoutParameter.setGravity(ccui.LinearLayoutParameter.BOTTOM);
                break;
            case ccui.ListView.GRAVITY_CENTER_VERTICAL:
                layoutParameter.setGravity(ccui.LinearLayoutParameter.CENTER_VERTICAL);
                break;
            default:
                break;
        }
        if (0 === itemIndex)
            layoutParameter.setMargin(ccui.MarginZero());
        else
            layoutParameter.setMargin(new ccui.Margin(this._itemsMargin, 0.0, 0.0, 0.0));
    },
    pushBackDefaultItem: function () {
        if (this._model == null)
            return;
        var newItem = this._model.clone();
        this._remedyLayoutParameter(newItem);
        this.addChild(newItem);
        this._refreshViewDirty = true;
    },
    insertDefaultItem: function (index) {
        if (this._model == null)
            return;
        var newItem = this._model.clone();
        this._items.splice(index, 0, newItem);
        ccui.ScrollView.prototype.addChild.call(this, newItem);
        this._remedyLayoutParameter(newItem);
        this._refreshViewDirty = true;
    },
    pushBackCustomItem: function (item) {
        this._remedyLayoutParameter(item);
        this.addChild(item);
        this._refreshViewDirty = true;
    },
    addChild: function (widget, zOrder, tag) {
        if (widget) {
            zOrder = zOrder || widget.getLocalZOrder();
            tag = tag || widget.getName();
            ccui.ScrollView.prototype.addChild.call(this, widget, zOrder, tag);
            if(widget instanceof ccui.Widget)
            {
                this._items.push(widget);
                this._onItemListChanged();
            }
        }
    },
    removeChild: function(widget, cleanup){
        if (widget) {
            var index = this._items.indexOf(widget);
            if(index > -1)
                this._items.splice(index, 1);
            this._onItemListChanged();
            ccui.ScrollView.prototype.removeChild.call(this, widget, cleanup);
        }
    },
    removeAllChildren: function(){
        this.removeAllChildrenWithCleanup(true);
    },
    removeAllChildrenWithCleanup: function(cleanup){
        ccui.ScrollView.prototype.removeAllChildrenWithCleanup.call(this, cleanup);
        this._items = [];
        this._onItemListChanged();
    },
    insertCustomItem: function (item, index) {
        this._items.splice(index, 0, item);
        this._onItemListChanged();
        ccui.ScrollView.prototype.addChild.call(this, item);
        this._remedyLayoutParameter(item);
        this._refreshViewDirty = true;
    },
    removeItem: function (index) {
        var item = this.getItem(index);
        if (item == null)
            return;
        this.removeChild(item, true);
        this._refreshViewDirty = true;
    },
    removeLastItem: function () {
        this.removeItem(this._items.length - 1);
    },
    removeAllItems: function(){
        this.removeAllChildren();
    },
    getItem: function (index) {
        if (index < 0 || index >= this._items.length)
            return null;
        return this._items[index];
    },
    getItems: function () {
        return this._items;
    },
    getIndex: function (item) {
        if(item == null)
            return -1;
        return this._items.indexOf(item);
    },
    setGravity: function (gravity) {
        if (this._gravity === gravity)
            return;
        this._gravity = gravity;
        this._refreshViewDirty = true;
    },
    setMagneticType: function(magneticType)
    {
        this._magneticType = magneticType;
        this._onItemListChanged();
        this._startMagneticScroll();
    },
    getMagneticType: function()
    {
        return this._magneticType;
    },
    setMagneticAllowedOutOfBoundary: function(magneticAllowedOutOfBoundary)
    {
        this._magneticAllowedOutOfBoundary = magneticAllowedOutOfBoundary;
    },
    getMagneticAllowedOutOfBoundary: function()
    {
        return this._magneticAllowedOutOfBoundary;
    },
    setItemsMargin: function (margin) {
        if (this._itemsMargin === margin)
            return;
        this._itemsMargin = margin;
        this._refreshViewDirty = true;
    },
    getItemsMargin:function(){
        return this._itemsMargin;
    },
    setDirection: function (dir) {
        switch (dir) {
            case ccui.ScrollView.DIR_VERTICAL:
                this.setLayoutType(ccui.Layout.LINEAR_VERTICAL);
                break;
            case ccui.ScrollView.DIR_HORIZONTAL:
                this.setLayoutType(ccui.Layout.LINEAR_HORIZONTAL);
                break;
            case ccui.ScrollView.DIR_BOTH:
                return;
            default:
                return;
                break;
        }
        ccui.ScrollView.prototype.setDirection.call(this, dir);
    },
    _getHowMuchOutOfBoundary: function(addition)
    {
        if(addition === undefined)
            addition = cc.p(0, 0);
        if(!this._magneticAllowedOutOfBoundary || this._items.length === 0)
        {
            return ccui.ScrollView.prototype._getHowMuchOutOfBoundary.call(this, addition);
        }
        else if(this._magneticType === ccui.ListView.MAGNETIC_NONE || this._magneticType === ccui.ListView.MAGNETIC_BOTH_END)
        {
            return ccui.ScrollView.prototype._getHowMuchOutOfBoundary.call(this, addition);
        }
        else if(addition.x === 0 && addition.y === 0 && !this._outOfBoundaryAmountDirty)
        {
            return this._outOfBoundaryAmount;
        }
        var leftBoundary = this._leftBoundary;
        var rightBoundary = this._rightBoundary;
        var topBoundary = this._topBoundary;
        var bottomBoundary = this._bottomBoundary;
        var lastItemIndex = this._items.length - 1;
        var contentSize = this.getContentSize();
        var firstItemAdjustment = cc.p(0, 0);
        var lastItemAdjustment = cc.p(0, 0);
        switch (this._magneticType)
        {
            case  ccui.ListView.MAGNETIC_CENTER:
                firstItemAdjustment.x = (contentSize.width - this._items[0].width) / 2;
                firstItemAdjustment.y = (contentSize.height - this._items[0].height) / 2;
                lastItemAdjustment.x = (contentSize.width - this._items[lastItemIndex].width) / 2;
                lastItemAdjustment.y = (contentSize.height - this._items[lastItemIndex].height) / 2;
                break;
            case ccui.ListView.MAGNETIC_LEFT:
            case ccui.ListView.MAGNETIC_TOP:
                lastItemAdjustment.x = contentSize.width - this._items[lastItemIndex].width;
                lastItemAdjustment.y = contentSize.height - this._items[lastItemIndex].height;
                break;
            case ccui.ListView.MAGNETIC_RIGHT:
            case ccui.ListView.MAGNETIC_BOTTOM:
                firstItemAdjustment.x = contentSize.width - this._items[0].width;
                firstItemAdjustment.y = contentSize.height - this._items[0].height;
                break;
        }
        leftBoundary += firstItemAdjustment.x;
        rightBoundary -= lastItemAdjustment.x;
        topBoundary -= firstItemAdjustment.y;
        bottomBoundary += lastItemAdjustment.y;
        var outOfBoundaryAmount = cc.p(0, 0);
        if(this._innerContainer.getLeftBoundary() + addition.x > leftBoundary)
        {
            outOfBoundaryAmount.x = leftBoundary - (this._innerContainer.getLeftBoundary() + addition.x);
        }
        else if(this._innerContainer.getRightBoundary() + addition.x < rightBoundary)
        {
            outOfBoundaryAmount.x = rightBoundary - (this._innerContainer.getRightBoundary() + addition.x);
        }
        if(this._innerContainer.getTopBoundary() + addition.y < topBoundary)
        {
            outOfBoundaryAmount.y = topBoundary - (this._innerContainer.getTopBoundary() + addition.y);
        }
        else if(this._innerContainer.getBottomBoundary() + addition.y > bottomBoundary)
        {
            outOfBoundaryAmount.y = bottomBoundary - (this._innerContainer.getBottomBoundary() + addition.y);
        }
        if(addition.x === 0 && addition.y === 0)
        {
            this._outOfBoundaryAmount = outOfBoundaryAmount;
            this._outOfBoundaryAmountDirty = false;
        }
        return outOfBoundaryAmount;
    },
    _calculateItemPositionWithAnchor: function(item, itemAnchorPoint)
    {
        var origin = cc.p(item.getLeftBoundary(), item.getBottomBoundary());
        var size = item.getContentSize();
        return cc.p(origin. x + size.width * itemAnchorPoint.x, origin.y + size.height * itemAnchorPoint.y);
    },
    _findClosestItem: function(targetPosition, items, itemAnchorPoint, firstIndex, distanceFromFirst, lastIndex, distanceFromLast)
    {
        cc.assert(firstIndex >= 0 && lastIndex < items.length && firstIndex <= lastIndex, "");
        if (firstIndex === lastIndex)
        {
            return items[firstIndex];
        }
        if (lastIndex - firstIndex === 1)
        {
            if (distanceFromFirst <= distanceFromLast)
            {
                return items[firstIndex];
            }
            else
            {
                return items[lastIndex];
            }
        }
        var midIndex = Math.floor((firstIndex + lastIndex) / 2);
        var itemPosition = this._calculateItemPositionWithAnchor(items[midIndex], itemAnchorPoint);
        var distanceFromMid = cc.pLength(cc.pSub(targetPosition, itemPosition));
        if (distanceFromFirst <= distanceFromLast)
        {
            return this._findClosestItem(targetPosition, items, itemAnchorPoint, firstIndex, distanceFromFirst, midIndex, distanceFromMid);
        }
        else
        {
            return this._findClosestItem(targetPosition, items, itemAnchorPoint, midIndex, distanceFromMid, lastIndex, distanceFromLast);
        }
    },
    getClosestItemToPosition: function(targetPosition, itemAnchorPoint)
    {
        if (this._items.length === 0)
        {
            return null;
        }
        var firstIndex = 0;
        var firstPosition = this._calculateItemPositionWithAnchor(this._items[firstIndex], itemAnchorPoint);
        var distanceFromFirst = cc.pLength(cc.pSub(targetPosition, firstPosition));
        var lastIndex = this._items.length - 1;
        var lastPosition = this._calculateItemPositionWithAnchor(this._items[lastIndex], itemAnchorPoint);
        var distanceFromLast = cc.pLength(cc.pSub(targetPosition, lastPosition));
        return this._findClosestItem(targetPosition, this._items, itemAnchorPoint, firstIndex, distanceFromFirst, lastIndex, distanceFromLast);
    },
    getClosestItemToPositionInCurrentView: function(positionRatioInView, itemAnchorPoint)
    {
        var contentSize = this.getContentSize();
        var targetPosition = cc.pMult(this._innerContainer.getPosition(), -1);
        targetPosition.x += contentSize.width * positionRatioInView.x;
        targetPosition.y += contentSize.height * positionRatioInView.y;
        return this.getClosestItemToPosition(targetPosition, itemAnchorPoint);
    },
    getCenterItemInCurrentView: function()
    {
        return this.getClosestItemToPositionInCurrentView(cc.p(0.5, 0.5), cc.p(0.5, 0.5));
    },
    getLeftmostItemInCurrentView: function()
    {
        if(this._direction === ccui.ScrollView.DIR_HORIZONTAL)
        {
            return this.getClosestItemToPositionInCurrentView(cc.p(0, 0.5), cc.p(0.5, 0.5));
        }
        return null;
    },
    getRightmostItemInCurrentView: function()
    {
        if(this._direction === ccui.ScrollView.DIR_HORIZONTAL)
        {
            return this.getClosestItemToPositionInCurrentView(cc.p(1, 0.5), cc.p(0.5, 0.5));
        }
        return null;
    },
    getTopmostItemInCurrentView: function()
    {
        if(this._direction === ccui.ScrollView.DIR_VERTICAL)
        {
            return this.getClosestItemToPositionInCurrentView(cc.p(0.5, 1), cc.p(0.5, 0.5));
        }
        return null;
    },
    getBottommostItemInCurrentView: function()
    {
        if(this._direction === ccui.ScrollView.DIR_VERTICAL)
        {
            return this.getClosestItemToPositionInCurrentView(cc.p(0.5, 0), cc.p(0.5, 0.5));
        }
        return null;
    },
    _calculateItemDestination: function(positionRatioInView, item, itemAnchorPoint)
    {
        var contentSize = this.getContentSize();
        var positionInView = cc.p(0, 0);
        positionInView.x += contentSize.width * positionRatioInView.x;
        positionInView.y += contentSize.height * positionRatioInView.y;
        var itemPosition = this._calculateItemPositionWithAnchor(item, itemAnchorPoint);
        return cc.pMult(cc.pSub(itemPosition, positionInView), -1);
    },
    jumpToBottom: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToBottom.call(this);
    },
    jumpToTop: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToTop.call(this);
    },
    jumpToLeft: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToLeft.call(this);
    },
    jumpToRight: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToRight.call(this);
    },
    jumpToTopLeft: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToTopLeft.call(this);
    },
    jumpToTopRight: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToTopRight.call(this);
    },
    jumpToBottomLeft: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToBottomLeft.call(this);
    },
    jumpToBottomRight: function()
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToBottomRight.call(this);
    },
    jumpToPercentVertical: function(percent)
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToPercentVertical.call(this, percent);
    },
    jumpToPercentHorizontal: function(percent)
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToPercentHorizontal.call(this, percent);
    },
    jumpToPercentBothDirection: function(percent)
    {
        this.doLayout();
        ccui.ScrollView.prototype.jumpToPercentBothDirection.call(this, percent);
    },
    jumpToItem: function(itemIndex, positionRatioInView, itemAnchorPoint)
    {
        var item = this.getItem(itemIndex);
        if(!item)
            return;
        this.doLayout();
        var destination = this._calculateItemDestination(positionRatioInView, item, itemAnchorPoint);
        if(!this.bounceEnabled)
        {
            var delta = cc.pSub(destination, this._innerContainer.getPosition());
            var outOfBoundary = this._getHowMuchOutOfBoundary(delta);
            destination.x += outOfBoundary.x;
            destination.y += outOfBoundary.y;
        }
        this._jumpToDestination(destination);
    },
    scrollToItem: function(itemIndex, positionRatioInView, itemAnchorPoint, timeInSec)
    {
        if(timeInSec === undefined)
            timeInSec = 1;
        var item = this.getItem(itemIndex);
        if(!item)
            return;
        var destination = this._calculateItemDestination(positionRatioInView, item, itemAnchorPoint);
        this._startAutoScrollToDestination(destination, timeInSec, true);
    },
    requestRefreshView: function () {
        this._refreshViewDirty = true;
    },
    refreshView: function () {
        this.forceDoLayout()
    },
    doLayout: function(){
        this._doLayout();
    },
    requestDoLayout: function()
    {
        this._refreshViewDirty = true;
    },
    _doLayout: function(){
        if (this._refreshViewDirty) {
            var locItems = this._items;
            for (var i = 0; i < locItems.length; i++) {
                var item = locItems[i];
                item.setLocalZOrder(i);
                this._remedyLayoutParameter(item);
            }
            this._updateInnerContainerSize();
            this._innerContainer.forceDoLayout();
            this._refreshViewDirty = false;
        }
    },
    addEventListenerListView: function (selector, target) {
        this._listViewEventListener = target;
        this._listViewEventSelector = selector;
    },
    addEventListener: function(selector){
        this._ccListViewEventCallback = selector;
    },
    _selectedItemEvent: function (event) {
        var eventEnum = (event === ccui.Widget.TOUCH_BEGAN) ? ccui.ListView.ON_SELECTED_ITEM_START : ccui.ListView.ON_SELECTED_ITEM_END;
        if(this._listViewEventSelector){
            if (this._listViewEventListener)
                this._listViewEventSelector.call(this._listViewEventListener, this, eventEnum);
            else
                this._listViewEventSelector(this, eventEnum);
        }
        if(this._ccListViewEventCallback)
            this._ccListViewEventCallback(this, eventEnum);
    },
    interceptTouchEvent: function (eventType, sender, touch) {
        ccui.ScrollView.prototype.interceptTouchEvent.call(this, eventType, sender, touch);
        if (!this._touchEnabled) {
            return;
        }
        if (eventType !== ccui.Widget.TOUCH_MOVED) {
            var parent = sender;
            while (parent) {
                if (parent && parent.getParent() === this._innerContainer) {
                    this._curSelectedIndex = this.getIndex(parent);
                    break;
                }
                parent = parent.getParent();
            }
            if (sender.isHighlighted())
                this._selectedItemEvent(eventType);
        }
    },
    getCurSelectedIndex: function () {
        return this._curSelectedIndex;
    },
    _onSizeChanged: function () {
        ccui.ScrollView.prototype._onSizeChanged.call(this);
        this._refreshViewDirty = true;
    },
    getDescription: function () {
        return "ListView";
    },
    _createCloneInstance: function () {
        return new ccui.ListView();
    },
    _copyClonedWidgetChildren: function (model) {
        var arrayItems = model.getItems();
        for (var i = 0; i < arrayItems.length; i++) {
            var item = arrayItems[i];
            this.pushBackCustomItem(item.clone());
        }
    },
    _copySpecialProperties: function (listView) {
        if(listView instanceof ccui.ListView){
            ccui.ScrollView.prototype._copySpecialProperties.call(this, listView);
            this.setItemModel(listView._model);
            this.setItemsMargin(listView._itemsMargin);
            this.setGravity(listView._gravity);
            this._listViewEventListener = listView._listViewEventListener;
            this._listViewEventSelector = listView._listViewEventSelector;
        }
    },
    _startAttenuatingAutoScroll: function(deltaMove, initialVelocity)
    {
        var adjustedDeltaMove = deltaMove;
        if(this._items.length !== 0 && this._magneticType !== ccui.ListView.MAGNETIC_NONE)
        {
            adjustedDeltaMove = this._flattenVectorByDirection(adjustedDeltaMove);
            var howMuchOutOfBoundary = this._getHowMuchOutOfBoundary(adjustedDeltaMove);
            if(howMuchOutOfBoundary.x === 0 && howMuchOutOfBoundary.y === 0 )
            {
                var magType = this._magneticType;
                if(magType === ccui.ListView.MAGNETIC_BOTH_END)
                {
                    if(this._direction === ccui.ScrollView.DIR_HORIZONTAL)
                    {
                        magType = (adjustedDeltaMove.x > 0 ? ccui.ListView.MAGNETIC_LEFT : ccui.ListView.MAGNETIC_RIGHT);
                    }
                    else if(this._direction === ccui.ScrollView.DIR_VERTICAL)
                    {
                        magType = (adjustedDeltaMove.y > 0 ? ccui.ListView.MAGNETIC_BOTTOM : ccui.ListView.MAGNETIC_TOP);
                    }
                }
                var magneticAnchorPoint = this._getAnchorPointByMagneticType(magType);
                var magneticPosition = cc.pMult(this._innerContainer.getPosition(), -1);
                magneticPosition.x += this.width * magneticAnchorPoint.x;
                magneticPosition.y += this.height * magneticAnchorPoint.y;
                var pTargetItem = this.getClosestItemToPosition(cc.pSub(magneticPosition, adjustedDeltaMove), magneticAnchorPoint);
                var itemPosition = this._calculateItemPositionWithAnchor(pTargetItem, magneticAnchorPoint);
                adjustedDeltaMove = cc.pSub(magneticPosition, itemPosition);
            }
        }
        ccui.ScrollView.prototype._startAttenuatingAutoScroll.call(this,adjustedDeltaMove, initialVelocity);
    },
    _getAnchorPointByMagneticType: function(magneticType)
    {
        switch(magneticType)
        {
            case ccui.ListView.MAGNETIC_NONE: return cc.p(0, 0);
            case ccui.ListView.MAGNETIC_BOTH_END: return cc.p(0, 1);
            case ccui.ListView.MAGNETIC_CENTER: return cc.p(0.5, 0.5);
            case ccui.ListView.MAGNETIC_LEFT: return cc.p(0, 0.5);
            case ccui.ListView.MAGNETIC_RIGHT: return cc.p(1, 0.5);
            case ccui.ListView.MAGNETIC_TOP: return cc.p(0.5, 1);
            case ccui.ListView.MAGNETIC_BOTTOM: return cc.p(0.5, 0);
        }
        return cc.p(0, 0);
    },
    _startMagneticScroll: function()
    {
        if(this._items.length === 0 || this._magneticType === ccui.ListView.MAGNETIC_NONE)
        {
            return;
        }
        var magneticAnchorPoint =this._getAnchorPointByMagneticType(this._magneticType);
        var magneticPosition = cc.pMult(this._innerContainer.getPosition(), -1);
        magneticPosition.x += this.width * magneticAnchorPoint.x;
        magneticPosition.y += this.height * magneticAnchorPoint.y;
        var pTargetItem = this.getClosestItemToPosition(magneticPosition, magneticAnchorPoint);
        this.scrollToItem(this.getIndex(pTargetItem), magneticAnchorPoint, magneticAnchorPoint);
    }
});
ccui.ListView.create = function () {
    return new ccui.ListView();
};
ccui.ListView.EVENT_SELECTED_ITEM = 0;
ccui.ListView.ON_SELECTED_ITEM_START = 0;
ccui.ListView.ON_SELECTED_ITEM_END = 1;
ccui.ListView.GRAVITY_LEFT = 0;
ccui.ListView.GRAVITY_RIGHT = 1;
ccui.ListView.GRAVITY_CENTER_HORIZONTAL = 2;
ccui.ListView.GRAVITY_TOP = 3;
ccui.ListView.GRAVITY_BOTTOM = 4;
ccui.ListView.GRAVITY_CENTER_VERTICAL = 5;
ccui.ListView.MAGNETIC_NONE = 0;
ccui.ListView.MAGNETIC_CENTER = 1;
ccui.ListView.MAGNETIC_BOTH_END = 2;
ccui.ListView.MAGNETIC_LEFT = 3;
ccui.ListView.MAGNETIC_RIGHT = 4;
ccui.ListView.MAGNETIC_TOP = 5;
ccui.ListView.MAGNETIC_BOTTOM = 6;
ccui.PageView = ccui.ListView.extend({
    _curPageIdx: 0,
    _childFocusCancelOffset: 0,
    _pageViewEventListener: null,
    _pageViewEventSelector: null,
    _className:"PageView",
    _indicator: null,
    _indicatorPositionAsAnchorPoint: null,
    /**
     * Allocates and initializes a UIPageView.
     * Constructor of ccui.PageView. please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
     * @example
     *
     * var uiPageView = new ccui.PageView();
     */
    ctor: function () {
        ccui.ListView.prototype.ctor.call(this);
        this._childFocusCancelOffset = 5;
        this._indicatorPositionAsAnchorPoint = cc.p(0.5, 0.1);
        this._pageViewEventListener = null;
        this._pageViewEventSelector = null;
        this.setDirection(ccui.ScrollView.DIR_HORIZONTAL);
        this.setMagneticType(ccui.ListView.MAGNETIC_CENTER);
        this.setScrollBarEnabled(false);
    },
    addWidgetToPage: function (widget, pageIdx, forceCreate) {
        this.insertCustomItem(widget, pageIdx);
    },
    addPage: function(page)
    {
        this.pushBackCustomItem(page);
    },
    insertPage: function(page, idx)
    {
        this.insertCustomItem(page, idx);
    },
    removePage: function (page) {
        this.removeItem(this.getIndex(page));
    },
    removePageAtIndex: function (index) {
        this.removeItem(index);
    },
    removeAllPages: function(){
        this.removeAllItems();
    },
    scrollToItem: function (idx) {
        ccui.ListView.prototype.scrollToItem.call(this, idx, cc.p(0.5, 0.5), cc.p(0.5, 0.5));
    },
    scrollToPage: function (idx) {
        this.scrollToItem(idx);
    },
    _doLayout: function(){
        if (!this._refreshViewDirty)
            return;
        ccui.ListView.prototype._doLayout.call(this);
        if(this._indicator)
        {
            var index = this.getIndex(this.getCenterItemInCurrentView());
            this._indicator.indicate(index);
        }
        this._refreshViewDirty = false;
    },
    setDirection: function(direction)
    {
        ccui.ListView.prototype.setDirection.call(this, direction);
        if(direction === ccui.ScrollView.DIR_HORIZONTAL)
        {
            this._indicatorPositionAsAnchorPoint = cc.p(0.5, 0.1);
        }
        else if(direction === ccui.ScrollView.DIR_VERTICAL)
        {
            this._indicatorPositionAsAnchorPoint = cc.p(0.1, 0.5);
        }
        if(this._indicator)
        {
            this._indicator.setDirection(direction);
            this._refreshIndicatorPosition();
        }
    },
    setCustomScrollThreshold: function(threshold){
    },
    getCustomScrollThreshold: function(){
        return 0;
    },
    setUsingCustomScrollThreshold: function(flag){
    },
    isUsingCustomScrollThreshold: function(){
        return false;
    },
    _moveInnerContainer: function(deltaMove, canStartBounceBack)
    {
        ccui.ListView.prototype._moveInnerContainer.call(this, deltaMove, canStartBounceBack);
        this._curPageIdx = this.getIndex(this.getCenterItemInCurrentView());
        if(this._indicator)
        {
            this._indicator.indicate(this._curPageIdx);
        }
    },
    _onItemListChanged: function()
    {
        ccui.ListView.prototype._onItemListChanged.call(this);
        if(this._indicator)
        {
            this._indicator.reset(this._items.length);
        }
    },
    _onSizeChanged: function()
    {
        ccui.ListView.prototype._onSizeChanged.call(this);
        this._refreshIndicatorPosition();
    },
    _remedyLayoutParameter: function (item)
    {
        item.setContentSize(this.getContentSize());
        ccui.ListView.prototype._remedyLayoutParameter.call(this, item);
    },
    _refreshIndicatorPosition: function()
    {
        if(this._indicator)
        {
            var contentSize = this.getContentSize();
            var posX = contentSize.width * this._indicatorPositionAsAnchorPoint.x;
            var posY = contentSize.height * this._indicatorPositionAsAnchorPoint.y;
            this._indicator.setPosition(cc.p(posX, posY));
        }
    },
    _handleReleaseLogic: function (touchPoint) {
        ccui.ScrollView.prototype._handleReleaseLogic.call(this, touchPoint);
        if (this._items.length <= 0)
            return;
        var touchMoveVelocity = this._flattenVectorByDirection(this._calculateTouchMoveVelocity());
        var INERTIA_THRESHOLD = 500;
        if(cc.pLength(touchMoveVelocity) < INERTIA_THRESHOLD)
        {
            this._startMagneticScroll();
        }
        else
        {
            var currentPage = this.getItem(this._curPageIdx);
            var destination = this._calculateItemDestination(cc.p(0.5, 0.5), currentPage, cc.p(0.5, 0.5));
            var deltaToCurrentPage = cc.pSub(destination, this.getInnerContainerPosition());
            deltaToCurrentPage = this._flattenVectorByDirection(deltaToCurrentPage);
            if(touchMoveVelocity.x * deltaToCurrentPage.x > 0 || touchMoveVelocity.y * deltaToCurrentPage.y > 0)
            {
                this._startMagneticScroll();
            }
            else
            {
                if(touchMoveVelocity.x < 0 || touchMoveVelocity.y > 0)
                {
                    ++this._curPageIdx;
                }
                else
                {
                    --this._curPageIdx;
                }
                this._curPageIdx = Math.min(this._curPageIdx, this._items.length);
                this._curPageIdx = Math.max(this._curPageIdx, 0);
                this.scrollToItem(this._curPageIdx);
            }
        }
    },
    _getAutoScrollStopEpsilon: function()
    {
        return 0.001;
    },
    _pageTurningEvent: function () {
        if(this._pageViewEventSelector){
            if (this._pageViewEventListener)
                this._pageViewEventSelector.call(this._pageViewEventListener, this, ccui.PageView.EVENT_TURNING);
            else
                this._pageViewEventSelector(this, ccui.PageView.EVENT_TURNING);
        }
        if(this._ccEventCallback)
            this._ccEventCallback(this, ccui.PageView.EVENT_TURNING);
    },
    addEventListenerPageView: function (selector, target) {
        this._pageViewEventSelector = selector;
        this._pageViewEventListener = target;
    },
    addEventListener: function(selector){
        this._ccEventCallback = function(ref, eventType) {
            if(eventType == ccui.ScrollView.EVENT_AUTOSCROLL_ENDED)
                selector(this, eventType)
        };
    },
    setCurrentPageIndex: function(index)
    {
        this.jumpToItem(index, cc.p(0.5, 0.5), cc.p(0.5, 0.5));
    },
    setCurPageIndex: function(index)
    {
        this.setCurrentPageIndex(index);
    },
    getCurrentPageIndex: function () {
        return this._curPageIdx;
    },
    getCurPageIndex: function () {
        var widget = this.getCenterItemInCurrentView();
        return this.getIndex(widget);
    },
    getPages:function(){
        return this.getItems();
    },
    getPage: function(index){
        return this.getItem(index);
    },
    getDescription: function () {
        return "PageView";
    },
    _createCloneInstance: function () {
        return new ccui.PageView();
    },
    _copyClonedWidgetChildren: function (model) {
        var arrayPages = model.getPages();
        for (var i = 0; i < arrayPages.length; i++) {
            var page = arrayPages[i];
            this.addPage(page.clone());
        }
    },
    _copySpecialProperties: function (pageView) {
        ccui.ListView.prototype._copySpecialProperties.call(this, pageView);
        this._ccEventCallback = pageView._ccEventCallback;
        this._pageViewEventListener = pageView._pageViewEventListener;
        this._pageViewEventSelector = pageView._pageViewEventSelector;
        this._customScrollThreshold = pageView._customScrollThreshold;
    },
    setIndicatorEnabled: function(enabled)
    {
        if(enabled == (this._indicator !== null))
        {
            return;
        }
        if(!enabled)
        {
            this.removeProtectedChild(this._indicator);
            this._indicator = null;
        }
        else
        {
            this._indicator = new ccui.PageViewIndicator();
            this._indicator.setDirection(this.getDirection());
            this.addProtectedChild(this._indicator, 10000);
            this.setIndicatorSelectedIndexColor(cc.color(100, 100, 255));
            this._refreshIndicatorPosition();
        }
    },
    getIndicatorEnabled: function()
    {
        return this._indicator !== null;
    },
    setIndicatorPositionAsAnchorPoint: function(positionAsAnchorPoint)
    {
        this._indicatorPositionAsAnchorPoint = positionAsAnchorPoint;
        this._refreshIndicatorPosition();
    },
    getIndicatorPositionAsAnchorPoint: function()
    {
        return this._indicatorPositionAsAnchorPoint;
    },
    setIndicatorPosition: function(position)
    {
        if(this._indicator)
        {
            var contentSize = this.getContentSize();
            this._indicatorPositionAsAnchorPoint.x = position.x / contentSize.width;
            this._indicatorPositionAsAnchorPoint.y = position.y / contentSize.height;
            this._indicator.setPosition(position);
        }
    },
    getIndicatorPosition: function()
    {
        cc.assert(this._indicator !== null, "");
        return this._indicator.getPosition();
    },
    setIndicatorSpaceBetweenIndexNodes: function(spaceBetweenIndexNodes)
    {
        if(this._indicator)
        {
            this._indicator.setSpaceBetweenIndexNodes(spaceBetweenIndexNodes);
        }
    },
    getIndicatorSpaceBetweenIndexNodes: function()
    {
        cc.assert(this._indicator !== null, "");
        return this._indicator.getSpaceBetweenIndexNodes();
    },
    setIndicatorSelectedIndexColor: function(color)
    {
        if(this._indicator)
        {
            this._indicator.setSelectedIndexColor(color);
        }
    },
    getIndicatorSelectedIndexColor: function()
    {
        cc.assert(this._indicator !== null, "");
        return this._indicator.getSelectedIndexColor();
    },
    setIndicatorIndexNodesColor: function(color)
    {
        if(this._indicator)
        {
            this._indicator.setIndexNodesColor(color);
        }
    },
    getIndicatorIndexNodesColor: function()
    {
        cc.assert(this._indicator !== null, "");
        return this._indicator.getIndexNodesColor();
    },
    setIndicatorIndexNodesScale: function(indexNodesScale)
    {
        if(this._indicator)
        {
            this._indicator.setIndexNodesScale(indexNodesScale);
            this._indicator.indicate(this._curPageIdx);
        }
    },
    getIndicatorIndexNodesScale: function()
    {
        cc.assert(this._indicator !== null, "");
        return this._indicator.getIndexNodesScale();
    },
    setIndicatorIndexNodesTexture: function(texName, texType)
    {
        if(this._indicator)
        {
            this._indicator.setIndexNodesTexture(texName, texType);
            this._indicator.indicate(this._curPageIdx);
        }
    }
});
ccui.PageView.create = function () {
    return new ccui.PageView();
};
ccui.PageView.EVENT_TURNING = 0;
ccui.PageView.TOUCH_DIR_LEFT = 0;
ccui.PageView.TOUCH_DIR_RIGHT = 1;
ccui.PageView.DIRECTION_LEFT = 0;
ccui.PageView.DIRECTION_RIGHT = 1;
ccui.PageViewIndicator = ccui.ProtectedNode.extend({
    _direction: null,
    _indexNodes: null,
    _currentIndexNode: null,
    _spaceBetweenIndexNodes: 0,
    _indexNodesScale: 1.0,
    _indexNodesColor: null,
    _useDefaultTexture: true,
    _indexNodesTextureFile: "",
    _indexNodesTexType: ccui.Widget.LOCAL_TEXTURE,
    _className: "PageViewIndicator",
    ctor: function () {
        cc.ProtectedNode.prototype.ctor.call(this);
        this._direction = ccui.ScrollView.DIR_HORIZONTAL;
        this._indexNodes = [];
        this._spaceBetweenIndexNodes = ccui.PageViewIndicator.SPACE_BETWEEN_INDEX_NODES_DEFAULT;
        this._indexNodesColor = cc.color.WHITE;
        this._currentIndexNode = ccui.helper._createSpriteFromBase64(ccui.PageViewIndicator.CIRCLE_IMAGE, ccui.PageViewIndicator.CIRCLE_IMAGE_KEY);
        this._currentIndexNode.setVisible(false);
        this.addProtectedChild(this._currentIndexNode, 1);
    },
    setDirection: function(direction)
    {
        this._direction = direction;
        this._rearrange();
    },
    reset: function(numberOfTotalPages)
    {
        while(this._indexNodes.length < numberOfTotalPages)
        {
            this._increaseNumberOfPages();
        }
        while(this._indexNodes.length > numberOfTotalPages)
        {
            this._decreaseNumberOfPages();
        }
        this._rearrange();
        this._currentIndexNode.setVisible(this._indexNodes.length > 0);
    },
    indicate: function(index)
    {
        if (index < 0 || index >= this._indexNodes.length)
        {
            return;
        }
        this._currentIndexNode.setPosition(this._indexNodes[index].getPosition());
    },
    _rearrange: function()
    {
        if(this._indexNodes.length === 0)
        {
            return;
        }
        var horizontal = (this._direction === ccui.ScrollView.DIR_HORIZONTAL);
        var indexNodeSize = this._indexNodes[0].getContentSize();
        var sizeValue = (horizontal ? indexNodeSize.width : indexNodeSize.height);
        var numberOfItems = this._indexNodes.length;
        var totalSizeValue = sizeValue * numberOfItems + this._spaceBetweenIndexNodes * (numberOfItems - 1);
        var posValue = -(totalSizeValue / 2) + (sizeValue / 2);
        for(var i = 0; i < this._indexNodes.length; ++i)
        {
            var position;
            if(horizontal)
            {
                position = cc.p(posValue, indexNodeSize.height / 2.0);
            }
            else
            {
                position = cc.p(indexNodeSize.width / 2.0, -posValue);
            }
            this._indexNodes[i].setPosition(position);
            posValue += sizeValue + this._spaceBetweenIndexNodes;
        }
    },
    setSpaceBetweenIndexNodes: function(spaceBetweenIndexNodes)
    {
        if(this._spaceBetweenIndexNodes === spaceBetweenIndexNodes)
        {
            return;
        }
        this._spaceBetweenIndexNodes = spaceBetweenIndexNodes;
        this._rearrange();
    },
    getSpaceBetweenIndexNodes: function()
    {
        return this._spaceBetweenIndexNodes;
    },
    setSelectedIndexColor: function(color)
    {
        this._currentIndexNode.setColor(color);
    },
    getSelectedIndexColor: function()
    {
        return this._currentIndexNode.getColor();
    },
    setIndexNodesColor: function(indexNodesColor)
    {
        this._indexNodesColor = indexNodesColor;
        for(var  i = 0 ; i < this._indexNodes.length; ++i)
        {
            this._indexNodes[i].setColor(indexNodesColor);
        }
    },
    getIndexNodesColor: function()
    {
        var locRealColor = this._indexNodesColor;
        return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
    },
    setIndexNodesScale: function(indexNodesScale)
    {
        if(this._indexNodesScale === indexNodesScale)
        {
            return;
        }
        this._indexNodesScale = indexNodesScale;
        this._currentIndexNode.setScale(indexNodesScale);
        for(var  i = 0 ; i < this._indexNodes.length; ++i)
        {
            this._indexNodes[i].setScale(this,_indexNodesScale);
        }
        this._rearrange();
    },
    getIndexNodesScale: function()
    {
        return this._indexNodesScale;
    },
    setIndexNodesTexture: function(texName, texType)
    {
        if(texType === undefined)
            texType = ccui.Widget.LOCAL_TEXTURE;
        this._useDefaultTexture = false;
        this._indexNodesTextureFile = texName;
        this._indexNodesTexType = texType;
        switch (texType)
        {
            case ccui.Widget.LOCAL_TEXTURE:
                this._currentIndexNode.setTexture(texName);
                for(var  i = 0 ; i < this._indexNodes.length; ++i)
                {
                    this._indexNodes[i].setTexture(texName);
                }
                break;
            case ccui.Widget.PLIST_TEXTURE:
                this._currentIndexNode.setSpriteFrame(texName);
                for(var  i = 0 ; i < this._indexNodes.length; ++i)
                {
                    this._indexNodes[i].setSpriteFrame(texName);
                }
                break;
            default:
                break;
        }
        this._rearrange();
    },
    _increaseNumberOfPages: function()
    {
        var indexNode;
        if(this._useDefaultTexture)
        {
            indexNode = ccui.helper._createSpriteFromBase64(ccui.PageViewIndicator.CIRCLE_IMAGE, ccui.PageViewIndicator.CIRCLE_IMAGE_KEY);
        }
        else
        {
            indexNode = new cc.Sprite();
            switch (this._indexNodesTexType)
            {
                case ccui.Widget.LOCAL_TEXTURE:
                    indexNode.initWithFile(this._indexNodesTextureFile);
                    break;
                case  ccui.Widget.PLIST_TEXTURE:
                    indexNode.initWithSpriteFrameName(this._indexNodesTextureFile);
                    break;
                default:
                    break;
            }
        }
        indexNode.setColor(this._indexNodesColor);
        indexNode.setScale(this._indexNodesScale);
        this.addProtectedChild(indexNode);
        this._indexNodes.push(indexNode);
    },
    _decreaseNumberOfPages: function()
    {
        if(this._indexNodes.length === 0)
        {
            return;
        }
        this.removeProtectedChild(this._indexNodes[0]);
        this._indexNodes.splice(0, 1);
    },
    clear: function()
    {
        for(var i = 0; i < this._indexNodes.length; ++i)
        {
            this.removeProtectedChild(this._indexNodes[i]);
        }
        this._indexNodes.length = 0;
        this._currentIndexNode.setVisible(false);
    }
});
var _p = ccui.PageViewIndicator.prototype;
_p.spaceBetweenIndexNodes;
cc.defineGetterSetter(_p, "spaceBetweenIndexNodes", _p.getSpaceBetweenIndexNodes, _p.setSpaceBetweenIndexNodes);
ccui.PageViewIndicator.SPACE_BETWEEN_INDEX_NODES_DEFAULT = 23;
ccui.PageViewIndicator.CIRCLE_IMAGE_KEY = "/__circle_image";
ccui.PageViewIndicator.CIRCLE_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAA8ElEQVRIx62VyRGCQBBF+6gWRCEmYDIQkhiBCgHhSclC8YqWzOV5oVzKAYZp3r1/9fpbxAIBMTsKrjx5cqVgR0wgLhCRUWOjJiPqD56xoaGPhpRZV/iSEy6crHmw5oIrF9b/lVeMofrJgjlnxlIy/wik+JB+mme8BExbBhm+5CJC2LE2LtSEQoyGWDioBA5CoRIohJtK4CYDxzNEM4GAugR1E9VjVC+SZpXvhCJCrjomESLvc17pDGX7bWmlh6UtpjPVCWy9zaJ0TD7qfm3pwERMz2trRVZk3K3BD/L34AY+dEDCniMVBkPFkT2J/b2/AIV+dRpFLOYoAAAAAElFTkSuQmCC";
ccui.VideoPlayer = ccui.Widget.extend({
    _played: false,
    _playing: false,
    _stopped: true,
    ctor: function(path){
        ccui.Widget.prototype.ctor.call(this);
        this._EventList = {};
        if(path)
            this.setURL(path);
    },
    _createRenderCmd: function(){
        return new ccui.VideoPlayer.RenderCmd(this);
    },
    setURL: function(address){
        this._renderCmd.updateURL(address);
    },
    getURL: function() {
        return this._renderCmd._url;
    },
    play: function(){
        var self = this,
            video = this._renderCmd._video;
        if(video){
            this._played = true;
            video.pause();
            if(this._stopped !== false || this._playing !== false || this._played !== true)
                video.currentTime = 0;
            if(ccui.VideoPlayer._polyfill.autoplayAfterOperation){
                setTimeout(function(){
                    video.play();
                    self._playing = true;
                    self._stopped = false;
                }, 20);
            }else{
                video.play();
                this._playing = true;
                this._stopped = false;
            }
        }
    },
    pause: function(){
        var video = this._renderCmd._video;
        if(video && this._playing === true && this._stopped === false){
            video.pause();
            this._playing = false;
        }
    },
    resume: function(){
        if(this._stopped === false && this._playing === false && this._played === true){
            this.play();
        }
    },
    stop: function(){
        var self = this,
            video = this._renderCmd._video;
        if(video){
            video.pause();
            video.currentTime = 0;
            this._playing = false;
            this._stopped = true;
        }
        setTimeout(function(){
            self._dispatchEvent(ccui.VideoPlayer.EventType.STOPPED);
        }, 0);
    },
    seekTo: function(sec){
        var video = this._renderCmd._video;
        if(video){
            video.currentTime = sec;
            if(ccui.VideoPlayer._polyfill.autoplayAfterOperation && this.isPlaying()){
                setTimeout(function(){
                    video.play();
                }, 20);
            }
        }
    },
    isPlaying: function(){
        if(ccui.VideoPlayer._polyfill.autoplayAfterOperation && this._playing){
            setTimeout(function(){
                video.play();
            }, 20);
        }
        return this._playing;
    },
    setKeepAspectRatioEnabled: function(enable){
        cc.log("On the web is always keep the aspect ratio");
    },
    isKeepAspectRatioEnabled: function(){
        return false;
    },
    setFullScreenEnabled: function(enable){
        var video = this._renderCmd._video;
        if(video){
            if(enable)
                cc.screen.requestFullScreen(video);
            else
                cc.screen.exitFullScreen(video);
        }
    },
    isFullScreenEnabled: function(){
        cc.log("Can't know status");
    },
    setEventListener: function(event, callback){
        this._EventList[event] = callback;
    },
    removeEventListener: function(event){
        this._EventList[event] = null;
    },
    _dispatchEvent: function(event) {
        var callback = this._EventList[event];
        if (callback)
            callback.call(this, this, this._renderCmd._video.src);
    },
    onPlayEvent: function(){
        var list = this._EventList[ccui.VideoPlayer.EventType.PLAYING];
        if(list)
            for(var i=0; i<list.length; i++)
                list[i].call(this, this, this._renderCmd._video.src);
    },
    setContentSize: function(w, h){
        ccui.Widget.prototype.setContentSize.call(this, w, h);
        if(h === undefined){
            h = w.height;
            w = w.width;
        }
        this._renderCmd.changeSize(w, h);
    },
    cleanup: function(){
        this._renderCmd.removeDom();
        this.stopAllActions();
        this.unscheduleAllCallbacks();
    },
    onEnter: function(){
        ccui.Widget.prototype.onEnter.call(this);
        var list = ccui.VideoPlayer.elements;
        if(list.indexOf(this) === -1)
            list.push(this);
    },
    onExit: function(){
        ccui.Widget.prototype.onExit.call(this);
        var list = ccui.VideoPlayer.elements;
        var index = list.indexOf(this);
        if(index !== -1)
            list.splice(index, 1);
    }
});
ccui.VideoPlayer.elements = [];
ccui.VideoPlayer.pauseElements = [];
cc.eventManager.addCustomListener(cc.game.EVENT_HIDE, function () {
    var list = ccui.VideoPlayer.elements;
    for(var node, i=0; i<list.length; i++){
        node = list[i];
        if(list[i]._playing){
            node.pause();
            ccui.VideoPlayer.pauseElements.push(node);
        }
    }
});
cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () {
    var list = ccui.VideoPlayer.pauseElements;
    var node = list.pop();
    while(node){
        node.play();
        node = list.pop();
    }
});
ccui.VideoPlayer.EventType = {
    PLAYING: "play",
    PAUSED: "pause",
    STOPPED: "stop",
    COMPLETED: "complete"
};
(function(video){
    video._polyfill = {
        devicePixelRatio: false,
        event: "canplay",
        canPlayType: []
    };
    (function(){
        var dom = document.createElement("video");
        if(dom.canPlayType("video/ogg")){
            video._polyfill.canPlayType.push(".ogg");
            video._polyfill.canPlayType.push(".ogv");
        }
        if(dom.canPlayType("video/mp4"))
            video._polyfill.canPlayType.push(".mp4");
        if(dom.canPlayType("video/webm"))
            video._polyfill.canPlayType.push(".webm");
    })();
    if(cc.sys.OS_IOS === cc.sys.os){
        video._polyfill.devicePixelRatio = true;
        video._polyfill.event = "progress";
    }
    if(cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX){
        video._polyfill.autoplayAfterOperation = true;
    }
    var style = document.createElement("style");
    style.innerHTML = ".cocosVideo:-moz-full-screen{transform:matrix(1,0,0,1,0,0) !important;}" +
    ".cocosVideo:full-screen{transform:matrix(1,0,0,1,0,0) !important;}" +
    ".cocosVideo:-webkit-full-screen{transform:matrix(1,0,0,1,0,0) !important;}";
    document.head.appendChild(style);
})(ccui.VideoPlayer);
(function(polyfill){
    var RenderCmd = null;
    if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        RenderCmd = cc.Node.WebGLRenderCmd;
    } else {
        RenderCmd = cc.Node.CanvasRenderCmd;
    }
    ccui.VideoPlayer.RenderCmd = function(node){
        RenderCmd.call(this, node);
        this._listener = null;
        this._url = "";
        this.initStyle();
    };
    var proto = ccui.VideoPlayer.RenderCmd.prototype = Object.create(RenderCmd.prototype);
    proto.constructor = ccui.VideoPlayer.RenderCmd;
    proto.visit = function(){
        var self = this,
            container = cc.container,
            eventManager = cc.eventManager;
        if(this._node._visible){
            container.appendChild(this._video);
            if(this._listener === null)
                this._listener = cc.eventManager.addCustomListener(cc.game.EVENT_RESIZE, function () {
                    self.resize();
                });
        }else{
            var hasChild = false;
            if('contains' in container) {
                hasChild = container.contains(this._video);
            }else {
                hasChild = container.compareDocumentPosition(this._video) % 16;
            }
            if(hasChild)
                container.removeChild(this._video);
            eventManager.removeListener(this._listener);
            this._listener = null;
        }
        this.updateStatus();
    };
    proto.transform = function (parentCmd, recursive) {
        this.originTransform(parentCmd, recursive);
        this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
    };
    proto.updateStatus = function(){
        polyfill.devicePixelRatio = cc.view.isRetinaEnabled();
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if(locFlag & flags.transformDirty){
            this.transform(this.getParentRenderCmd(), true);
            this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
            this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty ^ this._dirtyFlag;
        }
        if (locFlag & flags.orderDirty) {
            this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
        }
    };
    proto.resize = function(view){
        view = view || cc.view;
        var node = this._node,
            eventManager = cc.eventManager;
        if(node._parent && node._visible)
            this.updateMatrix(this._worldTransform, view._scaleX, view._scaleY);
        else{
            eventManager.removeListener(this._listener);
            this._listener = null;
        }
    };
    proto.updateMatrix = function(t, scaleX, scaleY){
        var node = this._node;
        if(polyfill.devicePixelRatio){
            var dpr = cc.view.getDevicePixelRatio();
            scaleX = scaleX / dpr;
            scaleY = scaleY / dpr;
        }
        if(this._loaded === false) return;
        var cw = node._contentSize.width,
            ch = node._contentSize.height;
        var a = t.a * scaleX,
            b = t.b,
            c = t.c,
            d = t.d * scaleY,
            tx = t.tx*scaleX - cw/2 + cw*node._scaleX/2*scaleX,
            ty = t.ty*scaleY - ch/2 + ch*node._scaleY/2*scaleY;
        var matrix = "matrix(" + a + "," + b + "," + c + "," + d + "," + tx + "," + -ty + ")";
        this._video.style["transform"] = matrix;
        this._video.style["-webkit-transform"] = matrix;
    };
    proto.updateURL = function(path){
        var source, video, hasChild, container, extname;
        var node = this._node;
        if (this._url == path)
            return;
        this._url = path;
        if(cc.loader.resPath && !/^http/.test(path))
            path = cc.path.join(cc.loader.resPath, path);
        hasChild = false;
        container = cc.container;
        if('contains' in container) {
            hasChild = container.contains(this._video);
        }else {
            hasChild = container.compareDocumentPosition(this._video) % 16;
        }
        if(hasChild)
            container.removeChild(this._video);
        this._video = document.createElement("video");
        video = this._video;
        this.bindEvent();
        var self = this;
        var cb = function(){
            if(self._loaded == true)
                return;
            self._loaded = true;
            self.changeSize();
            self.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
            video.removeEventListener(polyfill.event, cb);
            video.currentTime = 0;
            video.style["visibility"] = "visible";
            video.play();
            if(!node._played){
                video.pause();
                video.currentTime = 0;
            }
        };
        video.addEventListener(polyfill.event, cb);
        video.preload = "metadata";
        video.style["visibility"] = "hidden";
        this._loaded = false;
        node._played = false;
        node._playing = false;
        node._stopped = true;
        this.initStyle();
        this.visit();
        source = document.createElement("source");
        source.src = path;
        video.appendChild(source);
        extname = cc.path.extname(path);
        for(var i=0; i<polyfill.canPlayType.length; i++){
            if(extname !== polyfill.canPlayType[i]){
                source = document.createElement("source");
                source.src = path.replace(extname, polyfill.canPlayType[i]);
                video.appendChild(source);
            }
        }
    };
    proto.bindEvent = function(){
        var self = this,
            node = this._node,
            video = this._video;
        video.addEventListener("ended", function(){
            node._renderCmd.updateMatrix(self._worldTransform, cc.view._scaleX, cc.view._scaleY);
            node._playing = false;
            node._dispatchEvent(ccui.VideoPlayer.EventType.COMPLETED);
        });
        video.addEventListener("play", function(){
            node._dispatchEvent(ccui.VideoPlayer.EventType.PLAYING);
        });
        video.addEventListener("pause", function(){
            node._dispatchEvent(ccui.VideoPlayer.EventType.PAUSED);
        });
    };
    proto.initStyle = function(){
        if(!this._video)  return;
        var video = this._video;
        video.style.position = "absolute";
        video.style.bottom = "0px";
        video.style.left = "0px";
        video.className = "cocosVideo";
    };
    proto.changeSize = function(w, h){
        var contentSize = this._node._contentSize;
        w = w || contentSize.width;
        h = h || contentSize.height;
        var video = this._video;
        if(video){
            if(w !== 0)
                video.width = w;
            if(h !== 0)
                video.height = h;
        }
    };
    proto.removeDom = function(){
        var video = this._video;
        if(video){
            var hasChild = false;
            if('contains' in cc.container) {
                hasChild = cc.container.contains(video);
            }else {
                hasChild = cc.container.compareDocumentPosition(video) % 16;
            }
            if(hasChild)
                cc.container.removeChild(video);
        }
    };
})(ccui.VideoPlayer._polyfill);
ccui.WebView = ccui.Widget.extend({
    ctor: function(path){
        ccui.Widget.prototype.ctor.call(this);
        this._EventList = {};
        if(path)
            this.loadURL(path);
    },
    setJavascriptInterfaceScheme: function(scheme){},
    loadData: function(data, MIMEType, encoding, baseURL){},
    loadHTMLString: function(string, baseURL){},
    loadURL: function(url){
        this._renderCmd.updateURL(url);
        this._dispatchEvent(ccui.WebView.EventType.LOADING);
    },
    stopLoading: function(){
        cc.log("Web does not support loading");
    },
    reload: function(){
        var iframe = this._renderCmd._iframe;
        if(iframe){
            var win = iframe.contentWindow;
            if(win && win.location)
                win.location.reload();
        }
    },
    canGoBack: function(){
        cc.log("Web does not support query history");
        return true;
    },
    canGoForward: function(){
        cc.log("Web does not support query history");
        return true;
    },
    goBack: function(){
        try{
            if(ccui.WebView._polyfill.closeHistory)
                return cc.log("The current browser does not support the GoBack");
            var iframe = this._renderCmd._iframe;
            if(iframe){
                var win = iframe.contentWindow;
                if(win && win.location)
                    try {
                        win.history.back.call(win);
                    } catch (error) {
                        win.history.back();
                    }
            }
        }catch(err){
            cc.log(err);
        }
    },
    goForward: function(){
        try{
            if(ccui.WebView._polyfill.closeHistory)
                return cc.log("The current browser does not support the GoForward");
            var iframe = this._renderCmd._iframe;
            if(iframe){
                var win = iframe.contentWindow;
                if(win && win.location)
                    try {
                        win.history.forward.call(win);
                    } catch (error) {
                        win.history.forward();
                    }
            }
        }catch(err){
            cc.log(err);
        }
    },
    evaluateJS: function(str){
        var iframe = this._renderCmd._iframe;
        if(iframe){
            var win = iframe.contentWindow;
            try{
                win.eval(str);
                this._dispatchEvent(ccui.WebView.EventType.JS_EVALUATED);
            }catch(err){
                console.error(err);
            }
        }
    },
    setScalesPageToFit: function(){
        cc.log("Web does not support zoom");
    },
    setEventListener: function(event, callback){
        this._EventList[event] = callback;
    },
    removeEventListener: function(event){
        this._EventList[event] = null;
    },
    _dispatchEvent: function(event) {
        var callback = this._EventList[event];
        if (callback)
            callback.call(this, this, this._renderCmd._iframe.src);
    },
    _createRenderCmd: function(){
        return new ccui.WebView.RenderCmd(this);
    },
    setContentSize: function(w, h){
        ccui.Widget.prototype.setContentSize.call(this, w, h);
        if(h === undefined){
            h = w.height;
            w = w.width;
        }
        this._renderCmd.changeSize(w, h);
    },
    cleanup: function(){
        this._renderCmd.removeDom();
        this.stopAllActions();
        this.unscheduleAllCallbacks();
    }
});
ccui.WebView.EventType = {
    LOADING: "loading",
    LOADED: "load",
    ERROR: "error",
    JS_EVALUATED: "js"
};
(function(){
    var polyfill = ccui.WebView._polyfill = {
        devicePixelRatio: false,
        enableDiv: false
    };
    if(cc.sys.os === cc.sys.OS_IOS)
        polyfill.enableDiv = true;
    if(cc.sys.isMobile){
        if(cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX){
            polyfill.enableBG = true;
        }
    }else{
        if(cc.sys.browserType === cc.sys.BROWSER_TYPE_IE){
            polyfill.closeHistory = true;
        }
    }
})();
(function(polyfill){
    var RenderCmd = null;
    if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        RenderCmd = cc.Node.WebGLRenderCmd;
    } else {
        RenderCmd = cc.Node.CanvasRenderCmd;
    }
    ccui.WebView.RenderCmd = function(node){
        RenderCmd.call(this, node);
        this._div = null;
        this._iframe = null;
        if(polyfill.enableDiv){
            this._div = document.createElement("div");
            this._div.style["-webkit-overflow"] = "auto";
            this._div.style["-webkit-overflow-scrolling"] = "touch";
            this._iframe = document.createElement("iframe");
            this._iframe.style["width"] = "100%";
            this._iframe.style["height"] = "100%";
            this._div.appendChild(this._iframe);
        }else{
            this._div = this._iframe = document.createElement("iframe");
        }
        if(polyfill.enableBG)
            this._div.style["background"] = "#FFF";
        this._iframe.addEventListener("load", function(){
            node._dispatchEvent(ccui.WebView.EventType.LOADED);
        });
        this._iframe.addEventListener("error", function(){
            node._dispatchEvent(ccui.WebView.EventType.ERROR);
        });
        this._div.style["background"] = "#FFF";
        this._div.style.height = "200px";
        this._div.style.width = "300px";
        this._div.style.overflow = "scroll";
        this._listener = null;
        this.initStyle();
    };
    var proto = ccui.WebView.RenderCmd.prototype = Object.create(RenderCmd.prototype);
    proto.constructor = ccui.WebView.RenderCmd;
    proto.transform = function (parentCmd, recursive) {
        this.originTransform(parentCmd, recursive);
        this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
    };
    proto.updateStatus = function(){
        polyfill.devicePixelRatio = cc.view.isRetinaEnabled();
        var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
        if(locFlag & flags.transformDirty){
            this.transform(this.getParentRenderCmd(), true);
            this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
            this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty ^ this._dirtyFlag;
        }
        if (locFlag & flags.orderDirty) {
            this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
        }
    };
    proto.visit = function(){
        var self = this,
            container = cc.container,
            eventManager = cc.eventManager;
        if(this._node._visible){
            container.appendChild(this._div);
            if(this._listener === null)
                this._listener = eventManager.addCustomListener(cc.game.EVENT_RESIZE, function () {
                    self.resize();
                });
        }else{
            var hasChild = false;
            if('contains' in container) {
                hasChild = container.contains(this._div);
            }else {
                hasChild = container.compareDocumentPosition(this._div) % 16;
            }
            if(hasChild)
                container.removeChild(this._div);
            var list = eventManager._listenersMap[cc.game.EVENT_RESIZE].getFixedPriorityListeners();
            eventManager._removeListenerInVector(list, this._listener);
            this._listener = null;
        }
        this.updateStatus();
        this.resize(cc.view);
    };
    proto.resize = function(view){
        view = view || cc.view;
        var node = this._node,
            eventManager = cc.eventManager;
        if(node._parent && node._visible)
            this.updateMatrix(this._worldTransform, view._scaleX, view._scaleY);
        else{
            var list = eventManager._listenersMap[cc.game.EVENT_RESIZE].getFixedPriorityListeners();
            eventManager._removeListenerInVector(list, this._listener);
            this._listener = null;
        }
    };
    proto.updateMatrix = function(t, scaleX, scaleY){
        var node = this._node;
        if (polyfill.devicePixelRatio && scaleX !== 1 && scaleX !== 1) {
            var dpr = cc.view.getDevicePixelRatio();
            scaleX = scaleX / dpr;
            scaleY = scaleY / dpr;
        }
        if(this._loaded === false) return;
        var cw = node._contentSize.width,
            ch = node._contentSize.height;
        var a = t.a * scaleX,
            b = t.b,
            c = t.c,
            d = t.d * scaleY,
            tx = t.tx*scaleX - cw/2 + cw*node._scaleX/2*scaleX,
            ty = t.ty*scaleY - ch/2 + ch*node._scaleY/2*scaleY;
        var matrix = "matrix(" + a + "," + b + "," + c + "," + d + "," + tx + "," + -ty + ")";
        this._div.style["transform"] = matrix;
        this._div.style["-webkit-transform"] = matrix;
    };
    proto.initStyle = function(){
        if(!this._div)  return;
        var div = this._div;
        div.style.position = "absolute";
        div.style.bottom = "0px";
        div.style.left = "0px";
    };
    proto.updateURL = function(url){
        var iframe = this._iframe;
        iframe.src = url;
        var self = this;
        var cb = function(){
            self._loaded = true;
            iframe.removeEventListener("load", cb);
        };
        iframe.addEventListener("load", cb);
    };
    proto.changeSize = function(w, h){
        var div = this._div;
        if(div){
            div.style["width"] = w+"px";
            div.style["height"] = h+"px";
        }
    };
    proto.removeDom = function(){
        var div = this._div;
        if(div){
            var hasChild = false;
            if('contains' in cc.container) {
                hasChild = cc.container.contains(div);
            }else {
                hasChild = cc.container.compareDocumentPosition(div) % 16;
            }
            if(hasChild)
                cc.container.removeChild(div);
        }
    };
})(ccui.WebView._polyfill);
cc.Component = cc.Class.extend({
    _owner: null,
    _name: "",
    _enabled: true,
    ctor:function(){
        this._owner = null;
        this._name = "";
        this._enabled = true;
    },
    init:function(){
       return true;
    },
    onEnter:function(){
    },
    onExit:function(){
    },
    update:function(delta){
    },
    serialize:function( reader){
    },
    isEnabled:function(){
        return this._enabled;
    },
    setEnabled:function(enable){
        this._enabled = enable;
    },
    getName:function(){
        return this._name;
    } ,
    setName:function(name){
         this._name = name;
    } ,
    setOwner:function(owner){
        this._owner = owner;
    },
    getOwner:function(){
        return this._owner;
    }
});
cc.Component.create = function(){
    return new cc.Component();
};
ccui.LayoutComponent_ReferencePoint = {
    BOTTOM_LEFT: 0,
    TOP_LEFT: 1,
    BOTTOM_RIGHT: 2,
    TOP_RIGHT: 3
};
ccui.LayoutComponent_PositionType = {
    Position: 0,
    RelativePosition: 1,
    PreRelativePosition: 2,
    PreRelativePositionEnable: 3
};
ccui.LayoutComponent_SizeType = {
    Size: 0,
    PreSize: 1,
    PreSizeEnable: 2
};
ccui.LayoutComponent = cc.Component.extend({
    _horizontalEdge: 0,
    _verticalEdge: 0,
    _leftMargin: 0,
    _rightMargin: 0,
    _bottomMargin: 0,
    _topMargin: 0,
    _usingPositionPercentX: false,
    _positionPercentX: 0,
    _usingPositionPercentY: false,
    _positionPercentY: 0,
    _usingStretchWidth: false,
    _usingStretchHeight: false,
    _percentWidth: 0,
    _usingPercentWidth: false,
    _percentHeight: 0,
    _usingPercentHeight: false,
    _actived: true,
    _isPercentOnly: false,
    ctor: function () {
        this._name = ccui.LayoutComponent.NAME;
    },
    init: function () {
        var ret = true;
        if (!cc.Component.prototype.init.call(this)) {
            return false;
        }
        return ret;
    },
    getPercentContentSize: function () {
        return cc.p(this._percentWidth, this._percentHeight);
    },
    setPercentContentSize: function (percent) {
        this.setPercentWidth(percent.x);
        this.setPercentHeight(percent.y);
    },
    setUsingPercentContentSize: function (isUsed) {
        this._usingPercentWidth = this._usingPercentHeight = isUsed;
    },
    SetActiveEnable: function (enable) {
        this._actived = enable;
    },
    getUsingPercentContentSize: function () {
        return this._usingPercentWidth && this._usingPercentHeight;
    },
    getAnchorPosition: function () {
        return this._owner.getAnchorPoint();
    },
    setAnchorPosition: function (point, y) {
        var oldRect = this._owner.getBoundingBox();
        this._owner.setAnchorPoint(point, y);
        var newRect = this._owner.getBoundingBox();
        var offSetX = oldRect.x - newRect.x, offSetY = oldRect.y - newRect.y;
        var ownerPosition = this._owner.getPosition();
        ownerPosition.x += offSetX;
        ownerPosition.y += offSetY;
        this.setPosition(ownerPosition);
    },
    getPosition: function () {
        return this._owner.getPosition();
    },
    setPosition: function (position, y) {
        var parent = this._getOwnerParent(), x;
        if (parent != null) {
            if (y === undefined) {
                x = position.x;
                y = position.y;
            } else
                x = position;
            var parentSize = parent.getContentSize();
            if (parentSize.width !== 0)
                this._positionPercentX = x / parentSize.width;
            else {
                this._positionPercentX = 0;
                if (this._usingPositionPercentX)
                    x = 0;
            }
            if (parentSize.height !== 0)
                this._positionPercentY = y / parentSize.height;
            else {
                this._positionPercentY = 0;
                if (this._usingPositionPercentY)
                    y = 0;
            }
            this._owner.setPosition(x, y);
            this._refreshHorizontalMargin();
            this._refreshVerticalMargin();
        } else
            this._owner.setPosition(position, y);
    },
    isPositionPercentXEnabled: function () {
        return this._usingPositionPercentX;
    },
    setPositionPercentXEnabled: function (isUsed) {
        this._usingPositionPercentX = isUsed;
        if (this._usingPositionPercentX)
            this._horizontalEdge = ccui.LayoutComponent.horizontalEdge.NONE;
    },
    getPositionPercentX: function () {
        return this._positionPercentX;
    },
    setPositionPercentX: function (percentMargin) {
        this._positionPercentX = percentMargin;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            this._owner.setPositionX(parent.width * this._positionPercentX);
            this._refreshHorizontalMargin();
        }
    },
    isPositionPercentYEnabled: function () {
        return this._usingPositionPercentY;
    },
    setPositionPercentYEnabled: function (isUsed) {
        this._usingPositionPercentY = isUsed;
        if (this._usingPositionPercentY)
            this._verticalEdge = ccui.LayoutComponent.verticalEdge.NONE;
    },
    getPositionPercentY: function () {
        return this._positionPercentY;
    },
    setPositionPercentY: function (percentMargin) {
        this._positionPercentY = percentMargin;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            this._owner.setPositionY(parent.height * this._positionPercentY);
            this._refreshVerticalMargin();
        }
    },
    getHorizontalEdge: function () {
        return this._horizontalEdge;
    },
    setHorizontalEdge: function (hEdge) {
        this._horizontalEdge = hEdge;
        if (this._horizontalEdge !== ccui.LayoutComponent.horizontalEdge.NONE)
            this._usingPositionPercentX = false;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var ownerPoint = this._owner.getPosition();
            var parentSize = parent.getContentSize();
            if (parentSize.width !== 0)
                this._positionPercentX = ownerPoint.x / parentSize.width;
            else {
                this._positionPercentX = 0;
                ownerPoint.x = 0;
                if (this._usingPositionPercentX)
                    this._owner.setPosition(ownerPoint);
            }
            this._refreshHorizontalMargin();
        }
    },
    getVerticalEdge: function () {
        return this._verticalEdge;
    },
    setVerticalEdge: function (vEdge) {
        this._verticalEdge = vEdge;
        if (this._verticalEdge !== ccui.LayoutComponent.verticalEdge.NONE)
            this._usingPositionPercentY = false;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var ownerPoint = this._owner.getPosition();
            var parentSize = parent.getContentSize();
            if (parentSize.height !== 0)
                this._positionPercentY = ownerPoint.y / parentSize.height;
            else {
                this._positionPercentY = 0;
                ownerPoint.y = 0;
                if (this._usingPositionPercentY)
                    this._owner.setPosition(ownerPoint);
            }
            this._refreshVerticalMargin();
        }
    },
    getLeftMargin: function () {
        return this._leftMargin;
    },
    setLeftMargin: function (margin) {
        this._leftMargin = margin;
    },
    getRightMargin: function () {
        return this._rightMargin;
    },
    setRightMargin: function (margin) {
        this._rightMargin = margin;
    },
    getTopMargin: function () {
        return this._topMargin;
    },
    setTopMargin: function (margin) {
        this._topMargin = margin;
    },
    getBottomMargin: function () {
        return this._bottomMargin;
    },
    setBottomMargin: function (margin) {
        this._bottomMargin = margin;
    },
    getSize: function () {
        return this.getOwner().getContentSize();
    },
    setSize: function (size) {
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var ownerSize = size, parentSize = parent.getContentSize();
            if (parentSize.width !== 0)
                this._percentWidth = ownerSize.width / parentSize.width;
            else {
                this._percentWidth = 0;
                if (this._usingPercentWidth)
                    ownerSize.width = 0;
            }
            if (parentSize.height !== 0)
                this._percentHeight = ownerSize.height / parentSize.height;
            else {
                this._percentHeight = 0;
                if (this._usingPercentHeight)
                    ownerSize.height = 0;
            }
            this._owner.setContentSize(ownerSize);
            this._refreshHorizontalMargin();
            this._refreshVerticalMargin();
        }
        else
            this._owner.setContentSize(size);
    },
    isPercentWidthEnabled: function () {
        return this._usingPercentWidth;
    },
    setPercentWidthEnabled: function (isUsed) {
        this._usingPercentWidth = isUsed;
        if (this._usingPercentWidth)
            this._usingStretchWidth = false;
    },
    getSizeWidth: function () {
        return this._owner.width;
    },
    setSizeWidth: function (width) {
        var ownerSize = this._owner.getContentSize();
        ownerSize.width = width;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var parentSize = parent.getContentSize();
            if (parentSize.width !== 0)
                this._percentWidth = ownerSize.width / parentSize.width;
            else {
                this._percentWidth = 0;
                if (this._usingPercentWidth)
                    ownerSize.width = 0;
            }
            this._owner.setContentSize(ownerSize);
            this._refreshHorizontalMargin();
        } else
            this._owner.setContentSize(ownerSize);
    },
    getPercentWidth: function () {
        return this._percentWidth;
    },
    setPercentWidth: function (percentWidth) {
        this._percentWidth = percentWidth;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var ownerSize = this._owner.getContentSize();
            ownerSize.width = parent.width * this._percentWidth;
            this._owner.setContentSize(ownerSize);
            this._refreshHorizontalMargin();
        }
    },
    isPercentHeightEnabled: function () {
        return this._usingPercentHeight;
    },
    setPercentHeightEnabled: function (isUsed) {
        this._usingPercentHeight = isUsed;
        if (this._usingPercentHeight)
            this._usingStretchHeight = false;
    },
    getSizeHeight: function () {
        return this._owner.height;
    },
    setSizeHeight: function (height) {
        var ownerSize = this._owner.getContentSize();
        ownerSize.height = height;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var parentSize = parent.getContentSize();
            if (parentSize.height !== 0)
                this._percentHeight = ownerSize.height / parentSize.height;
            else {
                this._percentHeight = 0;
                if (this._usingPercentHeight)
                    ownerSize.height = 0;
            }
            this._owner.setContentSize(ownerSize);
            this._refreshVerticalMargin();
        }
        else
            this._owner.setContentSize(ownerSize);
    },
    getPercentHeight: function () {
        return this._percentHeight;
    },
    setPercentHeight: function (percentHeight) {
        this._percentHeight = percentHeight;
        var parent = this._getOwnerParent();
        if (parent !== null) {
            var ownerSize = this._owner.getContentSize();
            ownerSize.height = parent.height * this._percentHeight;
            this._owner.setContentSize(ownerSize);
            this._refreshVerticalMargin();
        }
    },
    isStretchWidthEnabled: function () {
        return this._usingStretchWidth;
    },
    setStretchWidthEnabled: function (isUsed) {
        this._usingStretchWidth = isUsed;
        if (this._usingStretchWidth)
            this._usingPercentWidth = false;
    },
    isStretchHeightEnabled: function () {
        return this._usingStretchHeight;
    },
    setStretchHeightEnabled: function (isUsed) {
        this._usingStretchHeight = isUsed;
        if (this._usingStretchHeight)
            this._usingPercentHeight = false;
    },
    setPercentOnlyEnabled: function(enable){
        this._isPercentOnly = enable;
    },
    setActiveEnabled: function (enable) {
        this._actived = enable;
    },
    refreshLayout: function () {
        if(!this._actived)
            return;
        var parent = this._getOwnerParent();
        if (parent === null)
            return;
        var parentSize = parent.getContentSize(), locOwner = this._owner;
        var ownerAnchor = locOwner.getAnchorPoint(), ownerSize = locOwner.getContentSize();
        var ownerPosition = locOwner.getPosition();
        switch (this._horizontalEdge) {
            case ccui.LayoutComponent.horizontalEdge.NONE:
                if (this._usingStretchWidth && !this._isPercentOnly) {
                    ownerSize.width = parentSize.width * this._percentWidth;
                    ownerPosition.x = this._leftMargin + ownerAnchor.x * ownerSize.width;
                } else {
                    if (this._usingPositionPercentX)
                        ownerPosition.x = parentSize.width * this._positionPercentX;
                    if (this._usingPercentWidth)
                        ownerSize.width = parentSize.width * this._percentWidth;
                }
                break;
            case ccui.LayoutComponent.horizontalEdge.LEFT:
                if(this._isPercentOnly)
                    break;
                if (this._usingPercentWidth || this._usingStretchWidth)
                    ownerSize.width = parentSize.width * this._percentWidth;
                ownerPosition.x = this._leftMargin + ownerAnchor.x * ownerSize.width;
                break;
            case ccui.LayoutComponent.horizontalEdge.RIGHT:
                if(this._isPercentOnly)
                    break;
                if (this._usingPercentWidth || this._usingStretchWidth)
                    ownerSize.width = parentSize.width * this._percentWidth;
                ownerPosition.x = parentSize.width - (this._rightMargin + (1 - ownerAnchor.x) * ownerSize.width);
                break;
            case ccui.LayoutComponent.horizontalEdge.CENTER:
                if(this._isPercentOnly)
                    break;
                if (this._usingStretchWidth) {
                    ownerSize.width = parentSize.width - this._leftMargin - this._rightMargin;
                    if (ownerSize.width < 0)
                        ownerSize.width = 0;
                    ownerPosition.x = this._leftMargin + ownerAnchor.x * ownerSize.width;
                } else {
                    if (this._usingPercentWidth)
                        ownerSize.width = parentSize.width * this._percentWidth;
                    ownerPosition.x = parentSize.width * this._positionPercentX;
                }
                break;
            default:
                break;
        }
        switch (this._verticalEdge) {
            case ccui.LayoutComponent.verticalEdge.NONE:
                if (this._usingStretchHeight && !this._isPercentOnly) {
                    ownerSize.height = parentSize.height * this._percentHeight;
                    ownerPosition.y = this._bottomMargin + ownerAnchor.y * ownerSize.height;
                } else {
                    if (this._usingPositionPercentY)
                        ownerPosition.y = parentSize.height * this._positionPercentY;
                    if (this._usingPercentHeight)
                        ownerSize.height = parentSize.height * this._percentHeight;
                }
                break;
            case ccui.LayoutComponent.verticalEdge.BOTTOM:
                if(this._isPercentOnly)
                    break;
                if (this._usingPercentHeight || this._usingStretchHeight)
                    ownerSize.height = parentSize.height * this._percentHeight;
                ownerPosition.y = this._bottomMargin + ownerAnchor.y * ownerSize.height;
                break;
            case ccui.LayoutComponent.verticalEdge.TOP:
                if(this._isPercentOnly)
                    break;
                if (this._usingPercentHeight || this._usingStretchHeight)
                    ownerSize.height = parentSize.height * this._percentHeight;
                ownerPosition.y = parentSize.height - (this._topMargin + (1 - ownerAnchor.y) * ownerSize.height);
                break;
            case ccui.LayoutComponent.verticalEdge.CENTER:
                if(this._isPercentOnly)
                    break;
                if (this._usingStretchHeight) {
                    ownerSize.height = parentSize.height - this._topMargin - this._bottomMargin;
                    if (ownerSize.height < 0)
                        ownerSize.height = 0;
                    ownerPosition.y = this._bottomMargin + ownerAnchor.y * ownerSize.height;
                } else {
                    if(this._usingPercentHeight)
                        ownerSize.height = parentSize.height * this._percentHeight;
                    ownerPosition.y = parentSize.height * this._positionPercentY;
                }
                break;
            default:
                break;
        }
        locOwner.setPosition(ownerPosition);
        locOwner.setContentSize(ownerSize);
        if(locOwner instanceof ccui.PageView){
            locOwner.forceDoLayout();
            var layoutVector = locOwner.getPages();
            for(var i=0; i<layoutVector.length; i++){
                ccui.helper.doLayout(layoutVector[i]);
            }
        }else{
            ccui.helper.doLayout(locOwner);
        }
    },
    _getOwnerParent: function () {
        return this._owner ? this._owner.getParent() : null;
    },
    _refreshHorizontalMargin: function () {
        var parent = this._getOwnerParent();
        if (parent === null)
            return;
        var ownerPoint = this._owner.getPosition(), ownerAnchor = this._owner.getAnchorPoint();
        var ownerSize = this._owner.getContentSize(), parentSize = parent.getContentSize();
        this._leftMargin = ownerPoint.x - ownerAnchor.x * ownerSize.width;
        this._rightMargin = parentSize.width - (ownerPoint.x + (1 - ownerAnchor.x) * ownerSize.width);
    },
    _refreshVerticalMargin: function () {
        var parent = this._getOwnerParent();
        if (parent === null)
            return;
        var ownerPoint = this._owner.getPosition(), ownerAnchor = this._owner.getAnchorPoint();
        var ownerSize = this._owner.getContentSize(), parentSize = parent.getContentSize();
        this._bottomMargin = ownerPoint.y - ownerAnchor.y * ownerSize.height;
        this._topMargin = parentSize.height - (ownerPoint.y + (1 - ownerAnchor.y) * ownerSize.height);
    }
});
ccui.LayoutComponent.horizontalEdge = {NONE: 0, LEFT: 1, RIGHT: 2, CENTER: 3};
ccui.LayoutComponent.verticalEdge = {NONE: 0, BOTTOM: 1, TOP: 2, CENTER: 3};
ccui.LayoutComponent.NAME = "__ui_layout";
ccui.LayoutComponent.bindLayoutComponent = function (node) {
    var layout = node.getComponent(ccui.LayoutComponent.NAME);
    if (layout !== undefined)
        return layout;
    layout = new ccui.LayoutComponent();
    layout.init();
    node.addComponent(layout);
    if (!(node instanceof ccui.Widget)) {
        node.addEventListener && node.addEventListener("load", function () {
            layout.refreshLayout();
        }, this);
    }
    return layout;
};
cc.ComponentContainer = cc.Class.extend({
    _components:null,
    _owner:null,
    ctor:function(node){
        this._components = null;
        this._owner = node;
    },
    getComponent:function(name){
        if(!name)
            throw new Error("cc.ComponentContainer.getComponent(): name should be non-null");
        name = name.trim();
        if(!this._components){
            this._components = {};
        }
        return this._components[name];
    },
    add:function(component){
        if(!component)
             throw new Error("cc.ComponentContainer.add(): component should be non-null");
        if(component.getOwner()){
            cc.log("cc.ComponentContainer.add(): Component already added. It can't be added again");
            return false;
        }
        if(this._components == null){
            this._components = {};
            this._owner.scheduleUpdate();
        }
        var oldComponent = this._components[component.getName()];
        if(oldComponent){
            cc.log("cc.ComponentContainer.add(): Component already added. It can't be added again");
            return false;
        }
        component.setOwner(this._owner);
        this._components[component.getName()] = component;
        component.onEnter();
        return true;
    },
    remove:function(name){
        if(!name)
            throw new Error("cc.ComponentContainer.remove(): name should be non-null");
        if(!this._components)
            return false;
        if(name instanceof cc.Component)
            return this._removeByComponent(name);
        else {
            name = name.trim();
            return this._removeByComponent(this._components[name]);
        }
    },
    _removeByComponent:function(component){
        if(!component)
            return false;
        component.onExit();
        component.setOwner(null);
        delete this._components[component.getName()];
        return true;
    },
    removeAll:function(){
        if(!this._components)
            return;
        var locComponents = this._components;
        for(var selKey in locComponents){
            var selComponent = locComponents[selKey];
            selComponent.onExit();
            selComponent.setOwner(null);
            delete locComponents[selKey];
        }
        this._owner.unscheduleUpdate();
        this._components = null;
    },
    _alloc:function(){
        this._components = {};
    },
    visit:function(delta){
        if(!this._components)
            return;
        var locComponents = this._components;
        for(var selKey in locComponents)
             locComponents[selKey].update(delta);
    },
    isEmpty: function () {
        if (!this._components)
            return true;
        return this._components.length === 0;
    }
});
var ccs = ccs || {};
ccs.Class = ccs.Class || cc.Class;
ccs.Class.extend = ccs.Class.extend || cc.Class.extend;
ccs.Node = ccs.Node || cc.Node;
ccs.Node.extend = ccs.Node.extend || cc.Node.extend;
ccs.Sprite = ccs.Sprite || cc.Sprite;
ccs.Sprite.extend = ccs.Sprite.extend || cc.Sprite.extend;
ccs.Component = ccs.Component || cc.Component;
ccs.Component.extend = ccs.Component.extend || cc.Component.extend;
ccs.cocostudioVersion = "v1.3.0.0";
ccs.VERSION_COMBINED = 0.30;
ccs.VERSION_CHANGE_ROTATION_RANGE = 1.0;
ccs.VERSION_COLOR_READING = 1.1;
ccs.MAX_VERTEXZ_VALUE = 5000000.0;
ccs.ARMATURE_MAX_CHILD = 50.0;
ccs.ARMATURE_MAX_ZORDER = 100;
ccs.ARMATURE_MAX_COUNT = ((ccs.MAX_VERTEXZ_VALUE) / (ccs.ARMATURE_MAX_CHILD) / ccs.ARMATURE_MAX_ZORDER);
ccs.AUTO_ADD_SPRITE_FRAME_NAME_PREFIX = false;
ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT = false;
ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX = false;
ccs.armatureVersion = function(){
    return "v1.1.0.0";
};
ccs.CONST_VERSION = "version";
ccs.CONST_VERSION_2_0 = 2.0;
ccs.CONST_VERSION_COMBINED = 0.3;
ccs.CONST_ARMATURES = "armatures";
ccs.CONST_ARMATURE = "armature";
ccs.CONST_BONE = "b";
ccs.CONST_DISPLAY = "d";
ccs.CONST_ANIMATIONS = "animations";
ccs.CONST_ANIMATION = "animation";
ccs.CONST_MOVEMENT = "mov";
ccs.CONST_FRAME = "f";
ccs.CONST_TEXTURE_ATLAS = "TextureAtlas";
ccs.CONST_SUB_TEXTURE = "SubTexture";
ccs.CONST_SKELETON = "skeleton";
ccs.CONST_A_NAME = "name";
ccs.CONST_A_DURATION = "dr";
ccs.CONST_A_FRAME_INDEX = "fi";
ccs.CONST_A_DURATION_TO = "to";
ccs.CONST_A_DURATION_TWEEN = "drTW";
ccs.CONST_A_LOOP = "lp";
ccs.CONST_A_MOVEMENT_SCALE = "sc";
ccs.CONST_A_MOVEMENT_DELAY = "dl";
ccs.CONST_A_DISPLAY_INDEX = "dI";
ccs.CONST_A_PLIST = "plist";
ccs.CONST_A_PARENT = "parent";
ccs.CONST_A_SKEW_X = "kX";
ccs.CONST_A_SKEW_Y = "kY";
ccs.CONST_A_SCALE_X = "cX";
ccs.CONST_A_SCALE_Y = "cY";
ccs.CONST_A_Z = "z";
ccs.CONST_A_EVENT = "evt";
ccs.CONST_A_SOUND = "sd";
ccs.CONST_A_SOUND_EFFECT = "sdE";
ccs.CONST_A_TWEEN_EASING = "twE";
ccs.CONST_A_EASING_PARAM = "twEP";
ccs.CONST_A_TWEEN_ROTATE = "twR";
ccs.CONST_A_IS_ARMATURE = "isArmature";
ccs.CONST_A_DISPLAY_TYPE = "displayType";
ccs.CONST_A_MOVEMENT = "mov";
ccs.CONST_A_X = "x";
ccs.CONST_A_Y = "y";
ccs.CONST_A_COCOS2DX_X = "cocos2d_x";
ccs.CONST_A_COCOS2DX_Y = "cocos2d_y";
ccs.CONST_A_WIDTH = "width";
ccs.CONST_A_HEIGHT = "height";
ccs.CONST_A_PIVOT_X = "pX";
ccs.CONST_A_PIVOT_Y = "pY";
ccs.CONST_A_COCOS2D_PIVOT_X = "cocos2d_pX";
ccs.CONST_A_COCOS2D_PIVOT_Y = "cocos2d_pY";
ccs.CONST_A_BLEND_TYPE = "bd";
ccs.CONST_A_BLEND_SRC = "bd_src";
ccs.CONST_A_BLEND_DST = "bd_dst";
ccs.CONST_A_ALPHA = "a";
ccs.CONST_A_RED = "r";
ccs.CONST_A_GREEN = "g";
ccs.CONST_A_BLUE = "b";
ccs.CONST_A_ALPHA_OFFSET = "aM";
ccs.CONST_A_RED_OFFSET = "rM";
ccs.CONST_A_GREEN_OFFSET = "gM";
ccs.CONST_A_BLUE_OFFSET = "bM";
ccs.CONST_A_COLOR_TRANSFORM = "colorTransform";
ccs.CONST_A_TWEEN_FRAME = "tweenFrame";
ccs.CONST_CONTOUR = "con";
ccs.CONST_CONTOUR_VERTEX = "con_vt";
ccs.CONST_FL_NAN = "NaN";
ccs.CONST_FRAME_DATA = "frame_data";
ccs.CONST_MOVEMENT_BONE_DATA = "mov_bone_data";
ccs.CONST_MOVEMENT_DATA = "mov_data";
ccs.CONST_ANIMATION_DATA = "animation_data";
ccs.CONST_DISPLAY_DATA = "display_data";
ccs.CONST_SKIN_DATA = "skin_data";
ccs.CONST_BONE_DATA = "bone_data";
ccs.CONST_ARMATURE_DATA = "armature_data";
ccs.CONST_CONTOUR_DATA = "contour_data";
ccs.CONST_TEXTURE_DATA = "texture_data";
ccs.CONST_VERTEX_POINT = "vertex";
ccs.CONST_COLOR_INFO = "color";
ccs.CONST_CONFIG_FILE_PATH = "config_file_path";
ccs.CONST_CONTENT_SCALE = "content_scale";
ccs.DataInfo = function () {
    this.asyncStruct = null;
    this.configFileQueue = [];
    this.contentScale = 1;
    this.filename = "";
    this.baseFilePath = "";
    this.flashToolVersion = 0;
    this.cocoStudioVersion = 0
};
ccs.dataReaderHelper = {
    ConfigType: {
        DragonBone_XML: 0,
        CocoStudio_JSON: 1,
        CocoStudio_Binary: 2
    },
    _configFileList: [],
    _flashToolVersion: ccs.CONST_VERSION_2_0,
    _positionReadScale: 1,
    _asyncRefCount: 0,
    _asyncRefTotalCount: 0,
    _dataQueue: null,
    setPositionReadScale: function (scale) {
        this._positionReadScale = scale;
    },
    getPositionReadScale: function () {
        return this._positionReadScale;
    },
    addDataFromFile: function (filePath) {
        if (this._configFileList.indexOf(filePath) !== -1)
            return;
        this._configFileList.push(filePath);
        var basefilePath = this._initBaseFilePath(filePath);
        var str = cc.path.extname(filePath).toLowerCase();
        var dataInfo = new ccs.DataInfo();
        dataInfo.filename = filePath;
        dataInfo.basefilePath = basefilePath;
        if (str === ".xml")
            ccs.dataReaderHelper.addDataFromXML(filePath, dataInfo);
        else if (str === ".json" || str === ".exportjson")
            ccs.dataReaderHelper.addDataFromJson(filePath, dataInfo);
        else if(str === ".csb")
            ccs.dataReaderHelper.addDataFromBinaryCache(filePath, dataInfo);
    },
    addDataFromFileAsync: function (imagePath, plistPath, filePath, selector, target) {
        if (this._configFileList.indexOf(filePath) !== -1) {
            if (target && selector) {
                if (this._asyncRefTotalCount === 0 && this._asyncRefCount === 0)
                    this._asyncCallBack(selector,target, 1);
                else
                    this._asyncCallBack(selector, target, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount);
            }
            return;
        }
        this._asyncRefTotalCount++;
        this._asyncRefCount++;
        var self = this;
        var fun = function () {
            self.addDataFromFile(filePath);
            self._asyncRefCount--;
            self._asyncCallBack(selector,target, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount);
        };
        cc.director.getScheduler().schedule(fun, this, 0.1, false, 0, false, "armatrueDataHelper");
    },
    removeConfigFile: function (configFile) {
        var locFileList = this._configFileList;
        var len = locFileList.length;
        var it = locFileList[len];
        for (var i = 0;i<len; i++){
            if (locFileList[i] === configFile)
                it = i;
        }
        if (it !== locFileList[len])
            cc.arrayRemoveObject(locFileList, configFile);
    },
    addDataFromCache: function (skeleton, dataInfo) {
        if (!skeleton) {
            cc.log("XML error  or  XML is empty.");
            return;
        }
        dataInfo.flashToolVersion = parseFloat(skeleton.getAttribute(ccs.CONST_VERSION));
        var armaturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ARMATURES + " >  " + ccs.CONST_ARMATURE + "");
        var armatureDataManager = ccs.armatureDataManager, i;
        for (i = 0; i < armaturesXML.length; i++) {
            var armatureData = this.decodeArmature(armaturesXML[i], dataInfo);
            armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
        }
        var animationsXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ANIMATIONS + " >  " + ccs.CONST_ANIMATION + "");
        for (i = 0; i < animationsXML.length; i++) {
            var animationData = this.decodeAnimation(animationsXML[i], dataInfo);
            armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
        }
        var texturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_TEXTURE_ATLAS + " >  " + ccs.CONST_SUB_TEXTURE + "");
        for (i = 0; i < texturesXML.length; i++) {
            var textureData = this.decodeTexture(texturesXML[i], dataInfo);
            armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
        }
    },
    decodeArmature: function (armatureXML, dataInfo) {
        var armatureData = new ccs.ArmatureData();
        armatureData.init();
        armatureData.name = armatureXML.getAttribute(ccs.CONST_A_NAME);
        var bonesXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE + " > " + ccs.CONST_BONE);
        for (var i = 0; i < bonesXML.length; i++) {
            var boneXML = bonesXML[i];
            var parentName = boneXML.getAttribute(ccs.CONST_A_PARENT);
            var parentXML = null;
            if (parentName) {
                for (var j = 0; j < bonesXML.length; j++) {
                    parentXML = bonesXML[j];
                    if (parentName == bonesXML[j].getAttribute(ccs.CONST_A_NAME)) {
                        break;
                    }
                }
            }
            var boneData = this.decodeBone(boneXML, parentXML, dataInfo);
            armatureData.addBoneData(boneData);
        }
        return armatureData;
    },
    decodeArmatureFromJSON: function (json, dataInfo) {
        var armatureData = new ccs.ArmatureData();
        armatureData.init();
        var name = json[ccs.CONST_A_NAME];
        if (name) {
            armatureData.name = name;
        }
        dataInfo.cocoStudioVersion = armatureData.dataVersion = json[ccs.CONST_VERSION] || 0.1;
        var boneDataList = json[ccs.CONST_BONE_DATA];
        for (var i = 0; i < boneDataList.length; i++) {
            var boneData = this.decodeBoneFromJson(boneDataList[i], dataInfo);
            armatureData.addBoneData(boneData);
        }
        return armatureData;
    },
    decodeBone: function (boneXML, parentXML, dataInfo) {
        var boneData = new ccs.BoneData();
        boneData.init();
        boneData.name = boneXML.getAttribute(ccs.CONST_A_NAME);
        boneData.parentName = boneXML.getAttribute(ccs.CONST_A_PARENT) || "";
        boneData.zOrder = parseInt(boneXML.getAttribute(ccs.CONST_A_Z)) || 0;
        var displaysXML = boneXML.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_DISPLAY);
        for (var i = 0; i < displaysXML.length; i++) {
            var displayXML = displaysXML[i];
            var displayData = this.decodeBoneDisplay(displayXML, dataInfo);
            boneData.addDisplayData(displayData);
        }
        return boneData;
    },
    decodeBoneFromJson: function (json, dataInfo) {
        var boneData = new ccs.BoneData();
        boneData.init();
        this.decodeNodeFromJson(boneData, json, dataInfo);
        boneData.name = json[ccs.CONST_A_NAME] || "";
        boneData.parentName = json[ccs.CONST_A_PARENT] || "";
        var displayDataList = json[ccs.CONST_DISPLAY_DATA] || [];
        for (var i = 0; i < displayDataList.length; i++) {
            var locDisplayData = this.decodeBoneDisplayFromJson(displayDataList[i], dataInfo);
            boneData.addDisplayData(locDisplayData);
        }
        return boneData;
    },
    decodeBoneDisplay: function (displayXML, dataInfo) {
        var isArmature = parseFloat(displayXML.getAttribute(ccs.CONST_A_IS_ARMATURE)) || 0;
        var displayData = null;
        if (isArmature === 1) {
            displayData = new ccs.ArmatureDisplayData();
            displayData.displayType = ccs.DISPLAY_TYPE_ARMATURE;
        } else {
            displayData = new ccs.SpriteDisplayData();
            displayData.displayType = ccs.DISPLAY_TYPE_SPRITE;
        }
        var displayName = displayXML.getAttribute(ccs.CONST_A_NAME) || "";
        if (displayName) {
            displayData.displayName = displayName;
        }
        return displayData;
    },
    decodeBoneDisplayFromJson: function (json, dataInfo) {
        var displayType = json[ccs.CONST_A_DISPLAY_TYPE] || ccs.DISPLAY_TYPE_SPRITE;
        var displayData = null;
        switch (displayType) {
            case ccs.DISPLAY_TYPE_SPRITE:
                displayData = new ccs.SpriteDisplayData();
                var name = json[ccs.CONST_A_NAME];
                if(name != null){
                    displayData.displayName =  name;
                }
                var dicArray = json[ccs.CONST_SKIN_DATA] || [];
                var dic = dicArray[0];
                if (dic) {
                    var skinData = displayData.skinData;
                    skinData.x = dic[ccs.CONST_A_X] * this._positionReadScale;
                    skinData.y = dic[ccs.CONST_A_Y] * this._positionReadScale;
                    skinData.scaleX = dic[ccs.CONST_A_SCALE_X] == null ? 1 : dic[ccs.CONST_A_SCALE_X];
                    skinData.scaleY = dic[ccs.CONST_A_SCALE_Y] == null ? 1 : dic[ccs.CONST_A_SCALE_Y];
                    skinData.skewX = dic[ccs.CONST_A_SKEW_X] == null ? 1 : dic[ccs.CONST_A_SKEW_X];
                    skinData.skewY = dic[ccs.CONST_A_SKEW_Y] == null ? 1 : dic[ccs.CONST_A_SKEW_Y];
                    skinData.x *= dataInfo.contentScale;
                    skinData.y *= dataInfo.contentScale;
                }
                break;
            case ccs.DISPLAY_TYPE_ARMATURE:
                displayData = new ccs.ArmatureDisplayData();
                var name = json[ccs.CONST_A_NAME];
                if(name != null){
                    displayData.displayName = json[ccs.CONST_A_NAME];
                }
                break;
            case ccs.DISPLAY_TYPE_PARTICLE:
                displayData = new ccs.ParticleDisplayData();
                var plist = json[ccs.CONST_A_PLIST];
                if(plist != null){
                    if(dataInfo.asyncStruct){
                        displayData.displayName = dataInfo.asyncStruct.basefilePath + plist;
                    }else{
                        displayData.displayName = dataInfo.basefilePath + plist;
                    }
                }
                break;
            default:
                displayData = new ccs.SpriteDisplayData();
                break;
        }
        displayData.displayType = displayType;
        return displayData;
    },
    decodeAnimation: function (animationXML, dataInfo) {
        var aniData = new ccs.AnimationData();
        var name = animationXML.getAttribute(ccs.CONST_A_NAME);
        var armatureData = ccs.armatureDataManager.getArmatureData(name);
        aniData.name = name;
        var movementsXML = animationXML.querySelectorAll(ccs.CONST_ANIMATION + " > " + ccs.CONST_MOVEMENT);
        var movementXML = null;
        for (var i = 0; i < movementsXML.length; i++) {
            movementXML = movementsXML[i];
            var movementData = this.decodeMovement(movementXML, armatureData, dataInfo);
            aniData.addMovement(movementData);
        }
        return aniData;
    },
    decodeAnimationFromJson: function (json, dataInfo) {
        var aniData = new ccs.AnimationData();
        var name = json[ccs.CONST_A_NAME];
        if(name){
            aniData.name = json[ccs.CONST_A_NAME];
        }
        var movementDataList = json[ccs.CONST_MOVEMENT_DATA] || [];
        for (var i = 0; i < movementDataList.length; i++) {
            var locMovementData = this.decodeMovementFromJson(movementDataList[i], dataInfo);
            aniData.addMovement(locMovementData);
        }
        return aniData;
    },
    decodeMovement: function (movementXML, armatureData, dataInfo) {
        var movementData = new ccs.MovementData();
        movementData.name = movementXML.getAttribute(ccs.CONST_A_NAME);
        var duration, durationTo, durationTween, loop, tweenEasing = 0;
        duration = movementXML.getAttribute(ccs.CONST_A_DURATION);
        movementData.duration = duration == null ? 0 : parseFloat(duration);
        durationTo = movementXML.getAttribute(ccs.CONST_A_DURATION_TO);
        movementData.durationTo = durationTo == null ? 0 : parseFloat(durationTo);
        durationTween = movementXML.getAttribute(ccs.CONST_A_DURATION_TWEEN);
        movementData.durationTween = durationTween == null ? 0 : parseFloat(durationTween);
        loop = movementXML.getAttribute(ccs.CONST_A_LOOP);
        movementData.loop = loop ? Boolean(parseFloat(loop)) : true;
        var easing = movementXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
        if (easing) {
            if (easing != ccs.CONST_FL_NAN) {
                tweenEasing = easing == null ? 0 : parseFloat(easing);
                movementData.tweenEasing = tweenEasing === 2 ? ccs.TweenType.SINE_EASEINOUT : tweenEasing;
            } else
                movementData.tweenEasing = ccs.TweenType.LINEAR;
        }
        var movBonesXml = movementXML.querySelectorAll(ccs.CONST_MOVEMENT + " > " + ccs.CONST_BONE);
        var movBoneXml = null;
        for (var i = 0; i < movBonesXml.length; i++) {
            movBoneXml = movBonesXml[i];
            var boneName = movBoneXml.getAttribute(ccs.CONST_A_NAME);
            if (movementData.getMovementBoneData(boneName))
                continue;
            var boneData = armatureData.getBoneData(boneName);
            var parentName = boneData.parentName;
            var parentXML = null;
            if (parentName !== "") {
                for (var j = 0; j < movBonesXml.length; j++) {
                    parentXML = movBonesXml[j];
                    if (parentName === parentXML.getAttribute(ccs.CONST_A_NAME))
                        break;
                }
            }
            var moveBoneData = this.decodeMovementBone(movBoneXml, parentXML, boneData, dataInfo);
            movementData.addMovementBoneData(moveBoneData);
        }
        return movementData;
    },
    decodeMovementFromJson: function (json, dataInfo) {
        var movementData = new ccs.MovementData();
        movementData.loop = json[ccs.CONST_A_LOOP] == null ? false : json[ccs.CONST_A_LOOP];
        movementData.durationTween = json[ccs.CONST_A_DURATION_TWEEN] || 0;
        movementData.durationTo = json[ccs.CONST_A_DURATION_TO] || 0;
        movementData.duration = json[ccs.CONST_A_DURATION] || 0;
        if(json[ccs.CONST_A_DURATION] == null){
            movementData.scale = 1;
        }else{
            movementData.scale = json[ccs.CONST_A_MOVEMENT_SCALE] == null ? 1 : json[ccs.CONST_A_MOVEMENT_SCALE];
        }
        movementData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] == null ? ccs.TweenType.LINEAR : json[ccs.CONST_A_TWEEN_EASING];
        var name = json[ccs.CONST_A_NAME];
        if(name)
            movementData.name = name;
        var movementBoneList = json[ccs.CONST_MOVEMENT_BONE_DATA] || [];
        for (var i = 0; i < movementBoneList.length; i++) {
            var locMovementBoneData = this.decodeMovementBoneFromJson(movementBoneList[i], dataInfo);
            movementData.addMovementBoneData(locMovementBoneData);
        }
        return movementData;
    },
    decodeMovementBone: function (movBoneXml, parentXml, boneData, dataInfo) {
        var movBoneData = new ccs.MovementBoneData();
        movBoneData.init();
        var scale, delay;
        if (movBoneXml) {
            scale = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_SCALE)) || 0;
            movBoneData.scale = scale;
            delay = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_DELAY)) || 0;
            if (delay > 0)
                delay -= 1;
            movBoneData.delay = delay;
        }
        var length = 0, parentTotalDuration = 0,currentDuration = 0;
        var parentFrameXML = null,parentXMLList = [];
        if (parentXml != null) {
            var parentFramesXML = parentXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
            for (var i = 0; i < parentFramesXML.length; i++)
                parentXMLList.push(parentFramesXML[i]);
            length = parentXMLList.length;
        }
        movBoneData.name = movBoneXml.getAttribute(ccs.CONST_A_NAME);
        var framesXML = movBoneXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
        var j = 0, totalDuration = 0;
        for (var ii = 0; ii < framesXML.length; ii++) {
            var frameXML = framesXML[ii];
            if (parentXml) {
                while (j < length && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) {
                    parentFrameXML = parentXMLList[j];
                    parentTotalDuration += currentDuration;
                    currentDuration = parseFloat(parentFrameXML.getAttribute(ccs.CONST_A_DURATION));
                    j++;
                }
            }
            var boneFrameData = this.decodeFrame(frameXML, parentFrameXML, boneData, dataInfo);
            movBoneData.addFrameData(boneFrameData);
            boneFrameData.frameID = totalDuration;
            totalDuration += boneFrameData.duration;
            movBoneData.duration = totalDuration;
        }
        var frames = movBoneData.frameList, pi = Math.PI;
        for (var i = frames.length - 1; i >= 0; i--) {
            if (i > 0) {
                var difSkewX = frames[i].skewX - frames[i - 1].skewX;
                var difSkewY = frames[i].skewY - frames[i - 1].skewY;
                if (difSkewX < -pi || difSkewX > pi) {
                    frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
                }
                if (difSkewY < -pi || difSkewY > pi) {
                    frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
                }
            }
        }
        var frameData = new ccs.FrameData();
        frameData.copy(movBoneData.frameList[movBoneData.frameList.length - 1]);
        frameData.frameID = movBoneData.duration;
        movBoneData.addFrameData(frameData);
        return movBoneData;
    },
    decodeMovementBoneFromJson: function (json, dataInfo) {
        var movementBoneData = new ccs.MovementBoneData();
        movementBoneData.init();
        movementBoneData.delay = json[ccs.CONST_A_MOVEMENT_DELAY] || 0;
        var name = json[ccs.CONST_A_NAME];
        if(name)
            movementBoneData.name = name;
        var framesData = json[ccs.CONST_FRAME_DATA] || [];
        var length = framesData.length;
        for (var i = 0; i < length; i++) {
            var dic = json[ccs.CONST_FRAME_DATA][i];
            var frameData = this.decodeFrameFromJson(dic, dataInfo);
            movementBoneData.addFrameData(frameData);
            if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED){
                frameData.frameID = movementBoneData.duration;
                movementBoneData.duration += frameData.duration;
            }
        }
        if (dataInfo.cocoStudioVersion < ccs.VERSION_CHANGE_ROTATION_RANGE) {
            var frames = movementBoneData.frameList;
            var pi = Math.PI;
            for (var i = frames.length - 1; i >= 0; i--) {
                if (i > 0) {
                    var difSkewX = frames[i].skewX - frames[i - 1].skewX;
                    var difSkewY = frames[i].skewY - frames[i - 1].skewY;
                    if (difSkewX < -pi || difSkewX > pi) {
                        frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
                    }
                    if (difSkewY < -pi || difSkewY > pi) {
                        frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
                    }
                }
            }
        }
        if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
            if (movementBoneData.frameList.length > 0) {
                var frameData = new ccs.FrameData();
                frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]);
                movementBoneData.addFrameData(frameData);
                frameData.frameID = movementBoneData.duration;
            }
        }
        return movementBoneData;
    },
    decodeFrame: function (frameXML, parentFrameXml, boneData, dataInfo) {
        var x = 0, y = 0, scale_x = 0, scale_y = 0, skew_x = 0, skew_y = 0, tweenRotate = 0;
        var duration = 0, displayIndex = 0, zOrder = 0, tweenEasing = 0, blendType = 0;
        var frameData = new ccs.FrameData();
        frameData.strMovement = frameXML.getAttribute(ccs.CONST_A_MOVEMENT) || "";
        frameData.movement = frameData.strMovement;
        frameData.strEvent = frameXML.getAttribute(ccs.CONST_A_EVENT) || "";
        frameData.event = frameData.strEvent;
        frameData.strSound = frameXML.getAttribute(ccs.CONST_A_SOUND) || "";
        frameData.sound = frameData.strSound;
        frameData.strSoundEffect = frameXML.getAttribute(ccs.CONST_A_SOUND_EFFECT) || "";
        frameData.soundEffect = frameData.strSoundEffect;
        var isTween = frameXML.getAttribute(ccs.CONST_A_TWEEN_FRAME);
        frameData.isTween = !(isTween !== undefined && (isTween === "false" || isTween === "0"));
        if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
            x = frameXML.getAttribute(ccs.CONST_A_COCOS2DX_X);
            if(x){
                frameData.x = parseFloat(x);
                frameData.x *= this._positionReadScale;
            }
            y = frameXML.getAttribute(ccs.CONST_A_COCOS2DX_Y);
            if(y){
                frameData.y = -parseFloat(y);
                frameData.y *= this._positionReadScale;
            }
        } else {
            x = frameXML.getAttribute(ccs.CONST_A_X);
            if(x) {
                frameData.x = parseFloat(x);
                frameData.x *= this._positionReadScale;
            }
            y = frameXML.getAttribute(ccs.CONST_A_Y);
            if(y) {
                frameData.y = -parseFloat(y);
                frameData.y *= this._positionReadScale;
            }
        }
        scale_x = frameXML.getAttribute(ccs.CONST_A_SCALE_X);
        if( scale_x != null )
            frameData.scaleX = parseFloat(scale_x);
        scale_y = frameXML.getAttribute(ccs.CONST_A_SCALE_Y);
        if( scale_y != null )
            frameData.scaleY = parseFloat(scale_y);
        skew_x = frameXML.getAttribute(ccs.CONST_A_SKEW_X);
        if( skew_x != null )
            frameData.skewX = cc.degreesToRadians(parseFloat(skew_x));
        skew_y = frameXML.getAttribute(ccs.CONST_A_SKEW_Y);
        if( skew_y != null )
            frameData.skewY = cc.degreesToRadians(-parseFloat(skew_y));
        duration = frameXML.getAttribute(ccs.CONST_A_DURATION);
        if( duration != null )
            frameData.duration = parseFloat(duration);
        displayIndex = frameXML.getAttribute(ccs.CONST_A_DISPLAY_INDEX);
        if( displayIndex != null )
            frameData.displayIndex = parseFloat(displayIndex);
        zOrder = frameXML.getAttribute(ccs.CONST_A_Z);
        if( zOrder != null )
            frameData.zOrder = parseInt(zOrder);
        tweenRotate = frameXML.getAttribute(ccs.CONST_A_TWEEN_ROTATE);
        if( tweenRotate != null )
            frameData.tweenRotate = parseFloat(tweenRotate);
        blendType = frameXML.getAttribute(ccs.CONST_A_BLEND_TYPE);
        if ( blendType != null ) {
            var blendFunc = frameData.blendFunc;
            switch (blendType) {
                case ccs.BLEND_TYPE_NORMAL:
                    blendFunc.src = cc.BLEND_SRC;
                    blendFunc.dst = cc.BLEND_DST;
                    break;
                case ccs.BLEND_TYPE_ADD:
                    blendFunc.src = cc.SRC_ALPHA;
                    blendFunc.dst = cc.ONE;
                    break;
                case ccs.BLEND_TYPE_MULTIPLY:
                    blendFunc.src = cc.DST_COLOR;
                    blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
                    break;
                case ccs.BLEND_TYPE_SCREEN:
                    blendFunc.src = cc.ONE;
                    blendFunc.dst = cc.ONE_MINUS_DST_COLOR;
                    break;
                default:
                    frameData.blendFunc.src = cc.BLEND_SRC;
                    frameData.blendFunc.dst = cc.BLEND_DST;
                    break;
            }
        }
        var colorTransformXML = frameXML.querySelectorAll(ccs.CONST_FRAME + " > " + ccs.CONST_A_COLOR_TRANSFORM);
        if (colorTransformXML && colorTransformXML.length > 0) {
            colorTransformXML = colorTransformXML[0];
            var alpha, red, green, blue;
            var alphaOffset, redOffset, greenOffset, blueOffset;
            alpha = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA)) || 0;
            red = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED)) || 0;
            green = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN)) || 0;
            blue = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE)) || 0;
            alphaOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA_OFFSET)) || 0;
            redOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED_OFFSET)) || 0;
            greenOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN_OFFSET)) || 0;
            blueOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE_OFFSET)) || 0;
            frameData.a = 2.55 * alphaOffset + alpha;
            frameData.r = 2.55 * redOffset + red;
            frameData.g = 2.55 * greenOffset + green;
            frameData.b = 2.55 * blueOffset + blue;
            frameData.isUseColorInfo = true;
        }
        var _easing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
        if(_easing != null) {
            if(_easing != ccs.CONST_FL_NAN){
                tweenEasing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
                if( tweenEasing )
                    frameData.tweenEasing = (tweenEasing === 2) ? ccs.TweenType.SINE_EASEINOUT : tweenEasing;
            } else
                frameData.tweenEasing = ccs.TweenType.LINEAR;
        }
        if (parentFrameXml) {
            var helpNode = new ccs.BaseData();
            if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
                helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_X));
                helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_Y));
            } else {
                helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_X));
                helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_Y));
            }
            helpNode.skewX = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_X));
            helpNode.skewY = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_Y));
            helpNode.y = -helpNode.y;
            helpNode.skewX = cc.degreesToRadians(helpNode.skewX);
            helpNode.skewY = cc.degreesToRadians(-helpNode.skewY);
            ccs.TransformHelp.transformFromParent(frameData, helpNode);
        }
        return frameData;
    },
    decodeFrameFromJson: function (json, dataInfo) {
        var frameData = new ccs.FrameData();
        this.decodeNodeFromJson(frameData, json, dataInfo);
        frameData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.LINEAR;
        frameData.displayIndex = json[ccs.CONST_A_DISPLAY_INDEX];
        var bd_src = json[ccs.CONST_A_BLEND_SRC] == null ? cc.BLEND_SRC : json[ccs.CONST_A_BLEND_SRC];
        var bd_dst = json[ccs.CONST_A_BLEND_DST] == null ? cc.BLEND_DST : json[ccs.CONST_A_BLEND_DST];
        frameData.blendFunc.src = bd_src;
        frameData.blendFunc.dst = bd_dst;
        frameData.isTween = json[ccs.CONST_A_TWEEN_FRAME] == null ? true : json[ccs.CONST_A_TWEEN_FRAME];
        var event = json[ccs.CONST_A_EVENT];
        if(event != null){
            frameData.strEvent = event;
            frameData.event = event;
        }
        if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED)
            frameData.duration = json[ccs.CONST_A_DURATION] == null ? 1 : json[ccs.CONST_A_DURATION];
        else
            frameData.frameID = json[ccs.CONST_A_FRAME_INDEX];
        var twEPs = json[ccs.CONST_A_EASING_PARAM] || [];
        for (var i = 0; i < twEPs.length; i++) {
            frameData.easingParams[i] = twEPs[i];
        }
        return frameData;
    },
    decodeTexture: function (textureXML, dataInfo) {
        var textureData = new ccs.TextureData();
        textureData.init();
        if (textureXML.getAttribute(ccs.CONST_A_NAME)) {
            textureData.name = textureXML.getAttribute(ccs.CONST_A_NAME);
        }
        var px, py;
        if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
            px = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_X)) || 0;
            py = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_Y)) || 0;
        } else {
            px = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_X)) || 0;
            py = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_Y)) || 0;
        }
        var width = parseFloat(textureXML.getAttribute(ccs.CONST_A_WIDTH)) || 0;
        var height = parseFloat(textureXML.getAttribute(ccs.CONST_A_HEIGHT)) || 0;
        var anchorPointX = px / width;
        var anchorPointY = (height - py) / height;
        textureData.pivotX = anchorPointX;
        textureData.pivotY = anchorPointY;
        var contoursXML = textureXML.querySelectorAll(ccs.CONST_SUB_TEXTURE + " > " + ccs.CONST_CONTOUR);
        for (var i = 0; i < contoursXML.length; i++) {
            textureData.addContourData(this.decodeContour(contoursXML[i], dataInfo));
        }
        return textureData;
    },
    decodeTextureFromJson: function (json) {
        var textureData = new ccs.TextureData();
        textureData.init();
        var name = json[ccs.CONST_A_NAME];
        if(name != null)
            textureData.name = name;
        textureData.width = json[ccs.CONST_A_WIDTH] || 0;
        textureData.height = json[ccs.CONST_A_HEIGHT] || 0;
        textureData.pivotX = json[ccs.CONST_A_PIVOT_X] || 0;
        textureData.pivotY = json[ccs.CONST_A_PIVOT_Y] || 0;
        var contourDataList = json[ccs.CONST_CONTOUR_DATA] || [];
        for (var i = 0; i < contourDataList.length; i++) {
            textureData.contourDataList.push(this.decodeContourFromJson(contourDataList[i]));
        }
        return textureData;
    },
    decodeContour: function (contourXML, dataInfo) {
        var contourData = new ccs.ContourData();
        contourData.init();
        var vertexDatasXML = contourXML.querySelectorAll(ccs.CONST_CONTOUR + " > " + ccs.CONST_CONTOUR_VERTEX);
        var vertexDataXML;
        for (var i = 0; i < vertexDatasXML.length; i++) {
            vertexDataXML = vertexDatasXML[i];
            var vertex = cc.p(0, 0);
            vertex.x = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_X)) || 0;
            vertex.y = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_Y)) || 0;
            vertex.y = - vertex.y;
            contourData.vertexList.push(vertex);
        }
        return contourData;
    },
    decodeContourFromJson: function (json) {
        var contourData = new ccs.ContourData();
        contourData.init();
        var vertexPointList = json[ccs.CONST_VERTEX_POINT] || [];
        var len = vertexPointList.length;
        for (var i = 0; i < len; i++) {
            var dic = vertexPointList[i];
            var vertex = cc.p(0, 0);
            vertex.x = dic[ccs.CONST_A_X] || 0;
            vertex.y = dic[ccs.CONST_A_Y] || 0;
            contourData.vertexList.push(vertex);
        }
        return contourData;
    },
    addDataFromJsonCache: function (dic, dataInfo) {
        dataInfo.contentScale = dic[ccs.CONST_CONTENT_SCALE] == null ? 1 : dic[ccs.CONST_CONTENT_SCALE];
        var armatureDataArr = dic[ccs.CONST_ARMATURE_DATA] || [], i;
        var armatureData;
        for (i = 0; i < armatureDataArr.length; i++) {
            armatureData = this.decodeArmatureFromJSON(armatureDataArr[i], dataInfo);
            ccs.armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
        }
        var animationDataArr = dic[ccs.CONST_ANIMATION_DATA] || [];
        var animationData;
        for (i = 0; i < animationDataArr.length; i++) {
            animationData = this.decodeAnimationFromJson(animationDataArr[i], dataInfo);
            ccs.armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
        }
        var textureDataArr = dic[ccs.CONST_TEXTURE_DATA] || [];
        var textureData;
        for (i = 0; i < textureDataArr.length; i++) {
            textureData = this.decodeTextureFromJson(textureDataArr[i], dataInfo);
            ccs.armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
        }
        var autoLoad = dataInfo.asyncStruct == null ? ccs.armatureDataManager.isAutoLoadSpriteFile() : dataInfo.asyncStruct.autoLoadSpriteFile;
        if (autoLoad) {
            var configFiles = dic[ccs.CONST_CONFIG_FILE_PATH] || [];
            var locFilePath, locPos, locPlistPath, locImagePath;
            for (i = 0; i < configFiles.length; i++) {
                locFilePath = configFiles[i];
                locPos = locFilePath.lastIndexOf(".");
                locFilePath = locFilePath.substring(0, locPos);
                locPlistPath = dataInfo.basefilePath + locFilePath + ".plist";
                locImagePath = dataInfo.basefilePath + locFilePath + ".png";
                ccs.armatureDataManager.addSpriteFrameFromFile(locPlistPath, locImagePath, dataInfo.filename);
            }
        }
        armatureData = null;
        animationData = null;
    },
    decodeNodeFromJson: function (node, json, dataInfo) {
        node.x = json[ccs.CONST_A_X] * this._positionReadScale;
        node.y = json[ccs.CONST_A_Y] * this._positionReadScale;
        node.x *= dataInfo.contentScale;
        node.y *= dataInfo.contentScale;
        node.zOrder = json[ccs.CONST_A_Z];
        node.skewX = json[ccs.CONST_A_SKEW_X] || 0;
        node.skewY = json[ccs.CONST_A_SKEW_Y] || 0;
        node.scaleX = json[ccs.CONST_A_SCALE_X] == null ? 1 : json[ccs.CONST_A_SCALE_X];
        node.scaleY = json[ccs.CONST_A_SCALE_Y] == null ? 1 : json[ccs.CONST_A_SCALE_Y];
        var colorDic;
        if (dataInfo.cocoStudioVersion < ccs.VERSION_COLOR_READING) {
            colorDic = json[0];
            if (colorDic){
                node.a = colorDic[ccs.CONST_A_ALPHA] == null ? 255 : colorDic[ccs.CONST_A_ALPHA];
                node.r = colorDic[ccs.CONST_A_RED] == null ? 255 : colorDic[ccs.CONST_A_RED];
                node.g = colorDic[ccs.CONST_A_GREEN] == null ? 255 : colorDic[ccs.CONST_A_GREEN];
                node.b = colorDic[ccs.CONST_A_BLUE] == null ? 255 : colorDic[ccs.CONST_A_BLUE];
                node.isUseColorInfo = true;
            }
        } else {
            colorDic = json[ccs.CONST_COLOR_INFO] || null;
            if (colorDic){
                node.a = colorDic[ccs.CONST_A_ALPHA] == null ? 255 : colorDic[ccs.CONST_A_ALPHA];
                node.r = colorDic[ccs.CONST_A_RED] == null ? 255 : colorDic[ccs.CONST_A_RED];
                node.g = colorDic[ccs.CONST_A_GREEN] == null ? 255 : colorDic[ccs.CONST_A_GREEN];
                node.b = colorDic[ccs.CONST_A_BLUE] == null ? 255 : colorDic[ccs.CONST_A_BLUE];
                node.isUseColorInfo = true;
            }
        }
    },
    clear: function () {
        this._configFileList = [];
        this._asyncRefCount = 0;
        this._asyncRefTotalCount = 0;
    },
    _asyncCallBack: function (selector, target, percent) {
        if(selector && cc.isFunction(selector))
            selector.call(target, percent);
        if(target && selector && typeof selector === 'string')
            target[selector](percent);
    },
    _initBaseFilePath: function (filePath) {
        var path = filePath;
        var pos = path.lastIndexOf("/");
        if (pos > -1)
            path = path.substr(0, pos + 1);
        else
            path = "";
        return path;
    },
    addDataFromXML: function (xml, dataInfo) {
        var xmlStr = cc.loader.getRes(xml);
        if (!xmlStr) throw new Error("Please load the resource first : " + xml);
        var skeletonXML = cc.saxParser.parse(xmlStr);
        var skeleton = skeletonXML.documentElement;
        if (skeleton)
            this.addDataFromCache(skeleton, dataInfo);
    },
    addDataFromJson: function (filePath, dataInfo) {
        var fileContent = cc.loader.getRes(filePath);
        this.addDataFromJsonCache(fileContent, dataInfo);
    }
};
ccs.spriteFrameCacheHelper =  {
    _textureAtlasDic:{},
    _imagePaths:[],
    addSpriteFrameFromFile:function (plistPath, imagePath) {
        cc.spriteFrameCache.addSpriteFrames(plistPath, imagePath);
    },
    getTextureAtlasWithTexture:function (texture) {
        return null;
        var textureName = texture.getName();
        var atlas = this._textureAtlasDic[textureName];
        if (atlas == null) {
            atlas = new cc.TextureAtlas(texture, 20);
            this._textureAtlasDic[textureName] = atlas;
        }
        return atlas;
    },
    clear: function () {
        this._textureAtlasDic = {};
        this._imagePaths = [];
    }
};
ccs.TransformHelp = ccs.TransformHelp || ccs.Class.extend({});
ccs.TransformHelp.helpMatrix1 = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
ccs.TransformHelp.helpMatrix2 = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
ccs.TransformHelp.helpPoint1 = cc.p(0, 0);
ccs.TransformHelp.helpPoint2 = cc.p(0, 0);
ccs.TransformHelp.helpParentNode = {};
ccs.TransformHelp.transformFromParent = function (bone, parentNode) {
    this.nodeToMatrix(bone, this.helpMatrix1);
    this.nodeToMatrix(parentNode, this.helpMatrix2);
    this.helpMatrix2 = cc.affineTransformInvert(this.helpMatrix2);
    this.helpMatrix1 = cc.affineTransformConcat(this.helpMatrix1, this.helpMatrix2);
    this.matrixToNode(this.helpMatrix1, bone);
};
ccs.TransformHelp.transformToParent = function(node, parentNode){
    this.nodeToMatrix(node, this.helpMatrix1);
    this.nodeToMatrix(parentNode, this.helpMatrix2);
    this.helpMatrix1 = cc.affineTransformConcat(this.helpMatrix1, this.helpMatrix2);
    this.matrixToNode(this.helpMatrix1, node);
};
ccs.TransformHelp.transformFromParentWithoutScale = function(node, parentNode){
    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);
};
ccs.TransformHelp.nodeToMatrix = function (node, matrix) {
    if (node.skewX === -node.skewY) {
        var sine = Math.sin(node.skewX);
        var cosine = Math.cos(node.skewX);
        matrix.a = node.scaleX * cosine;
        matrix.b = node.scaleX * -sine;
        matrix.c = node.scaleY * sine;
        matrix.d = node.scaleY * cosine;
    } else {
        matrix.a = node.scaleX * Math.cos(node.skewY);
        matrix.b = node.scaleX * Math.sin(node.skewY);
        matrix.c = node.scaleY * Math.sin(node.skewX);
        matrix.d = node.scaleY * Math.cos(node.skewX);
    }
    matrix.tx = node.x;
    matrix.ty = node.y;
};
ccs.TransformHelp.matrixToNode = function (matrix, node) {
    this.helpPoint1.x = 0;
    this.helpPoint1.y = 1;
    this.helpPoint1 = cc.pointApplyAffineTransform(this.helpPoint1, matrix);
    this.helpPoint1.x -= matrix.tx;
    this.helpPoint1.y -= matrix.ty;
    this.helpPoint2.x = 1;
    this.helpPoint2.y = 0;
    this.helpPoint2 = cc.pointApplyAffineTransform(this.helpPoint2, matrix);
    this.helpPoint2.x -= matrix.tx;
    this.helpPoint2.y -= matrix.ty;
    node.skewX = -(Math.atan2(this.helpPoint1.y, this.helpPoint1.x) - 1.5707964);
    node.skewY = Math.atan2(this.helpPoint2.y, this.helpPoint2.x);
    node.scaleX = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b);
    node.scaleY = Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d);
    node.x = matrix.tx;
    node.y = matrix.ty;
};
ccs.TransformHelp.nodeConcat = function (target, source) {
    target.x += source.x;
    target.y += source.y;
    target.skewX += source.skewX;
    target.skewY += source.skewY;
    target.scaleX += source.scaleX;
    target.scaleY += source.scaleY;
};
ccs.TransformHelp.nodeSub = function (target, source) {
    target.x -= source.x;
    target.y -= source.y;
    target.skewX -= source.skewX;
    target.skewY -= source.skewY;
    target.scaleX -= source.scaleX;
    target.scaleY -= source.scaleY;
};
ccs.TweenType = {
    CUSTOM_EASING: -1,
    LINEAR: 0,
    SINE_EASEIN: 1,
    SINE_EASEOUT: 2,
    SINE_EASEINOUT: 3,
    QUAD_EASEIN: 4,
    QUAD_EASEOUT: 5,
    QUAD_EASEINOUT: 6,
    CUBIC_EASEIN: 7,
    CUBIC_EASEOUT: 8,
    CUBIC_EASEINOUT: 9,
    QUART_EASEIN: 10,
    QUART_EASEOUT: 11,
    QUART_EASEINOUT: 12,
    QUINT_EASEIN: 13,
    QUINT_EASEOUT: 14,
    QUINT_EASEINOUT: 15,
    EXPO_EASEIN: 16,
    EXPO_EASEOUT: 17,
    EXPO_EASEINOUT: 18,
    CIRC_EASEIN: 19,
    CIRC_EASEOUT: 20,
    CIRC_EASEINOUT: 21,
    ELASTIC_EASEIN: 22,
    ELASTIC_EASEOUT: 23,
    ELASTIC_EASEINOUT: 24,
    BACK_EASEIN: 25,
    BACK_EASEOUT: 26,
    BACK_EASEINOUT: 27,
    BOUNCE_EASEIN: 28,
    BOUNCE_EASEOUT: 29,
    BOUNCE_EASEINOUT: 30,
    TWEEN_EASING_MAX: 10000
};
ccs.TweenFunction = ccs.TweenFunction || ccs.Class.extend({});
ccs.DOUBLE_PI = ccs.M_PI_X_2 = Math.PI * 2;
ccs.HALF_PI = ccs.M_PI_2 = Math.PI / 2;
ccs.M_PI = Math.PI;
ccs.TweenFunction.tweenTo = function (time, type, easingParam) {
    var delta = 0;
    switch (type) {
        case ccs.TweenType.CUSTOM_EASING:
            delta = this.customEase(time, easingParam);
            break;
        case ccs.TweenType.LINEAR:
            delta = this.linear(time);
            break;
        case ccs.TweenType.SINE_EASEIN:
            delta = this.sineEaseIn(time);
            break;
        case ccs.TweenType.SINE_EASEOUT:
            delta = this.sineEaseOut(time);
            break;
        case ccs.TweenType.SINE_EASEINOUT:
            delta = this.sineEaseInOut(time);
            break;
        case ccs.TweenType.QUAD_EASEIN:
            delta = this.quadEaseIn(time);
            break;
        case ccs.TweenType.QUAD_EASEOUT:
            delta = this.quadEaseOut(time);
            break;
        case ccs.TweenType.QUAD_EASEINOUT:
            delta = this.quadEaseInOut(time);
            break;
        case ccs.TweenType.CUBIC_EASEIN:
            delta = this.cubicEaseIn(time);
            break;
        case ccs.TweenType.CUBIC_EASEOUT:
            delta = this.cubicEaseOut(time);
            break;
        case ccs.TweenType.CUBIC_EASEINOUT:
            delta = this.cubicEaseInOut(time);
            break;
        case ccs.TweenType.QUART_EASEIN:
            delta = this.quartEaseIn(time);
            break;
        case ccs.TweenType.QUART_EASEOUT:
            delta = this.quartEaseOut(time);
            break;
        case ccs.TweenType.QUART_EASEINOUT:
            delta = this.quartEaseInOut(time);
            break;
        case ccs.TweenType.QUINT_EASEIN:
            delta = this.quintEaseIn(time);
            break;
        case ccs.TweenType.QUINT_EASEOUT:
            delta = this.quintEaseOut(time);
            break;
        case ccs.TweenType.QUINT_EASEINOUT:
            delta = this.quintEaseInOut(time);
            break;
        case ccs.TweenType.EXPO_EASEIN:
            delta = this.expoEaseIn(time);
            break;
        case ccs.TweenType.EXPO_EASEOUT:
            delta = this.expoEaseOut(time);
            break;
        case ccs.TweenType.EXPO_EASEINOUT:
            delta = this.expoEaseInOut(time);
            break;
        case ccs.TweenType.CIRC_EASEIN:
            delta = this.circEaseIn(time);
            break;
        case ccs.TweenType.CIRC_EASEOUT:
            delta = this.circEaseOut(time);
            break;
        case ccs.TweenType.CIRC_EASEINOUT:
            delta = this.circEaseInOut(time);
            break;
        case ccs.TweenType.ELASTIC_EASEIN:
            var period = 0.3;
            if(null != easingParam && easingParam.length > 0){
                period = easingParam[0];
            }
            delta = this.elasticEaseIn(time, period);
            break;
        case ccs.TweenType.ELASTIC_EASEOUT:
            var period = 0.3;
            if(null != easingParam && easingParam.length > 0){
                period = easingParam[0];
            }
            delta = this.elasticEaseOut(time, period);
            break;
        case ccs.TweenType.ELASTIC_EASEINOUT:
            var period = 0.3;
            if(null != easingParam && easingParam.length > 0){
                period = easingParam[0];
            }
            delta = this.elasticEaseInOut(time, period);
            break;
        case ccs.TweenType.BACK_EASEIN:
            delta = this.backEaseIn(time);
            break;
        case ccs.TweenType.BACK_EASEOUT:
            delta = this.backEaseOut(time);
            break;
        case ccs.TweenType.BACK_EASEINOUT:
            delta = this.backEaseInOut(time);
            break;
        case ccs.TweenType.BOUNCE_EASEIN:
            delta = this.bounceEaseIn(time);
            break;
        case ccs.TweenType.BOUNCE_EASEOUT:
            delta = this.bounceEaseOut(time);
            break;
        case ccs.TweenType.BOUNCE_EASEINOUT:
            delta = this.bounceEaseInOut(time);
            break;
        default:
            delta = this.sineEaseInOut(time);
            break;
    }
    return delta;
};
ccs.TweenFunction.linear = function (time) {
    return time;
};
ccs.TweenFunction.sineEaseIn = function (time) {
    return -1 * Math.cos(time * ccs.HALF_PI) + 1;
};
ccs.TweenFunction.sineEaseOut = function (time) {
    return Math.sin(time * ccs.HALF_PI);
};
ccs.TweenFunction.sineEaseInOut = function (time) {
    return -0.5 * (Math.cos(ccs.M_PI * time) - 1);
};
ccs.TweenFunction.quadEaseIn = function (time) {
    return time * time;
};
ccs.TweenFunction.quadEaseOut = function (time) {
    return -1 * time * (time - 2);
};
ccs.TweenFunction.quadEaseInOut = function (time) {
    time = time * 2;
    if (time < 1)
        return 0.5 * time * time;
    --time;
    return -0.5 * (time * (time - 2) - 1);
};
ccs.TweenFunction.cubicEaseIn = function (time) {
    return time * time * time;
};
ccs.TweenFunction.cubicEaseOut = function (time) {
    time -= 1;
    return (time * time * time + 1);
};
ccs.TweenFunction.cubicEaseInOut = function (time) {
    time = time * 2;
    if (time < 1)
        return 0.5 * time * time * time;
    time -= 2;
    return 0.5 * (time * time * time + 2);
};
ccs.TweenFunction.quartEaseIn = function (time) {
    return time * time * time * time;
};
ccs.TweenFunction.quartEaseOut = function (time) {
    time -= 1;
    return -(time * time * time * time - 1);
};
ccs.TweenFunction.quartEaseInOut = function (time) {
    time = time * 2;
    if (time < 1)
        return 0.5 * time * time * time * time;
    time -= 2;
    return -0.5 * (time * time * time * time - 2);
};
ccs.TweenFunction.quintEaseIn = function (time) {
    return time * time * time * time * time;
};
ccs.TweenFunction.quintEaseOut = function (time) {
    time -= 1;
    return (time * time * time * time * time + 1);
};
ccs.TweenFunction.quintEaseInOut = function (time) {
    time = time * 2;
    if (time < 1)
        return 0.5 * time * time * time * time * time;
    time -= 2;
    return 0.5 * (time * time * time * time * time + 2);
};
ccs.TweenFunction.expoEaseIn = function (time) {
    return time === 0 ? 0 : Math.pow(2, 10 * (time - 1)) - 0.001;
};
ccs.TweenFunction.expoEaseOut = function (time) {
    return time === 1 ? 1 : (-Math.pow(2, -10 * time) + 1);
};
ccs.TweenFunction.expoEaseInOut = function (time) {
    time /= 0.5;
    if (time < 1) {
        time = 0.5 * Math.pow(2, 10 * (time - 1));
    }
    else {
        time = 0.5 * (-Math.pow(2, -10 * (time - 1)) + 2);
    }
    return time;
};
ccs.TweenFunction.circEaseIn = function (time) {
    return -1 * (Math.sqrt(1 - time * time) - 1);
};
ccs.TweenFunction.circEaseOut = function (time) {
    time = time - 1;
    return Math.sqrt(1 - time * time);
};
ccs.TweenFunction.circEaseInOut = function (time) {
    time = time * 2;
    if (time < 1)
        return -0.5 * (Math.sqrt(1 - time * time) - 1);
    time -= 2;
    return 0.5 * (Math.sqrt(1 - time * time) + 1);
};
ccs.TweenFunction.elasticEaseIn = function (time, easingParam) {
    var period = 0.3;
    if (easingParam.length > 0) {
        period = easingParam[0];
    }
    var newT = 0;
    if (time === 0 || time === 1) {
        newT = time;
    }
    else {
        var s = period / 4;
        time = time - 1;
        newT = -Math.pow(2, 10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period);
    }
    return newT;
};
ccs.TweenFunction.elasticEaseOut = function (time, easingParam) {
    var period = 0.3;
    if (easingParam.length > 0) {
        period = easingParam[0];
    }
    var newT = 0;
    if (time === 0 || time === 1) {
        newT = time;
    }
    else {
        var s = period / 4;
        newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period) + 1;
    }
    return newT;
};
ccs.TweenFunction.elasticEaseInOut = function (time, easingParam) {
    var period = 0.3;
    if (easingParam.length > 0) {
        period = easingParam[0];
    }
    var newT = 0;
    if (time === 0 || time === 1) {
        newT = time;
    }
    else {
        time = time * 2;
        if (!period) {
            period = 0.3 * 1.5;
        }
        var s = period / 4;
        time = time - 1;
        if (time < 0) {
            newT = -0.5 * Math.pow(2, 10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period);
        } else {
            newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period) * 0.5 + 1;
        }
    }
    return newT;
};
ccs.TweenFunction.backEaseIn = function (time) {
    var overshoot = 1.70158;
    return time * time * ((overshoot + 1) * time - overshoot);
};
ccs.TweenFunction.backEaseOut = function (time) {
    var overshoot = 1.70158;
    time = time - 1;
    return time * time * ((overshoot + 1) * time + overshoot) + 1;
};
ccs.TweenFunction.backEaseInOut = function (time) {
    var overshoot = 1.70158 * 1.525;
    time = time * 2;
    if (time < 1) {
        return (time * time * ((overshoot + 1) * time - overshoot)) / 2;
    }
    else {
        time = time - 2;
        return (time * time * ((overshoot + 1) * time + overshoot)) / 2 + 1;
    }
};
ccs.bounceTime = function (time) {
    if (time < 1 / 2.75) {
        return 7.5625 * time * time;
    } else if (time < 2 / 2.75) {
        time -= 1.5 / 2.75;
        return 7.5625 * time * time + 0.75;
    } else if (time < 2.5 / 2.75) {
        time -= 2.25 / 2.75;
        return 7.5625 * time * time + 0.9375;
    }
    time -= 2.625 / 2.75;
    return 7.5625 * time * time + 0.984375;
};
ccs.TweenFunction.bounceEaseIn = function (time) {
    return 1 - ccs.bounceTime(1 - time);
};
ccs.TweenFunction.bounceEaseOut = function (time) {
    return ccs.bounceTime(time);
};
ccs.TweenFunction.bounceEaseInOut = function (time) {
    var newT = 0;
    if (time < 0.5) {
        time = time * 2;
        newT = (1 - ccs.bounceTime(1 - time)) * 0.5;
    } else {
        newT = ccs.bounceTime(time * 2 - 1) * 0.5 + 0.5;
    }
    return newT;
};
ccs.TweenFunction.customEase = function (time, easingParam) {
    if (easingParam.length > 0) {
        var tt = 1 - time;
        return easingParam[1] * tt * tt * tt + 3 * easingParam[3] * time * tt * tt + 3 * easingParam[5] * time * time * tt + easingParam[7] * time * time * time;
    }
    return time;
};
ccs.TweenFunction.easeIn = function(time, rate){
    return Math.pow(time, rate);
};
ccs.TweenFunction.easeOut = function(time, rate){
    return Math.pow(time, 1 / rate);
};
ccs.TweenFunction.easeInOut = function(time, rate){
    time *= 2;
    if(time < 1){
        return 0.5 * Math.pow(time, rate);
    }else{
        return 1 - 0.5 * Math.pow(2 - time, rate);
    }
};
ccs.TweenFunction.quadraticIn = function(time){
    return Math.pow(time, 2);
};
ccs.TweenFunction.quadraticOut = function(time){
    return -time * (time - 2);
};
ccs.TweenFunction.bezieratFunction = function(a, b, c, d, t){
    return (Math.pow(1-t,3) * a + 3*t*(Math.pow(1-t,2))*b + 3*Math.pow(t,2)*(1-t)*c + Math.pow(t,3)*d );
};
var ENABLE_PHYSICS_DETECT = false;
ccs.fmodf = function (x, y) {
    while (x > y) {
        x -= y;
    }
    return x;
};
var CC_SAFE_RELEASE = function (obj) {
    if (obj && obj.release) {
        obj.release();
    }
};
ccs.isSpriteContainPoint = function (sprite, point, outPoint) {
    var p = sprite.convertToNodeSpace(point);
    if (outPoint) {
        outPoint.x = p.x;
        outPoint.y = p.y;
    }
    var s = sprite.getContentSize();
    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;
ccs.extBezierTo = function (t, point1, point2, point3, point4) {
    var p = cc.p(0, 0);
    if (point3 && !point4) {
        p.x = Math.pow((1 - t), 2) * point1.x + 2 * t * (1 - t) * point2.x + Math.pow(t, 2) * point3.x;
        p.y = Math.pow((1 - t), 2) * point1.y + 2 * t * (1 - t) * point2.y + Math.pow(t, 2) * point3.y;
    }
    if (point4) {
        p.x = point1.x * Math.pow((1 - t), 3) + 3 * t * point2.x * Math.pow((1 - t), 2) + 3 * point3.x * Math.pow(t, 2) * (1 - t) + point4.x * Math.pow(t, 3);
        p.y = point1.y * Math.pow((1 - t), 3) + 3 * t * point2.y * Math.pow((1 - t), 2) + 3 * point3.y * Math.pow(t, 2) * (1 - t) + point4.y * Math.pow(t, 3);
    }
    return p;
};
ccs.extCircleTo = function (t, center, radius, fromRadian, radianDif) {
    var p = cc.p(0, 0);
    p.x = center.x + radius * Math.cos(fromRadian + radianDif * t);
    p.y = center.y + radius * Math.sin(fromRadian + radianDif * t);
    return p;
};
ccs.RelativeData = function () {
    this.plistFiles = [];
    this.armatures = [];
    this.animations = [];
    this.textures = [];
};
ccs.armatureDataManager =  {
    _animationDatas: {},
    _armatureDatas: {},
    _textureDatas: {},
    _autoLoadSpriteFile: false,
    _relativeDatas: {},
    s_sharedArmatureDataManager: null,
    removeArmatureFileInfo: function (configFilePath) {
        var data = this.getRelativeData(configFilePath);
        if (data) {
            var i, obj;
            for (i = 0; i < data.armatures.length; i++) {
                obj = data.armatures[i];
                this.removeArmatureData(obj);
            }
            for (i = 0; i < data.animations.length; i++) {
                obj = data.animations[i];
                this.removeAnimationData(obj);
            }
            for (i = 0; i < data.textures.length; i++) {
                obj = data.textures[i];
                this.removeTextureData(obj);
            }
            for (i = 0; i < data.plistFiles.length; i++) {
                obj = data.plistFiles[i];
                cc.spriteFrameCache.removeSpriteFramesFromFile(obj);
            }
            delete this._relativeDatas[configFilePath];
            ccs.dataReaderHelper.removeConfigFile(configFilePath);
        }
    },
    addArmatureData: function (id, armatureData, configFilePath) {
        var data = this.getRelativeData(configFilePath);
        if (data) {
            data.armatures.push(id);
        }
        this._armatureDatas[id] = armatureData;
    },
    getArmatureData: function (id) {
        var armatureData = null;
        if (this._armatureDatas) {
            armatureData = this._armatureDatas[id];
        }
        return armatureData;
    },
    removeArmatureData: function (id) {
        if (this._armatureDatas[id])
            delete this._armatureDatas[id];
    },
    addAnimationData: function (id, animationData, configFilePath) {
        var data = this.getRelativeData(configFilePath);
        if (data)
            data.animations.push(id);
        this._animationDatas[id] = animationData;
    },
    getAnimationData: function (id) {
        var animationData = null;
        if (this._animationDatas[id]) {
            animationData = this._animationDatas[id];
        }
        return animationData;
    },
    removeAnimationData: function (id) {
        if (this._animationDatas[id])
            delete this._animationDatas[id];
    },
    addTextureData: function (id, textureData, configFilePath) {
        var data = this.getRelativeData(configFilePath);
        if (data) {
            data.textures.push(id);
        }
        this._textureDatas[id] = textureData;
    },
    getTextureData: function (id) {
        var textureData = null;
        if (this._textureDatas) {
            textureData = this._textureDatas[id];
        }
        return textureData;
    },
    removeTextureData: function (id) {
        if (this._textureDatas[id])
            delete this._textureDatas[id];
    },
    addArmatureFileInfo: function (  ) {
        var imagePath, plistPath, configFilePath;
        switch (arguments.length) {
            case 1:
                configFilePath = arguments[0];
                this.addRelativeData(configFilePath);
                this._autoLoadSpriteFile = true;
                ccs.dataReaderHelper.addDataFromFile(configFilePath);
                break;
            case 3:
                imagePath = arguments[0];
                plistPath = arguments[1];
                configFilePath = arguments[2];
                this.addRelativeData(configFilePath);
                this._autoLoadSpriteFile = false;
                ccs.dataReaderHelper.addDataFromFile(configFilePath);
                this.addSpriteFrameFromFile(plistPath, imagePath);
        }
    },
    addArmatureFileInfoAsync: function (  ) {
        var imagePath, plistPath, configFilePath, target, selector;
        switch (arguments.length) {
            case 3:
                configFilePath = arguments[0];
                target = arguments[2];
                selector = arguments[1];
                this.addRelativeData(configFilePath);
                this._autoLoadSpriteFile = true;
                ccs.dataReaderHelper.addDataFromFileAsync("", "", configFilePath, selector, target);
                break;
            case 5:
                imagePath = arguments[0];
                plistPath = arguments[1];
                configFilePath = arguments[2];
                target = arguments[4];
                selector = arguments[3];
                this.addRelativeData(configFilePath);
                this._autoLoadSpriteFile = false;
                ccs.dataReaderHelper.addDataFromFileAsync(imagePath, plistPath, configFilePath, selector, target);
                this.addSpriteFrameFromFile(plistPath, imagePath);
        }
    },
    addSpriteFrameFromFile: function (plistPath, imagePath, configFilePath) {
        var data = this.getRelativeData(configFilePath);
        if (data)
            data.plistFiles.push(plistPath);
        ccs.spriteFrameCacheHelper.addSpriteFrameFromFile(plistPath, imagePath);
    },
    isAutoLoadSpriteFile: function () {
        return this._autoLoadSpriteFile;
    },
    getArmatureDatas: function () {
        return this._armatureDatas;
    },
    getAnimationDatas: function () {
        return this._animationDatas;
    },
    getTextureDatas: function () {
        return this._textureDatas;
    },
    addRelativeData: function (configFilePath) {
        if (!this._relativeDatas[configFilePath])
            this._relativeDatas[configFilePath] = new ccs.RelativeData();
    },
    getRelativeData: function (configFilePath) {
        return this._relativeDatas[configFilePath];
    },
    clear: function () {
        for (var key in this._relativeDatas) {
            this.removeArmatureFileInfo(key);
        }
        this._animationDatas = {};
        this._armatureDatas = {};
        this._textureDatas = {};
        this._relativeDatas = {};
        ccs.spriteFrameCacheHelper.clear();
        ccs.dataReaderHelper.clear();
    }
};
ccs.BLEND_TYPE_NORMAL = 0;
ccs.BLEND_TYPE_LAYER = 1;
ccs.BLEND_TYPE_DARKEN = 2;
ccs.BLEND_TYPE_MULTIPLY = 3;
ccs.BLEND_TYPE_LIGHTEN = 4;
ccs.BLEND_TYPE_SCREEN = 5;
ccs.BLEND_TYPE_OVERLAY = 6;
ccs.BLEND_TYPE_HIGHLIGHT = 7;
ccs.BLEND_TYPE_ADD = 8;
ccs.BLEND_TYPE_SUBTRACT = 9;
ccs.BLEND_TYPE_DIFFERENCE = 10;
ccs.BLEND_TYPE_INVERT = 11;
ccs.BLEND_TYPE_ALPHA = 12;
ccs.BLEND_TYPE_ERASE = 13;
ccs.DISPLAY_TYPE_SPRITE = 0;
ccs.DISPLAY_TYPE_ARMATURE = 1;
ccs.DISPLAY_TYPE_PARTICLE = 2;
ccs.DISPLAY_TYPE_MAX = 3;
ccs.BaseData = ccs.Class.extend({
    x:0,
    y:0,
    zOrder:0,
    skewX:0,
    skewY:0,
    scaleX:1,
    scaleY:1,
    tweenRotate:0,
    isUseColorInfo:false,
    r:255,
    g:255,
    b:255,
    a:255,
    ctor:function () {
        this.x = 0;
        this.y = 0;
        this.zOrder = 0;
        this.skewX = 0;
        this.skewY = 0;
        this.scaleX = 1;
        this.scaleY = 1;
        this.tweenRotate = 0;
        this.isUseColorInfo = false;
        this.r = 255;
        this.g = 255;
        this.b = 255;
        this.a = 255;
    },
    copy:function (node) {
        this.x = node.x;
        this.y = node.y;
        this.zOrder = node.zOrder;
        this.scaleX = node.scaleX;
        this.scaleY = node.scaleY;
        this.skewX = node.skewX;
        this.skewY = node.skewY;
        this.tweenRotate = node.tweenRotate;
        this.isUseColorInfo = node.isUseColorInfo;
        this.r = node.r;
        this.g = node.g;
        this.b = node.b;
        this.a = node.a;
    },
    setColor:function(color){
        this.r = color.r;
        this.g = color.g;
        this.b = color.b;
        this.a = color.a;
    },
    getColor:function(){
        return cc.color(this.r, this.g, this.b, this.a);
    },
    subtract:function (from, to, limit) {
        this.x = to.x - from.x;
        this.y = to.y - from.y;
        this.scaleX = to.scaleX - from.scaleX;
        this.scaleY = to.scaleY - from.scaleY;
        this.skewX = to.skewX - from.skewX;
        this.skewY = to.skewY - from.skewY;
        if (this.isUseColorInfo || from.isUseColorInfo || to.isUseColorInfo) {
            this.a = to.a - from.a;
            this.r = to.r - from.r;
            this.g = to.g - from.g;
            this.b = to.b - from.b;
            this.isUseColorInfo = true;
        } else {
            this.a = this.r = this.g = this.b = 0;
            this.isUseColorInfo = false;
        }
        if (limit) {
            if (this.skewX > ccs.M_PI)
                this.skewX -= ccs.DOUBLE_PI;
            if (this.skewX < -ccs.M_PI)
                this.skewX += ccs.DOUBLE_PI;
            if (this.skewY > ccs.M_PI)
                this.skewY -= ccs.DOUBLE_PI;
            if (this.skewY < -ccs.M_PI)
                this.skewY += ccs.DOUBLE_PI;
        }
        if (to.tweenRotate) {
            this.skewX += to.tweenRotate * ccs.PI * 2;
            this.skewY -= to.tweenRotate * ccs.PI * 2;
        }
    }
});
ccs.DisplayData = ccs.Class.extend({
    displayType: ccs.DISPLAY_TYPE_MAX,
    displayName: "",
    ctor: function () {
        this.displayType = ccs.DISPLAY_TYPE_MAX;
    },
    changeDisplayToTexture:function (displayName) {
        var textureName = displayName;
        var startPos = textureName.lastIndexOf(".");
        if (startPos !== -1)
            textureName = textureName.substring(0, startPos);
        return textureName;
    },
    copy:function (displayData) {
        this.displayName = displayData.displayName;
        this.displayType = displayData.displayType;
    }
});
ccs.SpriteDisplayData = ccs.DisplayData.extend({
    skinData:null,
    ctor:function () {
        this.skinData = new ccs.BaseData();
        this.displayType = ccs.DISPLAY_TYPE_SPRITE;
    },
    copy:function (displayData) {
        ccs.DisplayData.prototype.copy.call(this,displayData);
        this.skinData = displayData.skinData;
    }
});
ccs.ArmatureDisplayData = ccs.DisplayData.extend({
    ctor:function () {
        this.displayName = "";
        this.displayType = ccs.DISPLAY_TYPE_ARMATURE;
    }
});
ccs.ParticleDisplayData = ccs.DisplayData.extend({
    ctor:function () {
        this.displayType = ccs.DISPLAY_TYPE_PARTICLE;
    }
});
ccs.BoneData = ccs.BaseData.extend({
    displayDataList: null,
    name: "",
    parentName: "",
    boneDataTransform: null,
    ctor: function () {
        this.displayDataList = [];
        this.name = "";
        this.parentName = "";
        this.boneDataTransform = null;
    },
    init: function () {
        this.displayDataList.length = 0;
        return true;
    },
    addDisplayData:function (displayData) {
        this.displayDataList.push(displayData);
    },
    getDisplayData:function (index) {
        return this.displayDataList[index];
    }
});
ccs.ArmatureData = ccs.Class.extend({
    boneDataDic:null,
    name:"",
    dataVersion:0.1,
    ctor:function () {
        this.boneDataDic = {};
        this.name = "";
        this.dataVersion = 0.1;
    },
    init:function () {
        return true;
    },
    addBoneData:function (boneData) {
        this.boneDataDic[boneData.name] = boneData;
    },
    getBoneDataDic:function () {
        return this.boneDataDic;
    },
    getBoneData:function (boneName) {
        return this.boneDataDic[boneName];
    }
});
ccs.FrameData = ccs.BaseData.extend({
        duration:0,
        tweenEasing:0,
        easingParamNumber: 0,
        easingParams: null,
        displayIndex:-1,
        movement:"",
        event:"",
        sound:"",
        soundEffect:"",
        blendFunc:null,
        frameID:0,
        isTween:true,
        ctor:function () {
            ccs.BaseData.prototype.ctor.call(this);
            this.duration = 1;
            this.tweenEasing = ccs.TweenType.LINEAR;
            this.easingParamNumber = 0;
            this.easingParams = [];
            this.displayIndex = 0;
            this.movement = "";
            this.event = "";
            this.sound = "";
            this.soundEffect = "";
            this.blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
            this.frameID = 0;
            this.isTween = true;
        },
        copy:function (frameData) {
            ccs.BaseData.prototype.copy.call(this, frameData);
            this.duration = frameData.duration;
            this.displayIndex = frameData.displayIndex;
            this.tweenEasing = frameData.tweenEasing;
            this.easingParamNumber = frameData.easingParamNumber;
            if (this.easingParamNumber !== 0){
                this.easingParams.length = 0;
                for (var i = 0; i<this.easingParamNumber; i++){
                    this.easingParams[i] = frameData.easingParams[i];
                }
            }
            this.blendFunc = frameData.blendFunc;
            this.isTween = frameData.isTween;
        }
    }
);
ccs.MovementBoneData = ccs.Class.extend({
    delay:0,
    scale:1,
    duration:0,
    frameList:null,
    name:"",
    ctor:function () {
        this.delay = 0;
        this.scale = 1;
        this.duration = 0;
        this.frameList = [];
        this.name = "";
    },
    init:function () {
        return true;
    },
    addFrameData:function (frameData) {
        this.frameList.push(frameData);
    },
    getFrameData:function (index) {
        return this.frameList[index];
    }
});
ccs.MovementData = function(){
    this.name = "";
    this.duration = 0;
    this.scale = 1;
    this.durationTo = 0;
    this.durationTween = 0;
    this.loop = true;
    this.tweenEasing = ccs.TweenType.LINEAR;
    this.movBoneDataDic = {};
};
ccs.MovementData.prototype.addMovementBoneData = function(movBoneData){
    this.movBoneDataDic[ movBoneData.name] = movBoneData;
};
ccs.MovementData.prototype.getMovementBoneData = function(boneName){
    return  this.movBoneDataDic[boneName];
};
ccs.AnimationData = function(){
    this.movementDataDic = {};
    this.movementNames = [];
    this.name = "";
};
ccs.AnimationData.prototype.addMovement = function(moveData){
    this.movementDataDic[moveData.name] = moveData;
    this.movementNames.push(moveData.name);
};
ccs.AnimationData.prototype.getMovement = function(moveName){
    return this.movementDataDic[moveName];
};
ccs.AnimationData.prototype.getMovementCount = function(){
    return Object.keys(this.movementDataDic).length;
};
ccs.ContourVertex2 = function (x, y) {
    this.x = x || 0;
    this.y = y || 0;
};
ccs.ContourData = function(){
    this.vertexList = [];
};
ccs.ContourData.prototype.init = function(){
    this.vertexList.length = 0;
    return true;
};
ccs.ContourData.prototype.addVertex = function(p){
    this.vertexList.push(p);
};
ccs.TextureData = function(){
    this.height = 0;
    this.width = 0;
    this.pivotX = 0.5;
    this.pivotY = 0.5;
    this.name = "";
    this.contourDataList = [];
};
ccs.TextureData.prototype.init = function(){
    this.contourDataList.length = 0;
};
ccs.TextureData.prototype.addContourData = function(contourData){
    this.contourDataList.push(contourData);
};
ccs.TextureData.prototype.getContourData = function(index){
    return this.contourDataList[index];
};
ccs.DecorativeDisplay = ccs.Class.extend({
    _display: null,
    _colliderDetector: null,
    _displayData: null,
    ctor:function () {
        this._display = null;
        this._colliderDetector = null;
        this._displayData = null;
    },
    init:function () {
        return true;
    },
    setDisplay:function (display) {
        if(display._parent){
            display._parent.removeChild(display);
            delete display._parent;
        }
        this._display = display;
    },
    getDisplay:function () {
        return this._display;
    },
    setColliderDetector:function (colliderDetector) {
        this._colliderDetector = colliderDetector;
    },
    getColliderDetector:function () {
        return this._colliderDetector;
    },
    setDisplayData:function (displayData) {
        this._displayData = displayData;
    },
    getDisplayData:function () {
        return this._displayData;
    },
    release:function () {
        this._display = null;
        this._displayData = null;
        this._colliderDetector = null;
    }
});
ccs.DecorativeDisplay.create = function () {
    return new ccs.DecorativeDisplay();
};
ccs.displayFactory = {
    addDisplay: function (bone, decoDisplay, displayData) {
        switch (displayData.displayType) {
            case ccs.DISPLAY_TYPE_SPRITE:
                this.addSpriteDisplay(bone, decoDisplay, displayData);
                break;
            case ccs.DISPLAY_TYPE_PARTICLE:
                this.addParticleDisplay(bone, decoDisplay, displayData);
                break;
            case ccs.DISPLAY_TYPE_ARMATURE:
                this.addArmatureDisplay(bone, decoDisplay, displayData);
                break;
            default:
                break;
        }
    },
    createDisplay: function (bone, decoDisplay) {
        switch (decoDisplay.getDisplayData().displayType) {
            case ccs.DISPLAY_TYPE_SPRITE:
                this.createSpriteDisplay(bone, decoDisplay);
                break;
            case ccs.DISPLAY_TYPE_PARTICLE:
                this.createParticleDisplay(bone, decoDisplay);
                break;
            case ccs.DISPLAY_TYPE_ARMATURE:
                this.createArmatureDisplay(bone, decoDisplay);
                break;
            default:
                break;
        }
    },
    _helpTransform: {a:1, b:0, c:0, d:1, tx:0, ty:0},
    updateDisplay: function (bone, dt, dirty) {
        var display = bone.getDisplayRenderNode();
        if(!display)
            return;
        switch (bone.getDisplayRenderNodeType()) {
            case ccs.DISPLAY_TYPE_SPRITE:
                if (dirty) {
                    display._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
                    display.updateArmatureTransform();
                }
                break;
            case ccs.DISPLAY_TYPE_PARTICLE:
                this.updateParticleDisplay(bone, display, dt);
                break;
            case ccs.DISPLAY_TYPE_ARMATURE:
                this.updateArmatureDisplay(bone, display, dt);
                break;
            default:
                var transform = bone.getNodeToArmatureTransform();
                display.setAdditionalTransform(transform);
                break;
        }
        if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
            if (dirty) {
                var decoDisplay = bone.getDisplayManager().getCurrentDecorativeDisplay();
                var detector = decoDisplay.getColliderDetector();
                if (detector) {
                    var node = decoDisplay.getDisplay();
                    var displayTransform = node.getNodeToParentTransform();
                    var helpTransform = this._helpTransform;
                    helpTransform.a = displayTransform.a;
                    helpTransform.b = displayTransform.b;
                    helpTransform.c = displayTransform.c;
                    helpTransform.d = displayTransform.d;
                    helpTransform.tx = displayTransform.tx;
                    helpTransform.ty = displayTransform.ty;
                    var anchorPoint = cc.pointApplyAffineTransform(node.getAnchorPointInPoints(), helpTransform);
                    helpTransform.tx = anchorPoint.x;
                    helpTransform.ty = anchorPoint.y;
                    var t = cc.affineTransformConcat(helpTransform, bone.getArmature().getNodeToParentTransform());
                    detector.updateTransform(t);
                }
            }
        }
    },
    addSpriteDisplay: function (bone, decoDisplay, displayData) {
        var sdp = new ccs.SpriteDisplayData();
        sdp.copy(displayData);
        decoDisplay.setDisplayData(sdp);
        this.createSpriteDisplay(bone, decoDisplay);
    },
    createSpriteDisplay: function (bone, decoDisplay) {
        var skin = null;
        var displayData = decoDisplay.getDisplayData();
        var textureName = displayData.displayName;
        var startPos = textureName.lastIndexOf(".");
        if (startPos !== -1)
            textureName = textureName.substring(0, startPos);
        if (textureName === "")
            skin = new ccs.Skin();
        else
            skin = new ccs.Skin("#" + textureName + ".png");
        decoDisplay.setDisplay(skin);
        skin.setBone(bone);
        this.initSpriteDisplay(bone, decoDisplay, displayData.displayName, skin);
        var armature = bone.getArmature();
        if (armature) {
            if (armature.getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED)
                skin.setSkinData(displayData.skinData);
            else
                skin.setSkinData(bone.boneData);
        }
    },
    initSpriteDisplay: function (bone, decoDisplay, displayName, skin) {
        var textureName = displayName;
        var startPos = textureName.lastIndexOf(".");
        if (startPos !== -1)
            textureName = textureName.substring(0, startPos);
        var textureData = ccs.armatureDataManager.getTextureData(textureName);
        if (textureData) {
            skin.setAnchorPoint(cc.p(textureData.pivotX, textureData.pivotY));
        }
        if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
            if (textureData && textureData.contourDataList.length > 0) {
                var colliderDetector = new ccs.ColliderDetector(bone);
                colliderDetector.addContourDataList(textureData.contourDataList);
                decoDisplay.setColliderDetector(colliderDetector);
            }
        }
    },
    addArmatureDisplay: function (bone, decoDisplay, displayData) {
        var adp = new ccs.ArmatureDisplayData();
        adp.copy(displayData);
        decoDisplay.setDisplayData(adp);
        this.createArmatureDisplay(bone, decoDisplay);
    },
    createArmatureDisplay: function (bone, decoDisplay) {
        var displayData = decoDisplay.getDisplayData();
        var armature = new ccs.Armature(displayData.displayName, bone);
        decoDisplay.setDisplay(armature);
    },
    updateArmatureDisplay: function (bone, armature, dt) {
        if (armature) {
            armature.sortAllChildren();
            armature.update(dt);
        }
    },
    addParticleDisplay: function (bone, decoDisplay, displayData) {
        var adp = new ccs.ParticleDisplayData();
        adp.copy(displayData);
        decoDisplay.setDisplayData(adp);
        this.createParticleDisplay(bone, decoDisplay);
    },
    createParticleDisplay: function (bone, decoDisplay) {
        var displayData = decoDisplay.getDisplayData();
        var system = new cc.ParticleSystem(displayData.displayName);
        system.removeFromParent();
        system.cleanup();
        var armature = bone.getArmature();
        if (armature)
            system.setParent(bone.getArmature());
        decoDisplay.setDisplay(system);
    },
    updateParticleDisplay: function (bone, particleSystem, dt) {
        var node = new ccs.BaseData();
        ccs.TransformHelp.matrixToNode(bone.nodeToArmatureTransform(), node);
        particleSystem.setPosition(node.x, node.y);
        particleSystem.setScaleX(node.scaleX);
        particleSystem.setScaleY(node.scaleY);
        particleSystem.update(dt);
    }
};
ccs.DisplayManager = ccs.Class.extend({
    _decoDisplayList:null,
    _currentDecoDisplay:null,
    _displayRenderNode:null,
    _displayIndex: null,
    _forceChangeDisplay:false,
    _bone:null,
    _visible:true,
    _displayType: null,
    ctor:function (bone) {
        this._decoDisplayList = [];
        this._currentDecoDisplay = null;
        this._displayRenderNode = null;
        this._displayIndex = null;
        this._forceChangeDisplay = false;
        this._bone = null;
        this._visible = true;
        this._displayType = ccs.DISPLAY_TYPE_MAX;
        bone && ccs.DisplayManager.prototype.init.call(this, bone);
    },
    init:function (bone) {
        this._bone = bone;
        this.initDisplayList(bone.getBoneData());
        return true;
    },
    addDisplay: function (display, index) {
        var decoDisplay, locDisplayList = this._decoDisplayList;
        if( (index >= 0) && (index < locDisplayList.length) )
            decoDisplay = locDisplayList[index];
        else{
            decoDisplay = new ccs.DecorativeDisplay();
            locDisplayList.push(decoDisplay);
        }
        if(display instanceof ccs.DisplayData){
            ccs.displayFactory.addDisplay(this._bone, decoDisplay, display);
            if(index === this._displayIndex) {
                this._displayIndex = -1;
                this.changeDisplayWithIndex(index, false);
            }
            return;
        }
        var displayData = null;
        if (display instanceof ccs.Skin) {
            display.setBone(this._bone);
            displayData = new ccs.SpriteDisplayData();
            ccs.displayFactory.initSpriteDisplay(this._bone, decoDisplay, display.getDisplayName(), display);
            var spriteDisplayData = decoDisplay.getDisplayData();
            if (spriteDisplayData instanceof ccs.SpriteDisplayData) {
                display.setSkinData(spriteDisplayData.skinData);
                displayData.skinData = spriteDisplayData.skinData;
            } else {
                var find = false;
                for (var i = locDisplayList.length - 2; i >= 0; i--) {
                    var dd = locDisplayList[i];
                    var sdd = dd.getDisplayData();
                    if (sdd instanceof ccs.SpriteDisplayData) {
                        find = true;
                        display.setSkinData(sdd.skinData);
                        displayData.skinData = sdd.skinData;
                        break;
                    }
                }
                if (!find)
                    display.setSkinData(new ccs.BaseData());
            }
        } else if (display instanceof cc.ParticleSystem){
            displayData = new ccs.ParticleDisplayData();
            display.removeFromParent();
            display.cleanup();
            var armature = this._bone.getArmature();
            if (armature)
                display.setParent(armature);
        } else if(display instanceof ccs.Armature) {
            displayData = new ccs.ArmatureDisplayData();
            displayData.displayName = display.getName();
            display.setParentBone(this._bone);
        } else
            displayData = new ccs.DisplayData();
        decoDisplay.setDisplay(display);
        decoDisplay.setDisplayData(displayData);
        if(index === this._displayIndex) {
            this._displayIndex = -1;
            this.changeDisplayWithIndex(index, false);
        }
    },
    _addDisplayOther:function(decoDisplay,display){
        var displayData = null;
        if (display instanceof ccs.Skin){
            var skin = display;
            skin.setBone(this._bone);
            displayData = new ccs.SpriteDisplayData();
            displayData.displayName = skin.getDisplayName();
            ccs.displayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
            var spriteDisplayData = decoDisplay.getDisplayData();
            if (spriteDisplayData instanceof ccs.SpriteDisplayData)
                skin.setSkinData(spriteDisplayData.skinData);
            else{
                var find = false;
                for (var i = this._decoDisplayList.length - 2; i >= 0; i--) {
                    var dd = this._decoDisplayList[i];
                    var sdd = dd.getDisplayData();
                    if (sdd) {
                        find = true;
                        skin.setSkinData(sdd.skinData);
                        displayData.skinData = sdd.skinData;
                        break;
                    }
                }
                if (!find) {
                    skin.setSkinData(new ccs.BaseData());
                }
                skin.setSkinData(new ccs.BaseData());
            }
        }
        else if (display instanceof cc.ParticleSystem){
            displayData = new ccs.ParticleDisplayData();
            displayData.displayName = display._plistFile;
        }
        else if (display instanceof ccs.Armature){
            displayData = new ccs.ArmatureDisplayData();
            displayData.displayName = display.getName();
            display.setParentBone(this._bone);
        }
        else  {
            displayData = new ccs.DisplayData();
        }
        decoDisplay.setDisplay(display);
        decoDisplay.setDisplayData(displayData);
    },
    removeDisplay:function (index) {
        this._decoDisplayList.splice(index, 1);
        if (index === this._displayIndex) {
            this.setCurrentDecorativeDisplay(null);
            this._displayIndex = -1;
        }
    },
    getDecorativeDisplayList:function(){
        return this._decoDisplayList;
    },
    changeDisplayWithIndex:function (index, force) {
        if (index >= this._decoDisplayList.length) {
            cc.log("the index value is out of range");
            return;
        }
        this._forceChangeDisplay = force;
        if (this._displayIndex === index)
            return;
        this._displayIndex = index;
        if (index < 0) {
            if(this._displayRenderNode) {
                this._displayRenderNode.removeFromParent(true);
                this.setCurrentDecorativeDisplay(null);
            }
            return;
        }
        this.setCurrentDecorativeDisplay(this._decoDisplayList[index]);
    },
    changeDisplayWithName: function (name, force) {
        var locDisplayList = this._decoDisplayList;
        for (var i = 0; i < locDisplayList.length; i++) {
            if (locDisplayList[i].getDisplayData().displayName === name) {
                this.changeDisplayWithIndex(i, force);
                break;
            }
        }
    },
    setCurrentDecorativeDisplay:function (decoDisplay) {
        var locCurrentDecoDisplay = this._currentDecoDisplay;
        if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
            if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector())
                locCurrentDecoDisplay.getColliderDetector().setActive(false);
        }
        this._currentDecoDisplay = decoDisplay;
        locCurrentDecoDisplay = this._currentDecoDisplay;
        if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
            if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector())
                locCurrentDecoDisplay.getColliderDetector().setActive(true);
        }
        var displayRenderNode = (!locCurrentDecoDisplay) ? null : locCurrentDecoDisplay.getDisplay();
        var locRenderNode = this._displayRenderNode, locBone = this._bone;
        if (locRenderNode) {
            if (locRenderNode instanceof ccs.Armature)
                locBone.setChildArmature(null);
            locRenderNode.removeFromParent(true);
        }
        this._displayRenderNode = displayRenderNode;
        if (displayRenderNode) {
            if (displayRenderNode instanceof ccs.Armature) {
                this._bone.setChildArmature(displayRenderNode);
                displayRenderNode.setParentBone(this._bone);
            } else if (displayRenderNode instanceof cc.ParticleSystem) {
                if (displayRenderNode instanceof ccs.Armature) {
                    locBone.setChildArmature(displayRenderNode);
                    displayRenderNode.setParentBone(locBone);
                } else if (displayRenderNode instanceof cc.ParticleSystem)
                    displayRenderNode.resetSystem();
            }
            displayRenderNode.setColor(locBone.getDisplayedColor());
            displayRenderNode.setOpacity(locBone.getDisplayedOpacity());
            this._displayRenderNode.setVisible(this._visible);
            this._displayType = this._currentDecoDisplay.getDisplayData().displayType;
        }else
            this._displayType = ccs.DISPLAY_TYPE_MAX;
        cc.renderer.childrenOrderDirty = true;
    },
    getDisplayRenderNode:function () {
        return this._displayRenderNode;
    },
    getDisplayRenderNodeType:function(){
        return this._displayType;
    },
    getCurrentDisplayIndex:function () {
        return this._displayIndex;
    },
    getCurrentDecorativeDisplay:function () {
        return this._currentDecoDisplay;
    },
    getDecorativeDisplayByIndex:function (index) {
        return this._decoDisplayList[index];
    },
    initDisplayList:function (boneData) {
        this._decoDisplayList.length = 0;
        if (!boneData)
            return;
        var displayList = boneData.displayDataList, decoList = this._decoDisplayList, locBone = this._bone;
        for (var i = 0; i < displayList.length; i++) {
            var displayData = displayList[i];
            var decoDisplay = new ccs.DecorativeDisplay();
            decoDisplay.setDisplayData(displayData);
            ccs.displayFactory.createDisplay(locBone, decoDisplay);
            decoList.push(decoDisplay);
        }
    },
    containPoint: function (point, y) {
        if (!this._visible || this._displayIndex < 0)
            return false;
        if (y !== undefined)
            point = cc.p(point, y);
        if(this._currentDecoDisplay.getDisplayData().displayType === ccs.DISPLAY_TYPE_SPRITE){
            var sprite = this._currentDecoDisplay.getDisplay();
            sprite = sprite.getChildByTag(0);
            return ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, point);
        }
        return false;
    },
    setVisible:function (visible) {
        if (!this._displayRenderNode)
            return;
        this._visible = visible;
        this._displayRenderNode.setVisible(visible);
    },
    isVisible:function () {
        return this._visible;
    },
    getContentSize:function () {
        if (!this._displayRenderNode)
            return cc.size(0, 0);
        return this._displayRenderNode.getContentSize();
    },
    getBoundingBox:function () {
        if (!this._displayRenderNode)
            return cc.rect(0, 0, 0, 0);
        return this._displayRenderNode.getBoundingBox();
    },
    getAnchorPoint:function () {
        if (!this._displayRenderNode)
            return  cc.p(0, 0);
        return this._displayRenderNode.getAnchorPoint();
    },
    getAnchorPointInPoints:function () {
        if (!this._displayRenderNode)
            return  cc.p(0, 0);
        return this._displayRenderNode.getAnchorPointInPoints();
    },
    getForceChangeDisplay:function () {
        return this._forceChangeDisplay;
    },
    release:function () {
        this._decoDisplayList = null;
        if (this._displayRenderNode) {
            this._displayRenderNode.removeFromParent(true);
            this._displayRenderNode = null;
        }
    }
});
ccs.DisplayManager.create = function (bone) {
    return new ccs.DisplayManager(bone);
};
ccs.Skin = ccs.Sprite.extend({
    _skinData: null,
    bone: null,
    _skinTransform: null,
    _displayName: "",
    _armature: null,
    _className: "Skin",
    ctor: function (fileName, rect) {
        cc.Sprite.prototype.ctor.call(this);
        this._skinData = null;
        this.bone = null;
        this._displayName = "";
        this._skinTransform = cc.affineTransformIdentity();
        this._armature = null;
        if (fileName == null || fileName === "") {
            ccs.Skin.prototype.init.call(this);
        } else {
            if(fileName[0] === "#"){
                ccs.Skin.prototype.initWithSpriteFrameName.call(this, fileName.substr(1));
            } else {
                ccs.Skin.prototype.initWithFile.call(this, fileName, rect);
            }
        }
    },
    initWithSpriteFrameName: function (spriteFrameName) {
        if(spriteFrameName === "")
            return false;
        var pFrame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
        var ret = true;
        if(pFrame)
            this.initWithSpriteFrame(pFrame);
        else{
            cc.log("Can't find CCSpriteFrame with %s. Please check your .plist file", spriteFrameName);
            ret = false;
        }
        this._displayName = spriteFrameName;
        return ret;
    },
    initWithFile: function (fileName, rect) {
        var ret = rect ? cc.Sprite.prototype.initWithFile.call(this, fileName, rect)
                       : cc.Sprite.prototype.initWithFile.call(this, fileName);
        this._displayName = fileName;
        return ret;
    },
    setSkinData: function (skinData) {
        this._skinData = skinData;
        this.setScaleX(skinData.scaleX);
        this.setScaleY(skinData.scaleY);
        this.setRotationX(cc.radiansToDegrees(skinData.skewX));
        this.setRotationY(cc.radiansToDegrees(-skinData.skewY));
        this.setPosition(skinData.x, skinData.y);
        this._renderCmd.transform();
    },
    getSkinData: function () {
        return this._skinData;
    },
    updateArmatureTransform: function () {
        this._renderCmd.transform();
    },
    getNodeToWorldTransform: function(){
        return this._renderCmd.getNodeToWorldTransform();
    },
    getNodeToWorldTransformAR: function(){
        return this._renderCmd.getNodeToWorldTransformAR();
    },
    setBone: function (bone) {
        this.bone = bone;
        var armature = this.bone.getArmature();
        if(armature)
            this._armature = armature;
    },
    getBone: function () {
        return this.bone;
    },
    getDisplayName: function () {
        return this._displayName;
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new ccs.Skin.CanvasRenderCmd(this);
        else
            return new ccs.Skin.WebGLRenderCmd(this);
    }
});
var _p = ccs.Skin.prototype;
_p.skinData;
cc.defineGetterSetter(_p, "skinData", _p.getSkinData, _p.setSkinData);
_p.displayName;
cc.defineGetterSetter(_p, "displayName", _p.getDisplayName);
_p = null;
ccs.Skin.create = function (fileName, rect) {
    return new ccs.Skin(fileName, rect);
};
ccs.Skin.createWithSpriteFrameName = function (spriteFrameName) {
    return new ccs.Skin("#" + spriteFrameName);
};
(function(){
    ccs.Skin.RenderCmd = {
        _realWorldTM: null,
        transform: function (parentCmd, recursive) {
            var node = this._node,
                pt = parentCmd ? parentCmd._worldTransform : null,
                t = this._transform,
                wt = this._worldTransform,
                dirty = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty;
            if (dirty || pt) {
                this.originTransform();
                cc.affineTransformConcatIn(t, node.bone.getNodeToArmatureTransform());
                this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty ^ this._dirtyFlag;
            }
            if (pt) {
                wt.a  = t.a  * pt.a + t.b  * pt.c;
                wt.b  = t.a  * pt.b + t.b  * pt.d;
                wt.c  = t.c  * pt.a + t.d  * pt.c;
                wt.d  = t.c  * pt.b + t.d  * pt.d;
                wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
                wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
                var vertices = this._vertices;
                if (vertices) {
                    var lx = node._offsetPosition.x, rx = lx + node._rect.width,
                        by = node._offsetPosition.y, ty = by + node._rect.height;
                    vertices[0].x = lx * wt.a + ty * wt.c + wt.tx;
                    vertices[0].y = lx * wt.b + ty * wt.d + wt.ty;
                    vertices[1].x = lx * wt.a + by * wt.c + wt.tx;
                    vertices[1].y = lx * wt.b + by * wt.d + wt.ty;
                    vertices[2].x = rx * wt.a + ty * wt.c + wt.tx;
                    vertices[2].y = rx * wt.b + ty * wt.d + wt.ty;
                    vertices[3].x = rx * wt.a + by * wt.c + wt.tx;
                    vertices[3].y = rx * wt.b + by * wt.d + wt.ty;
                }
            }
            else {
                wt.a  = t.a;
                wt.b  = t.b;
                wt.c  = t.c;
                wt.d  = t.d;
                wt.tx = t.tx;
                wt.ty = t.ty;
            }
            var rwtm = this._realWorldTM;
            if(rwtm) {
                rwtm.a = t.a; rwtm.b = t.b; rwtm.c = t.c; rwtm.d = t.d; rwtm.tx= t.tx; rwtm.ty = t.ty;
                cc.affineTransformConcatIn(rwtm, this._node.bone.getArmature()._renderCmd._worldTransform);
            }
        },
        getNodeToWorldTransform: function () {
            return cc.affineTransformConcat(this._transform, this._node.bone.getArmature().getNodeToWorldTransform());
        },
        getNodeToWorldTransformAR: function () {
            var displayTransform = this._transform, node = this._node;
            this._anchorPointInPoints = cc.pointApplyAffineTransform(this._anchorPointInPoints, displayTransform);
            displayTransform.tx = this._anchorPointInPoints.x;
            displayTransform.ty = this._anchorPointInPoints.y;
            return cc.affineTransformConcat(displayTransform, node.bone.getArmature().getNodeToWorldTransform());
        }
    };
    ccs.Skin.CanvasRenderCmd = function(renderable){
        cc.Sprite.CanvasRenderCmd.call(this, renderable);
        this._realWorldTM = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
    };
    var proto = ccs.Skin.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
    cc.inject(ccs.Skin.RenderCmd, proto);
    proto.constructor = ccs.Skin.CanvasRenderCmd;
    proto._updateCurrentRegions = function () {
        var temp = this._currentRegion;
        this._currentRegion = this._oldRegion;
        this._oldRegion = temp;
        if (cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble === this._regionFlag && (!this._currentRegion.isEmpty())) {
            this._oldRegion.union(this._currentRegion);
        }
        this._currentRegion.updateRegion(this.getLocalBB(), this._realWorldTM);
    };
    ccs.Skin.WebGLRenderCmd = function(renderable){
        cc.Sprite.WebGLRenderCmd.call(this, renderable);
    };
    proto = ccs.Skin.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
    cc.inject(ccs.Skin.RenderCmd, proto);
    proto.constructor = ccs.Skin.WebGLRenderCmd;
})();
ccs.ANIMATION_TYPE_SINGLE_FRAME = -4;
ccs.ANIMATION_TYPE_NO_LOOP = -3;
ccs.ANIMATION_TYPE_TO_LOOP_FRONT = -2;
ccs.ANIMATION_TYPE_TO_LOOP_BACK = -1;
ccs.ANIMATION_TYPE_LOOP_FRONT = 0;
ccs.ANIMATION_TYPE_LOOP_BACK = 1;
ccs.ANIMATION_TYPE_MAX = 2;
ccs.ProcessBase = ccs.Class.extend({
    _processScale: 1,
    _isComplete: true,
    _isPause: true,
    _isPlaying: false,
    _currentPercent: 0.0,
    _rawDuration: 0,
    _loopType: 0,
    _tweenEasing: 0,
    animationInternal: null,
    _currentFrame: 0,
    _durationTween: 0,
    _nextFrameIndex: 0,
    _curFrameIndex: null,
    _isLoopBack: false,
    ctor: function () {
        this._processScale = 1;
        this._isComplete = true;
        this._isPause = true;
        this._isPlaying = false;
        this._currentFrame = 0;
        this._currentPercent = 0.0;
        this._durationTween = 0;
        this._rawDuration = 0;
        this._loopType = ccs.ANIMATION_TYPE_LOOP_BACK;
        this._tweenEasing = ccs.TweenType.LINEAR;
        this.animationInternal = 1 / 60;
        this._curFrameIndex = 0;
        this._durationTween = 0;
        this._isLoopBack = false;
    },
    pause: function () {
        this._isPause = true;
        this._isPlaying = false;
    },
    resume: function () {
        this._isPause = false;
        this._isPlaying = true;
    },
    stop: function () {
        this._isComplete = true;
        this._isPlaying = false;
    },
    play: function (durationTo, durationTween, loop, tweenEasing) {
        this._isComplete = false;
        this._isPause = false;
        this._isPlaying = true;
        this._currentFrame = 0;
        this._nextFrameIndex = durationTo;
        this._tweenEasing = tweenEasing;
    },
    update: function (dt) {
        if (this._isComplete || this._isPause)
            return;
        if (this._rawDuration <= 0 || dt > 1)
            return;
        var locNextFrameIndex = this._nextFrameIndex === undefined ? 0 : this._nextFrameIndex;
        var locCurrentFrame = this._currentFrame;
        if (locNextFrameIndex <= 0) {
            this._currentPercent = 1;
            locCurrentFrame = 0;
        } else {
            locCurrentFrame += this._processScale * (dt / this.animationInternal);
            this._currentPercent = locCurrentFrame / locNextFrameIndex;
            locCurrentFrame = ccs.fmodf(locCurrentFrame, locNextFrameIndex);
        }
        this._currentFrame = locCurrentFrame;
        this.updateHandler();
    },
    gotoFrame: function (frameIndex) {
        var locLoopType = this._loopType;
        if (locLoopType === ccs.ANIMATION_TYPE_NO_LOOP)
            locLoopType = ccs.ANIMATION_TYPE_MAX;
        else if (locLoopType === ccs.ANIMATION_TYPE_TO_LOOP_FRONT)
            locLoopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
        this._loopType = locLoopType;
        this._curFrameIndex = frameIndex;
        this._nextFrameIndex = this._durationTween;
    },
    getCurrentFrameIndex: function () {
        this._curFrameIndex = (this._rawDuration - 1) * this._currentPercent;
        return this._curFrameIndex;
    },
    updateHandler: function () {
    },
    isPause: function () {
        return this._isPause;
    },
    isComplete: function () {
        return this._isComplete;
    },
    getCurrentPercent: function () {
        return this._currentPercent;
    },
    getRawDuration: function () {
        return this._rawDuration;
    },
    getLoop: function () {
        return this._loopType;
    },
    getTweenEasing: function () {
        return this._tweenEasing;
    },
    getAnimationInternal: function () {
        return this.animationInternal;
    },
    setAnimationInternal: function (animationInternal) {
        this.animationInternal = animationInternal;
    },
    getProcessScale: function () {
        return this._processScale;
    },
    setProcessScale: function (processScale) {
        this._processScale = processScale;
    },
    isPlaying: function () {
        return this._isPlaying;
    }
});
var _p = ccs.ProcessBase.prototype;
_p.currentFrameIndex;
cc.defineGetterSetter(_p, "currentFrameIndex", _p.getCurrentFrameIndex);
_p.paused;
cc.defineGetterSetter(_p, "paused", _p.isPause);
_p.completed;
cc.defineGetterSetter(_p, "completed", _p.isComplete);
_p.currentPercent;
cc.defineGetterSetter(_p, "currentPercent", _p.getCurrentPercent);
_p.rawDuration;
cc.defineGetterSetter(_p, "rawDuration", _p.getRawDuration);
_p.loop;
cc.defineGetterSetter(_p, "loop", _p.getLoop);
_p.tweenEasing;
cc.defineGetterSetter(_p, "tweenEasing", _p.getTweenEasing);
_p.playing;
cc.defineGetterSetter(_p, "playing", _p.isPlaying);
_p = null;
ccs.MovementEventType = {
    start: 0,
    complete: 1,
    loopComplete: 2
};
ccs.AnimationEvent = ccs.Class.extend({
    _arguments: null,
    _callFunc: null,
    _selectorTarget: null,
    ctor: function (callFunc,target, data) {
        this._data = data;
        this._callFunc = callFunc;
        this._selectorTarget = target;
    },
    call: function () {
        if (this._callFunc)
            this._callFunc.apply(this._selectorTarget, this._arguments);
    },
    setArguments: function (args) {
        this._arguments = args;
    }
});
ccs.MovementEvent = function () {
    this.armature = null;
    this.movementType = ccs.MovementEventType.start;
    this.movementID = "";
};
ccs.FrameEvent = function () {
    this.bone = null;
    this.frameEventName = "";
    this.originFrameIndex = 0;
    this.currentFrameIndex = 0;
};
ccs.ArmatureAnimation = ccs.ProcessBase.extend({
    _animationData: null,
    _movementData: null,
    _armature: null,
    _movementID: "",
    _toIndex: 0,
    _tweenList: null,
    _speedScale: 1,
    _ignoreFrameEvent: false,
    _frameEventQueue: null,
    _movementEventQueue: null,
    _movementList: null,
    _onMovementList: false,
    _movementListLoop: false,
    _movementIndex: 0,
    _movementListDurationTo: -1,
    _movementEventCallFunc: null,
    _frameEventCallFunc: null,
    _movementEventTarget: null,
    _frameEventTarget:null,
    _movementEventListener: null,
    _frameEventListener: null,
    ctor: function (armature) {
        ccs.ProcessBase.prototype.ctor.call(this);
        this._tweenList = [];
        this._movementList = [];
        this._frameEventQueue = [];
        this._movementEventQueue = [];
        this._armature = null;
        armature && ccs.ArmatureAnimation.prototype.init.call(this, armature);
    },
    init: function (armature) {
        this._armature = armature;
        this._tweenList.length = 0;
        return true;
    },
    pause: function () {
        var locTweenList = this._tweenList;
        for (var i = 0; i < locTweenList.length; i++)
            locTweenList[i].pause();
        ccs.ProcessBase.prototype.pause.call(this);
    },
    resume: function () {
        var locTweenList = this._tweenList;
        for (var i = 0; i < locTweenList.length; i++)
            locTweenList[i].resume();
        ccs.ProcessBase.prototype.resume.call(this);
    },
    stop: function () {
        var locTweenList = this._tweenList;
        for (var i = 0; i < locTweenList.length; i++)
            locTweenList[i].stop();
        locTweenList.length = 0;
        ccs.ProcessBase.prototype.stop.call(this);
    },
    setAnimationScale: function (animationScale) {
        this.setSpeedScale(animationScale);
    },
    getAnimationScale: function () {
        return this.getSpeedScale();
    },
    setSpeedScale: function (speedScale) {
        if (speedScale === this._speedScale)
            return;
        this._speedScale = speedScale;
        this._processScale = !this._movementData ? this._speedScale : this._speedScale * this._movementData.scale;
        var dict = this._armature.getBoneDic();
        for (var key in dict) {
            var bone = dict[key];
            bone.getTween().setProcessScale(this._processScale);
            if (bone.getChildArmature())
                bone.getChildArmature().getAnimation().setSpeedScale(this._processScale);
        }
    },
    getSpeedScale: function () {
        return this._speedScale;
    },
    play: function (animationName, durationTo, loop) {
        cc.assert(this._animationData, "this.animationData can not be null");
        this._movementData = this._animationData.getMovement(animationName);
        cc.assert(this._movementData, "this._movementData can not be null");
        durationTo = (durationTo === undefined) ? -1 : durationTo;
        loop = (loop === undefined) ? -1 : loop;
        this._rawDuration = this._movementData.duration;
        this._movementID = animationName;
        this._processScale = this._speedScale * this._movementData.scale;
        durationTo = (durationTo === -1) ? this._movementData.durationTo : durationTo;
        var durationTween = this._movementData.durationTween === 0 ? this._rawDuration : this._movementData.durationTween;
        var tweenEasing = this._movementData.tweenEasing;
        loop = (loop < 0) ? this._movementData.loop : loop;
        this._onMovementList = false;
        ccs.ProcessBase.prototype.play.call(this, durationTo, durationTween, loop, tweenEasing);
        if (this._rawDuration === 0)
            this._loopType = ccs.ANIMATION_TYPE_SINGLE_FRAME;
        else {
            this._loopType = loop ? ccs.ANIMATION_TYPE_TO_LOOP_FRONT : ccs.ANIMATION_TYPE_NO_LOOP;
            this._durationTween = durationTween;
        }
        this._tweenList.length = 0;
        var movementBoneData, map = this._armature.getBoneDic();
        for(var element in map) {
            var bone = map[element];
            movementBoneData = this._movementData.movBoneDataDic[bone.getName()];
            var tween = bone.getTween();
            if(movementBoneData && movementBoneData.frameList.length > 0) {
                this._tweenList.push(tween);
                movementBoneData.duration = this._movementData.duration;
                tween.play(movementBoneData, durationTo, durationTween, loop, tweenEasing);
                tween.setProcessScale(this._processScale);
                if (bone.getChildArmature()) {
                    bone.getChildArmature().getAnimation().setSpeedScale(this._processScale);
                    if (!bone.getChildArmature().getAnimation().isPlaying())
                        bone.getChildArmature().getAnimation().playWithIndex(0);
                }
            } else {
                if(!bone.isIgnoreMovementBoneData()){
                    bone.getDisplayManager().changeDisplayWithIndex(-1, false);
                    tween.stop();
                }
            }
        }
        this._armature.update(0);
    },
    playByIndex: function (animationIndex, durationTo, durationTween, loop, tweenEasing) {
        cc.log("playByIndex is deprecated. Use playWithIndex instead.");
        this.playWithIndex(animationIndex, durationTo, loop);
    },
    playWithIndex: function (animationIndex, durationTo, loop) {
        var movName = this._animationData.movementNames;
        cc.assert((animationIndex > -1) && (animationIndex < movName.length));
        var animationName = movName[animationIndex];
        this.play(animationName, durationTo, loop);
    },
    playWithNames: function (movementNames, durationTo, loop) {
        durationTo = (durationTo === undefined) ? -1 : durationTo;
        loop = (loop === undefined) ? true : loop;
        this._movementListLoop = loop;
        this._movementListDurationTo = durationTo;
        this._onMovementList = true;
        this._movementIndex = 0;
        if(movementNames instanceof Array)
            this._movementList = movementNames;
        else
            this._movementList.length = 0;
        this.updateMovementList();
    },
    playWithIndexes: function (movementIndexes, durationTo, loop) {
        durationTo = (durationTo === undefined) ? -1 : durationTo;
        loop = (loop === undefined) ? true : loop;
        this._movementList.length = 0;
        this._movementListLoop = loop;
        this._movementListDurationTo = durationTo;
        this._onMovementList = true;
        this._movementIndex = 0;
        var movName = this._animationData.movementNames;
        for (var i = 0; i < movementIndexes.length; i++) {
            var name = movName[movementIndexes[i]];
            this._movementList.push(name);
        }
        this.updateMovementList();
    },
    gotoAndPlay: function (frameIndex) {
        if (!this._movementData || frameIndex < 0 || frameIndex >= this._movementData.duration) {
            cc.log("Please ensure you have played a movement, and the frameIndex is in the range.");
            return;
        }
        var ignoreFrameEvent = this._ignoreFrameEvent;
        this._ignoreFrameEvent = true;
        this._isPlaying = true;
        this._isComplete = this._isPause = false;
        ccs.ProcessBase.prototype.gotoFrame.call(this, frameIndex);
        this._currentPercent = this._curFrameIndex / (this._movementData.duration - 1);
        this._currentFrame = this._nextFrameIndex * this._currentPercent;
        var locTweenList = this._tweenList;
        for (var i = 0; i < locTweenList.length; i++)
            locTweenList[i].gotoAndPlay(frameIndex);
        this._armature.update(0);
        this._ignoreFrameEvent = ignoreFrameEvent;
    },
    gotoAndPause: function (frameIndex) {
        this.gotoAndPlay(frameIndex);
        this.pause();
    },
    getMovementCount: function () {
        return this._animationData.getMovementCount();
    },
    update: function (dt) {
        ccs.ProcessBase.prototype.update.call(this, dt);
        var locTweenList = this._tweenList;
        for (var i = 0; i < locTweenList.length; i++)
            locTweenList[i].update(dt);
        var frameEvents = this._frameEventQueue, event;
        while (frameEvents.length > 0) {
            event = frameEvents.shift();
            this._ignoreFrameEvent = true;
            if(this._frameEventCallFunc)
                this._frameEventCallFunc.call(this._frameEventTarget, event.bone, event.frameEventName, event.originFrameIndex, event.currentFrameIndex);
            if(this._frameEventListener)
                this._frameEventListener(event.bone, event.frameEventName, event.originFrameIndex, event.currentFrameIndex);
            this._ignoreFrameEvent = false;
        }
        var movementEvents = this._movementEventQueue;
        while (movementEvents.length > 0) {
            event = movementEvents.shift();
            if(this._movementEventCallFunc)
                this._movementEventCallFunc.call(this._movementEventTarget, event.armature, event.movementType, event.movementID);
            if (this._movementEventListener)
                this._movementEventListener(event.armature, event.movementType, event.movementID);
        }
    },
    updateHandler: function () {
        var locCurrentPercent = this._currentPercent;
        if (locCurrentPercent >= 1) {
            switch (this._loopType) {
                case ccs.ANIMATION_TYPE_NO_LOOP:
                    this._loopType = ccs.ANIMATION_TYPE_MAX;
                    this._currentFrame = (locCurrentPercent - 1) * this._nextFrameIndex;
                    locCurrentPercent = this._currentFrame / this._durationTween;
                    if (locCurrentPercent < 1.0) {
                        this._nextFrameIndex = this._durationTween;
                        this.movementEvent(this._armature, ccs.MovementEventType.start, this._movementID);
                        break;
                    }
                    break;
                case ccs.ANIMATION_TYPE_MAX:
                case ccs.ANIMATION_TYPE_SINGLE_FRAME:
                    locCurrentPercent = 1;
                    this._isComplete = true;
                    this._isPlaying = false;
                    this.movementEvent(this._armature, ccs.MovementEventType.complete, this._movementID);
                    this.updateMovementList();
                    break;
                case ccs.ANIMATION_TYPE_TO_LOOP_FRONT:
                    this._loopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
                    locCurrentPercent = ccs.fmodf(locCurrentPercent, 1);
                    this._currentFrame = this._nextFrameIndex === 0 ? 0 : ccs.fmodf(this._currentFrame, this._nextFrameIndex);
                    this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1;
                    this.movementEvent(this, ccs.MovementEventType.start, this._movementID);
                    break;
                default:
                    this._currentFrame = ccs.fmodf(this._currentFrame, this._nextFrameIndex);
                    this._toIndex = 0;
                    this.movementEvent(this._armature, ccs.MovementEventType.loopComplete, this._movementID);
                    break;
            }
            this._currentPercent = locCurrentPercent;
        }
    },
    getCurrentMovementID: function () {
        if (this._isComplete)
            return "";
        return this._movementID;
    },
    setMovementEventCallFunc: function (callFunc, target) {
        if(arguments.length === 1){
            this._movementEventListener = callFunc;
        }else if(arguments.length === 2){
            this._movementEventTarget = target;
            this._movementEventCallFunc = callFunc;
        }
    },
    setFrameEventCallFunc: function (callFunc, target) {
        if(arguments.length === 1){
            this._frameEventListener = callFunc;
        }else if(arguments.length === 2){
            this._frameEventTarget = target;
            this._frameEventCallFunc = callFunc;
        }
    },
    setUserObject: function (userObject) {
        this._userObject = userObject;
    },
    frameEvent: function (bone, frameEventName, originFrameIndex, currentFrameIndex) {
        if ((this._frameEventTarget && this._frameEventCallFunc) || this._frameEventListener) {
            var frameEvent = new ccs.FrameEvent();
            frameEvent.bone = bone;
            frameEvent.frameEventName = frameEventName;
            frameEvent.originFrameIndex = originFrameIndex;
            frameEvent.currentFrameIndex = currentFrameIndex;
            this._frameEventQueue.push(frameEvent);
        }
    },
    movementEvent: function (armature, movementType, movementID) {
        if ((this._movementEventTarget && this._movementEventCallFunc) || this._movementEventListener) {
            var event = new ccs.MovementEvent();
            event.armature = armature;
            event.movementType = movementType;
            event.movementID = movementID;
            this._movementEventQueue.push(event);
        }
    },
    updateMovementList: function () {
        if (this._onMovementList) {
            var movementObj, locMovementList = this._movementList;
            if (this._movementListLoop) {
                movementObj = locMovementList[this._movementIndex];
                this.play(movementObj, movementObj.durationTo, 0);
                this._movementIndex++;
                if (this._movementIndex >= locMovementList.length)
                    this._movementIndex = 0;
            } else {
                if (this._movementIndex < locMovementList.length) {
                    movementObj = locMovementList[this._movementIndex];
                    this.play(movementObj, movementObj.durationTo, 0);
                    this._movementIndex++;
                } else
                    this._onMovementList = false;
            }
            this._onMovementList = true;
        }
    },
    setAnimationData: function (data) {
        if(this._animationData !== data)
            this._animationData = data;
    },
    getAnimationData: function () {
        return this._animationData;
    },
    getUserObject: function () {
        return this._userObject;
    },
    isIgnoreFrameEvent: function () {
        return this._ignoreFrameEvent;
    }
});
var _p = ccs.ArmatureAnimation.prototype;
_p.speedScale;
cc.defineGetterSetter(_p, "speedScale", _p.getSpeedScale, _p.setSpeedScale);
_p.animationScale;
cc.defineGetterSetter(_p, "animationScale", _p.getAnimationScale, _p.setAnimationScale);
_p = null;
ccs.ArmatureAnimation.create = function (armature) {
    return new ccs.ArmatureAnimation(armature);
};
ccs.Tween = ccs.ProcessBase.extend({
    _tweenData:null,
    _to:null,
    _from:null,
    _between:null,
    _movementBoneData:null,
    _bone:null,
    _frameTweenEasing:0,
    _betweenDuration:0,
    _totalDuration:0,
    _toIndex:0,
    _fromIndex:0,
    _animation:null,
    _passLastFrame:false,
    ctor:function (bone) {
        ccs.ProcessBase.prototype.ctor.call(this);
        this._frameTweenEasing = ccs.TweenType.LINEAR;
        ccs.Tween.prototype.init.call(this, bone);
    },
    init:function (bone) {
        this._from = new ccs.FrameData();
        this._between = new ccs.FrameData();
        this._bone = bone;
        this._tweenData = this._bone.getTweenData();
        this._tweenData.displayIndex = -1;
        this._animation = (this._bone !== null && this._bone.getArmature() !== null) ?
            this._bone.getArmature().getAnimation() :
            null;
        return true;
    },
    play:function (movementBoneData, durationTo, durationTween, loop, tweenEasing) {
        ccs.ProcessBase.prototype.play.call(this, durationTo, durationTween, loop, tweenEasing);
        this._loopType = (loop)?ccs.ANIMATION_TYPE_TO_LOOP_FRONT:ccs.ANIMATION_TYPE_NO_LOOP;
        this._totalDuration = 0;
        this._betweenDuration = 0;
        this._fromIndex = this._toIndex = 0;
        var difMovement = movementBoneData !== this._movementBoneData;
        this.setMovementBoneData(movementBoneData);
        this._rawDuration = this._movementBoneData.duration;
        var nextKeyFrame = this._movementBoneData.getFrameData(0);
        this._tweenData.displayIndex = nextKeyFrame.displayIndex;
        if (this._bone.getArmature().getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED)        {
            ccs.TransformHelp.nodeSub(this._tweenData, this._bone.getBoneData());
            this._tweenData.scaleX += 1;
            this._tweenData.scaleY += 1;
        }
        if (this._rawDuration === 0) {
            this._loopType = ccs.ANIMATION_TYPE_SINGLE_FRAME;
            if (durationTo === 0)
                this.setBetween(nextKeyFrame, nextKeyFrame);
            else
                this.setBetween(this._tweenData, nextKeyFrame);
            this._frameTweenEasing = ccs.TweenType.LINEAR;
        }
        else if (this._movementBoneData.frameList.length > 1) {
            this._durationTween = durationTween * this._movementBoneData.scale;
            if (loop && this._movementBoneData.delay !== 0)
                this.setBetween(this._tweenData, this.tweenNodeTo(this.updateFrameData(1 - this._movementBoneData.delay), this._between));
            else {
                if (!difMovement || durationTo === 0)
                    this.setBetween(nextKeyFrame, nextKeyFrame);
                else
                    this.setBetween(this._tweenData, nextKeyFrame);
            }
        }
        this.tweenNodeTo(0);
    },
    gotoAndPlay: function (frameIndex) {
        ccs.ProcessBase.prototype.gotoFrame.call(this, frameIndex);
        this._totalDuration = 0;
        this._betweenDuration = 0;
        this._fromIndex = this._toIndex = 0;
        this._isPlaying = true;
        this._isComplete = this._isPause = false;
        this._currentPercent = this._curFrameIndex / (this._rawDuration-1);
        this._currentFrame = this._nextFrameIndex * this._currentPercent;
    },
    gotoAndPause: function (frameIndex) {
        this.gotoAndPlay(frameIndex);
        this.pause();
    },
    updateHandler:function () {
        var locCurrentPercent = this._currentPercent == null ? 1 : this._currentPercent;
        var locLoopType = this._loopType;
        if (locCurrentPercent >= 1) {
            switch (locLoopType) {
                case ccs.ANIMATION_TYPE_SINGLE_FRAME:
                    locCurrentPercent = 1;
                    this._isComplete = true;
                    this._isPlaying = false;
                    break;
                case ccs.ANIMATION_TYPE_NO_LOOP:
                    locLoopType = ccs.ANIMATION_TYPE_MAX;
                    if (this._durationTween <= 0)
                        locCurrentPercent = 1;
                    else
                        locCurrentPercent = (locCurrentPercent - 1) * this._nextFrameIndex / this._durationTween;
                    if (locCurrentPercent >= 1) {
                        locCurrentPercent = 1;
                        this._isComplete = true;
                        this._isPlaying = false;
                        break;
                    } else {
                        this._nextFrameIndex = this._durationTween;
                        this._currentFrame = locCurrentPercent * this._nextFrameIndex;
                        this._totalDuration = 0;
                        this._betweenDuration = 0;
                        this._fromIndex = this._toIndex = 0;
                        break;
                    }
                case ccs.ANIMATION_TYPE_TO_LOOP_FRONT:
                    locLoopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
                    this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1;
                    if (this._movementBoneData.delay !== 0) {
                        this._currentFrame = (1 - this._movementBoneData.delay) * this._nextFrameIndex;
                        locCurrentPercent = this._currentFrame / this._nextFrameIndex;
                    } else {
                        locCurrentPercent = 0;
                        this._currentFrame = 0;
                    }
                    this._totalDuration = 0;
                    this._betweenDuration = 0;
                    this._fromIndex = this._toIndex = 0;
                    break;
                case ccs.ANIMATION_TYPE_MAX:
                    locCurrentPercent = 1;
                    this._isComplete = true;
                    this._isPlaying = false;
                    break;
                default:
                    this._currentFrame = ccs.fmodf(this._currentFrame, this._nextFrameIndex);
                    break;
            }
        }
        if (locCurrentPercent < 1 && locLoopType < ccs.ANIMATION_TYPE_TO_LOOP_BACK)
            locCurrentPercent = Math.sin(locCurrentPercent * cc.PI / 2);
        this._currentPercent = locCurrentPercent;
        this._loopType = locLoopType;
        if (locLoopType > ccs.ANIMATION_TYPE_TO_LOOP_BACK)
            locCurrentPercent = this.updateFrameData(locCurrentPercent);
        if (this._frameTweenEasing !== ccs.TweenType.TWEEN_EASING_MAX)
            this.tweenNodeTo(locCurrentPercent);
    },
    setBetween:function (from, to, limit) {
        if(limit === undefined)
            limit = true;
        do {
            if (from.displayIndex < 0 && to.displayIndex >= 0) {
                this._from.copy(to);
                this._between.subtract(to, to, limit);
                break;
            }
            if (to.displayIndex < 0 && from.displayIndex >= 0) {
                this._from.copy(from);
                this._between.subtract(to, to, limit);
                break;
            }
            this._from.copy(from);
            this._between.subtract(from, to, limit);
        } while (0);
        if (!from.isTween){
            this._tweenData.copy(from);
            this._tweenData.isTween = true;
        }
        this.arriveKeyFrame(from);
    },
    arriveKeyFrame:function (keyFrameData) {
        if (keyFrameData) {
            var locBone = this._bone;
            var displayManager = locBone.getDisplayManager();
            var displayIndex = keyFrameData.displayIndex;
            if (!displayManager.getForceChangeDisplay())
                displayManager.changeDisplayWithIndex(displayIndex, false);
            this._tweenData.zOrder = keyFrameData.zOrder;
            locBone.updateZOrder();
            this._bone.setBlendFunc(keyFrameData.blendFunc);
            var childAramture = locBone.getChildArmature();
            if (childAramture) {
                if (keyFrameData.movement !== "")
                    childAramture.getAnimation().play(keyFrameData.movement);
            }
        }
    },
    tweenNodeTo:function (percent, node) {
        if (!node)
            node = this._tweenData;
        var locFrom = this._from;
        var locBetween = this._between;
        if (!locFrom.isTween)
            percent = 0;
        node.x = locFrom.x + percent * locBetween.x;
        node.y = locFrom.y + percent * locBetween.y;
        node.scaleX = locFrom.scaleX + percent * locBetween.scaleX;
        node.scaleY = locFrom.scaleY + percent * locBetween.scaleY;
        node.skewX = locFrom.skewX + percent * locBetween.skewX;
        node.skewY = locFrom.skewY + percent * locBetween.skewY;
        this._bone.setTransformDirty(true);
        if (node && locBetween.isUseColorInfo)
            this.tweenColorTo(percent, node);
        return node;
    },
    tweenColorTo:function(percent,node){
        var locFrom = this._from;
        var locBetween = this._between;
        node.a = locFrom.a + percent * locBetween.a;
        node.r = locFrom.r + percent * locBetween.r;
        node.g = locFrom.g + percent * locBetween.g;
        node.b = locFrom.b + percent * locBetween.b;
        this._bone.updateColor();
    },
    updateFrameData:function (currentPercent) {
        if (currentPercent > 1 && this._movementBoneData.delay !== 0)
            currentPercent = ccs.fmodf(currentPercent,1);
        var playedTime = (this._rawDuration-1) * currentPercent;
        var from, to;
        var locTotalDuration = this._totalDuration,locBetweenDuration = this._betweenDuration, locToIndex = this._toIndex;
        if (playedTime < locTotalDuration || playedTime >= locTotalDuration + locBetweenDuration) {
            var frames = this._movementBoneData.frameList;
            var length = frames.length;
            if (playedTime < frames[0].frameID){
                from = to = frames[0];
                this.setBetween(from, to);
                return this._currentPercent;
            }
            if (playedTime >= frames[length - 1].frameID) {
                if (this._passLastFrame) {
                    from = to = frames[length - 1];
                    this.setBetween(from, to);
                    return this._currentPercent;
                }
                this._passLastFrame = true;
            } else
                this._passLastFrame = false;
            do {
                this._fromIndex = locToIndex;
                from = frames[this._fromIndex];
                locTotalDuration = from.frameID;
                locToIndex = this._fromIndex + 1;
                if (locToIndex >= length)
                    locToIndex = 0;
                to = frames[locToIndex];
                if(from.strEvent && !this._animation.isIgnoreFrameEvent())
                    this._animation.frameEvent(this._bone, from.strEvent,from.frameID, playedTime);
                if (playedTime === from.frameID|| (this._passLastFrame && this._fromIndex === length-1))
                    break;
            } while  (playedTime < from.frameID || playedTime >= to.frameID);
            locBetweenDuration = to.frameID - from.frameID;
            this._frameTweenEasing = from.tweenEasing;
            this.setBetween(from, to, false);
            this._totalDuration = locTotalDuration;
            this._betweenDuration = locBetweenDuration;
            this._toIndex = locToIndex;
        }
        currentPercent = locBetweenDuration === 0 ? 0 : (playedTime - this._totalDuration) / this._betweenDuration;
        var tweenType = (this._frameTweenEasing !== ccs.TweenType.LINEAR) ? this._frameTweenEasing : this._tweenEasing;
        if (tweenType !== ccs.TweenType.TWEEN_EASING_MAX && tweenType !== ccs.TweenType.LINEAR && !this._passLastFrame) {
            currentPercent = ccs.TweenFunction.tweenTo(currentPercent, tweenType, this._from.easingParams);
        }
        return currentPercent;
    },
    setAnimation:function (animation) {
        this._animation = animation;
    },
    getAnimation:function () {
        return this._animation;
    },
    setMovementBoneData: function(data){
        this._movementBoneData = data;
    }
});
var _p = ccs.Tween.prototype;
_p.animation;
cc.defineGetterSetter(_p, "animation", _p.getAnimation, _p.setAnimation);
_p = null;
ccs.Tween.create = function (bone) {
    return new ccs.Tween(bone);
};
ccs.PT_RATIO = 32;
ccs.ColliderFilter = ccs.Class.extend({
    _collisionType: 0,
    _group: 0,
    _categoryBits: 0,
    _groupIndex: 0,
    _maskBits: 0,
    ctor: function (collisionType, group) {
        this._collisionType = collisionType || 0;
        this._group = group || 0;
    },
    updateShape: function (shape) {
        if(shape instanceof cp.Shape){
            shape.collision_type = this._collisionType;
            shape.group = this._group;
        }else if(shape instanceof Box2D.b2FilterData){
            var filter = new Box2D.b2FilterData();
            filter.categoryBits = this._categoryBits;
            filter.groupIndex = this._groupIndex;
            filter.maskBits = this._maskBits;
            shape.SetFilterData(filter);
        }
    }
});
ccs.ColliderBody = ccs.Class.extend({
    shape: null,
    coutourData: null,
    colliderFilter: null,
    _calculatedVertexList: null,
    ctor: function (contourData) {
        this.shape = null;
        this.coutourData = contourData;
        this.colliderFilter = new ccs.ColliderFilter();
        if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
            this._calculatedVertexList = [];
        }
    },
    getContourData: function () {
        return this.coutourData;
    },
    setColliderFilter: function (colliderFilter) {
        this.colliderFilter = colliderFilter;
    },
    getCalculatedVertexList: function () {
        return this._calculatedVertexList;
    },
    setB2Fixture: function(fixture){
        this._fixture = fixture;
    },
    getB2Fixture: function(){
        return this._fixture;
    },
    setShape: function (shape) {
        this.shape = shape;
    },
    getShape: function () {
        return this.shape;
    },
    setContourData: function (contourData) {
        this.coutourData = contourData;
    },
    getColliderFilter: function () {
        return this.colliderFilter;
    }
});
ccs.ColliderDetector = ccs.Class.extend({
    _colliderBodyList: null,
    _bone: null,
    _body: null,
    _active: false,
    _filter: null,
    helpPoint: cc.p(0, 0),
    ctor: function (bone) {
        this._colliderBodyList = [];
        this._bone = null;
        this._body = null;
        this._active = false;
        this._filter = null;
        ccs.ColliderDetector.prototype.init.call(this, bone);
    },
    init: function (bone) {
        this._colliderBodyList.length = 0;
        if (bone)
            this._bone = bone;
        this._filter = new ccs.ColliderFilter();
        return true;
    },
    addContourData: function (contourData) {
        var colliderBody = new ccs.ColliderBody(contourData);
        this._colliderBodyList.push(colliderBody);
        if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
            var calculatedVertexList = colliderBody.getCalculatedVertexList();
            var vertexList = contourData.vertexList;
            for (var i = 0; i < vertexList.length; i++) {
                var newVertex = new ccs.ContourVertex2(0, 0);
                calculatedVertexList.push(newVertex);
            }
        }
    },
    addContourDataList: function (contourDataList) {
        for (var i = 0; i < contourDataList.length; i++) {
            this.addContourData(contourDataList[i]);
        }
    },
    removeContourData: function (contourData) {
        var eraseList = [], i, locBodyList = this._colliderBodyList;
        for (i = 0; i < locBodyList.length; i++) {
            var body = locBodyList[i];
            if (body && body.getContourData() === contourData)
                eraseList.push(body);
        }
        for (i=0; i<eraseList.length; i++)
            cc.arrayRemoveObject(locBodyList, eraseList[i]);
    },
    removeAll: function () {
        this._colliderBodyList.length = 0;
    },
    setActive: function (active) {
        if (this._active === active)
            return;
        this._active = active;
        var locBody = this._body;
        var locShape;
        if (locBody) {
            var colliderBody = null;
            if (this._active) {
                for (var i = 0; i < this._colliderBodyList.length; i++) {
                    colliderBody = this._colliderBodyList[i];
                    locShape = colliderBody.getShape();
                    locBody.space.addShape(locShape);
                }
            } else {
                for (var i = 0; i < this._colliderBodyList.length; i++) {
                    colliderBody = this._colliderBodyList[i];
                    locShape = colliderBody.getShape();
                    locBody.space.removeShape(locShape);
                }
            }
        }
    },
    getActive: function () {
        return this._active;
    },
    getColliderBodyList: function(){
        return this._colliderBodyList;
    },
    setColliderFilter: function (filter) {
        this._filter = filter;
        var locBodyList = this._colliderBodyList;
        for(var i=0; i< locBodyList.length; i++){
            var colliderBody = locBodyList[i];
            colliderBody.setColliderFilter(filter);
            if (colliderBody.getShape())
                colliderBody.getColliderFilter().updateShape(colliderBody.getShape());
        }
    },
    getColliderFilter: function () {
        return this._filter;
    },
    updateTransform: function (t) {
        if (!this._active)
            return;
        var colliderBody = null;
        var locBody = this._body;
        var locHelpPoint = this.helpPoint;
        for (var i = 0; i < this._colliderBodyList.length; i++) {
            colliderBody = this._colliderBodyList[i];
            var contourData = colliderBody.getContourData();
            var shape = null;
            if (locBody) {
                shape = colliderBody.getShape();
            }
            var vs = contourData.vertexList;
            var cvs = colliderBody.getCalculatedVertexList();
            for (var j = 0; j < vs.length; j++) {
                locHelpPoint.x = vs[j].x;
                locHelpPoint.y = vs[j].y;
                locHelpPoint = cc.pointApplyAffineTransform(locHelpPoint, t);
                if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
                    var v = cc.p(0, 0);
                    v.x = locHelpPoint.x;
                    v.y = locHelpPoint.y;
                    cvs[j] = v;
                }
                if (shape) {
                    shape.verts[j * 2] = locHelpPoint.x;
                    shape.verts[j * 2 + 1] = locHelpPoint.y;
                }
            }
            if (shape) {
                for (var j = 0; j < vs.length; j++) {
                    var b = shape.verts[(j + 1) % shape.verts.length];
                    var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[j])));
                    if(shape.planes){
                        shape.planes[j].n = n;
                        shape.planes[j].d = cp.v.dot(n, shape.verts[j]);
                    }
                }
            }
        }
    },
    setBody: function (body) {
        this._body = body;
        var colliderBody, locBodyList = this._colliderBodyList;
        for (var i = 0; i < locBodyList.length; i++) {
            colliderBody = locBodyList[i];
            var contourData = colliderBody.getContourData(), verts = [];
            var vs = contourData.vertexList;
            for (var j = 0; j < vs.length; j++) {
                var v = vs[j];
                verts.push(v.x);
                verts.push(v.y);
            }
            var shape = new cp.PolyShape(this._body, verts, cp.vzero);
            shape.sensor = true;
            shape.data = this._bone;
            if (this._active)
                this._body.space.addShape(shape);
            colliderBody.setShape(shape);
            colliderBody.getColliderFilter().updateShape(shape);
        }
    },
    getBody: function () {
        return this._body;
    }
});
var _p = ccs.ColliderDetector.prototype;
_p.colliderFilter;
cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter);
_p.active;
cc.defineGetterSetter(_p, "active", _p.getActive, _p.setActive);
_p.body;
cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
_p = null;
ccs.ColliderDetector.create = function (bone) {
    return new ccs.ColliderDetector(bone);
};
ccs.Armature = ccs.Node.extend({
    animation: null,
    armatureData: null,
    batchNode: null,
    _textureAtlas: null,
    _parentBone: null,
    _boneDic: null,
    _topBoneList: null,
    _armatureIndexDic: null,
    _offsetPoint: null,
    version: 0,
    _armatureTransformDirty: true,
    _body: null,
    _blendFunc: null,
    _className: "Armature",
    ctor: function (name, parentBone) {
        cc.Node.prototype.ctor.call(this);
        this._name = "";
        this._topBoneList = [];
        this._armatureIndexDic = {};
        this._offsetPoint = cc.p(0, 0);
        this._armatureTransformDirty = true;
        this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
        name && ccs.Armature.prototype.init.call(this, name, parentBone);
    },
    init: function (name, parentBone) {
        cc.Node.prototype.init.call(this);
        if (parentBone)
            this._parentBone = parentBone;
        this.removeAllChildren();
        this.animation = new ccs.ArmatureAnimation();
        this.animation.init(this);
        this._boneDic = {};
        this._topBoneList.length = 0;
        var armatureDataManager = ccs.armatureDataManager;
        var animationData;
        if (name !== "") {
            animationData = armatureDataManager.getAnimationData(name);
            cc.assert(animationData, "AnimationData not exist!");
            this.animation.setAnimationData(animationData);
            var armatureData = armatureDataManager.getArmatureData(name);
            cc.assert(armatureData, "ArmatureData not exist!");
            this.armatureData = armatureData;
            var boneDataDic = armatureData.getBoneDataDic();
            for (var key in boneDataDic) {
                var bone = this.createBone(String(key));
                do {
                    var movData = animationData.getMovement(animationData.movementNames[0]);
                    if (!movData) break;
                    var _movBoneData = movData.getMovementBoneData(bone.getName());
                    if (!_movBoneData || _movBoneData.frameList.length <= 0) break;
                    var frameData = _movBoneData.getFrameData(0);
                    if (!frameData) break;
                    bone.getTweenData().copy(frameData);
                    bone.changeDisplayWithIndex(frameData.displayIndex, false);
                } while (0);
            }
            this.update(0);
            this.updateOffsetPoint();
        } else {
            name = "new_armature";
            this.armatureData = new ccs.ArmatureData();
            this.armatureData.name = name;
            animationData = new ccs.AnimationData();
            animationData.name = name;
            armatureDataManager.addArmatureData(name, this.armatureData);
            armatureDataManager.addAnimationData(name, animationData);
            this.animation.setAnimationData(animationData);
        }
        this._renderCmd.initShaderCache();
        this.setCascadeOpacityEnabled(true);
        this.setCascadeColorEnabled(true);
        return true;
    },
    addChild: function (child, localZOrder, tag) {
        if(child instanceof ccui.Widget){
            cc.log("Armature doesn't support to add Widget as its child, it will be fix soon.");
            return;
        }
        cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
    },
    createBone: function (boneName) {
        var existedBone = this.getBone(boneName);
        if (existedBone)
            return existedBone;
        var boneData = this.armatureData.getBoneData(boneName);
        var parentName = boneData.parentName;
        var bone = null;
        if (parentName) {
            this.createBone(parentName);
            bone = new ccs.Bone(boneName);
            this.addBone(bone, parentName);
        } else {
            bone = new ccs.Bone(boneName);
            this.addBone(bone, "");
        }
        bone.setBoneData(boneData);
        bone.getDisplayManager().changeDisplayWithIndex(-1, false);
        return bone;
    },
    addBone: function (bone, parentName) {
        cc.assert(bone, "Argument must be non-nil");
        var locBoneDic = this._boneDic;
        if(bone.getName())
            cc.assert(!locBoneDic[bone.getName()], "bone already added. It can't be added again");
        if (parentName) {
            var boneParent = locBoneDic[parentName];
            if (boneParent)
                boneParent.addChildBone(bone);
            else
                this._topBoneList.push(bone);
        } else
            this._topBoneList.push(bone);
        bone.setArmature(this);
        locBoneDic[bone.getName()] = bone;
        this.addChild(bone);
    },
    removeBone: function (bone, recursion) {
        cc.assert(bone, "bone must be added to the bone dictionary!");
        bone.setArmature(null);
        bone.removeFromParent(recursion);
        cc.arrayRemoveObject(this._topBoneList, bone);
        delete  this._boneDic[bone.getName()];
        this.removeChild(bone, true);
    },
    getBone: function (name) {
        return this._boneDic[name];
    },
    changeBoneParent: function (bone, parentName) {
        cc.assert(bone, "bone must be added to the bone dictionary!");
        var parentBone = bone.getParentBone();
        if (parentBone) {
            cc.arrayRemoveObject(parentBone.getChildren(), bone);
            bone.setParentBone(null);
        }
        if (parentName) {
            var boneParent = this._boneDic[parentName];
            if (boneParent) {
                boneParent.addChildBone(bone);
                cc.arrayRemoveObject(this._topBoneList, bone);
            } else
                this._topBoneList.push(bone);
        }
    },
    getBoneDic: function () {
        return this._boneDic;
    },
    updateOffsetPoint: function () {
        var rect = this.getBoundingBox();
        this.setContentSize(rect);
        var locOffsetPoint = this._offsetPoint;
        locOffsetPoint.x = -rect.x;
        locOffsetPoint.y = -rect.y;
        if (rect.width !== 0 && rect.height !== 0)
            this.setAnchorPoint(locOffsetPoint.x / rect.width, locOffsetPoint.y / rect.height);
    },
    getOffsetPoints: function(){
        return {x: this._offsetPoint.x, y: this._offsetPoint.y};
    },
    setAnimation: function (animation) {
        this.animation = animation;
    },
    getAnimation: function () {
        return this.animation;
    },
    getArmatureTransformDirty: function () {
        return this._armatureTransformDirty;
    },
    update: function (dt) {
        this.animation.update(dt);
        var locTopBoneList = this._topBoneList;
        for (var i = 0; i < locTopBoneList.length; i++)
            locTopBoneList[i].update(dt);
        this._armatureTransformDirty = false;
    },
    onEnter: function () {
        cc.Node.prototype.onEnter.call(this);
        this.scheduleUpdate();
    },
    onExit: function () {
        cc.Node.prototype.onExit.call(this);
        this.unscheduleUpdate();
    },
    getBoundingBox: function(){
        var minX, minY, maxX, maxY = 0;
        var first = true;
        var boundingBox = cc.rect(0, 0, 0, 0), locChildren = this._children;
        var len = locChildren.length;
        for (var i=0; i<len; i++) {
            var bone = locChildren[i];
            if (bone) {
                var r = bone.getDisplayManager().getBoundingBox();
                if (r.x === 0 && r.y === 0 && r.width === 0 && r.height === 0)
                    continue;
                if(first) {
                    minX = r.x;
                    minY = r.y;
                    maxX = r.x + r.width;
                    maxY = r.y + r.height;
                    first = false;
                } else {
                    minX = r.x < boundingBox.x ? r.x : boundingBox.x;
                    minY = r.y < boundingBox.y ? r.y : boundingBox.y;
                    maxX = r.x + r.width > boundingBox.x + boundingBox.width ?
                        r.x + r.width : boundingBox.x + boundingBox.width;
                    maxY = r.y + r.height > boundingBox.y + boundingBox.height ?
                        r.y + r.height : boundingBox.y + boundingBox.height;
                }
                boundingBox.x = minX;
                boundingBox.y = minY;
                boundingBox.width = maxX - minX;
                boundingBox.height = maxY - minY;
            }
        }
        return cc.rectApplyAffineTransform(boundingBox, this.getNodeToParentTransform());
    },
    getBoneAtPoint: function (x, y) {
        var locChildren = this._children;
        for (var i = locChildren.length - 1; i >= 0; i--) {
            var child = locChildren[i];
            if (child instanceof ccs.Bone && child.getDisplayManager().containPoint(x, y))
                return child;
        }
        return null;
    },
    setParentBone: function (parentBone) {
        this._parentBone = parentBone;
        var locBoneDic = this._boneDic;
        for (var key in locBoneDic) {
            locBoneDic[key].setArmature(this);
        }
    },
    getParentBone: function () {
        return this._parentBone;
    },
    drawContour: function () {
        cc._drawingUtil.setDrawColor(255, 255, 255, 255);
        cc._drawingUtil.setLineWidth(1);
        var locBoneDic = this._boneDic;
        for (var key in locBoneDic) {
            var bone = locBoneDic[key];
            var detector = bone.getColliderDetector();
            if(!detector)
                continue;
            var bodyList = detector.getColliderBodyList();
            for (var i = 0; i < bodyList.length; i++) {
                var body = bodyList[i];
                var vertexList = body.getCalculatedVertexList();
                cc._drawingUtil.drawPoly(vertexList, vertexList.length, true);
            }
        }
    },
    setBody: function (body) {
        if (this._body === body)
            return;
        this._body = body;
        this._body.data = this;
        var child, displayObject, locChildren = this._children;
        for (var i = 0; i < locChildren.length; i++) {
            child = locChildren[i];
            if (child instanceof ccs.Bone) {
                var displayList = child.getDisplayManager().getDecorativeDisplayList();
                for (var j = 0; j < displayList.length; j++) {
                    displayObject = displayList[j];
                    var detector = displayObject.getColliderDetector();
                    if (detector)
                        detector.setBody(this._body);
                }
            }
        }
    },
    getShapeList: function () {
        if (this._body)
            return this._body.shapeList;
        return null;
    },
    getBody: function () {
        return this._body;
    },
    setBlendFunc: function (blendFunc, dst) {
        if(dst === undefined){
            this._blendFunc.src = blendFunc.src;
            this._blendFunc.dst = blendFunc.dst;
        } else {
            this._blendFunc.src = blendFunc;
            this._blendFunc.dst = dst;
        }
    },
    getBlendFunc: function () {
        return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
    },
    setColliderFilter: function (filter) {
        var locBoneDic = this._boneDic;
        for (var key in locBoneDic)
            locBoneDic[key].setColliderFilter(filter);
    },
    getArmatureData: function () {
        return this.armatureData;
    },
    setArmatureData: function (armatureData) {
        this.armatureData = armatureData;
    },
    getBatchNode: function () {
        return this.batchNode;
    },
    setBatchNode: function (batchNode) {
        this.batchNode = batchNode;
    },
    getVersion: function () {
        return this.version;
    },
    setVersion: function (version) {
        this.version = version;
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new ccs.Armature.CanvasRenderCmd(this);
        else
            return new ccs.Armature.WebGLRenderCmd(this);
    }
});
var _p = ccs.Armature.prototype;
_p.parentBone;
cc.defineGetterSetter(_p, "parentBone", _p.getParentBone, _p.setParentBone);
_p.body;
cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
_p.colliderFilter;
cc.defineGetterSetter(_p, "colliderFilter", null, _p.setColliderFilter);
_p = null;
ccs.Armature.create = function (name, parentBone) {
    return new ccs.Armature(name, parentBone);
};
(function(){
    ccs.Armature.RenderCmd = {
        _updateAnchorPointInPoint: function(){
            var node = this._node;
            var contentSize = node._contentSize, anchorPoint = node._anchorPoint, offsetPoint = node._offsetPoint;
            this._anchorPointInPoints.x = contentSize.width * anchorPoint.x - offsetPoint.x;
            this._anchorPointInPoints.y = contentSize.height * anchorPoint.y - offsetPoint.y;
            this._realAnchorPointInPoints.x = contentSize.width * anchorPoint.x;
            this._realAnchorPointInPoints.y = contentSize.height * anchorPoint.y;
            this.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        },
        getAnchorPointInPoints: function(){
            return cc.p(this._realAnchorPointInPoints);
        }
    };
})();
(function(){
    ccs.Armature.CanvasRenderCmd = function(renderableObject){
        cc.Node.CanvasRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._realAnchorPointInPoints = new cc.Point(0,0);
        this._canUseDirtyRegion = true;
        this._startRenderCmd = new cc.CustomRenderCmd(this, this._startCmdCallback);
        this._RestoreRenderCmd = new cc.CustomRenderCmd(this, this._RestoreCmdCallback);
        this._startRenderCmd._canUseDirtyRegion = true;
        this._RestoreRenderCmd._canUseDirtyRegion = true;
    };
    var proto = ccs.Armature.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    cc.inject(ccs.Armature.RenderCmd, proto);
    proto.constructor = ccs.Armature.CanvasRenderCmd;
    proto._startCmdCallback = function(ctx, scaleX, scaleY){
        var node = this._node, parent = node._parent;
        this.transform(parent ? parent._renderCmd : null);
        var wrapper = ctx || cc._renderContext;
        wrapper.save();
        wrapper._switchToArmatureMode(true, this._worldTransform, scaleX, scaleY);
    };
    proto.transform = function(parentCmd, recursive){
        ccs.Node.CanvasRenderCmd.prototype.transform.call(this, parentCmd, recursive);
        var locChildren = this._node._children;
        for (var i = 0, len = locChildren.length; i< len; i++) {
            var selBone = locChildren[i];
            var boneCmd = selBone._renderCmd;
            if (selBone && selBone.getDisplayRenderNode) {
                var boneType = selBone.getDisplayRenderNodeType();
                var selNode = selBone.getDisplayRenderNode();
                if (selNode && selNode._renderCmd){
                    var cmd = selNode._renderCmd;
                    cmd.transform(null);
                    if (boneType !== ccs.DISPLAY_TYPE_ARMATURE && boneType !== ccs.DISPLAY_TYPE_SPRITE) {
                        cc.affineTransformConcatIn(cmd._worldTransform, selBone._worldTransform);
                    }
                    var flags = cc.Node._dirtyFlags, locFlag = cmd._dirtyFlag, boneFlag = boneCmd._dirtyFlag;
                    var colorDirty = boneFlag & flags.colorDirty,
                        opacityDirty = boneFlag & flags.opacityDirty;
                    if (colorDirty)
                        boneCmd._updateDisplayColor();
                    if (opacityDirty)
                        boneCmd._updateDisplayOpacity();
                    if (colorDirty || opacityDirty)
                        boneCmd._updateColor();
                    var parentColor = selBone._renderCmd._displayedColor, parentOpacity = selBone._renderCmd._displayedOpacity;
                    colorDirty = locFlag & flags.colorDirty;
                    opacityDirty = locFlag & flags.opacityDirty;
                    if (colorDirty)
                        cmd._updateDisplayColor(parentColor);
                    if (opacityDirty)
                        cmd._updateDisplayOpacity(parentOpacity);
                    if (colorDirty || opacityDirty) {
                        cmd._updateColor();
                    }
                }
            }
        }
    };
    proto._RestoreCmdCallback = function(wrapper){
        this._cacheDirty = false;
        wrapper._switchToArmatureMode(false);
        wrapper.restore();
    };
    proto.initShaderCache = function(){};
    proto.setShaderProgram = function(){};
    proto.updateChildPosition = function(dis, bone){
        dis.visit();
    };
    proto.rendering = function(ctx, scaleX, scaleY){
        var node = this._node;
        var locChildren = node._children;
        var alphaPremultiplied = cc.BlendFunc.ALPHA_PREMULTIPLIED, alphaNonPremultipled = cc.BlendFunc.ALPHA_NON_PREMULTIPLIED;
        for (var i = 0, len = locChildren.length; i< len; i++) {
            var selBone = locChildren[i];
            if (selBone && selBone.getDisplayRenderNode) {
                var selNode = selBone.getDisplayRenderNode();
                if (null === selNode)
                    continue;
                var boneCmd = selBone._renderCmd;
                boneCmd._syncStatus(this);
                switch (selBone.getDisplayRenderNodeType()) {
                    case ccs.DISPLAY_TYPE_SPRITE:
                        selNode._renderCmd.visit(boneCmd);
                        break;
                    case ccs.DISPLAY_TYPE_ARMATURE:
                        selNode._renderCmd.rendering(ctx, scaleX, scaleY);
                        break;
                    default:
                        selNode._renderCmd.visit(boneCmd);
                        break;
                }
            } else if(selBone instanceof cc.Node) {
                this._visitNormalChild(selBone);
            }
        }
    };
    proto._visitNormalChild = function(childNode){
        if (!childNode)
            return;
        var cmd = childNode._renderCmd;
        if (!childNode._visible)
            return;
        cmd._curLevel = this._curLevel + 1;
        var i, children = childNode._children, child;
        cmd._syncStatus(this);
        cmd.transform(null);
        var len = children.length;
        if (len > 0) {
            childNode.sortAllChildren();
            for (i = 0; i < len; i++) {
                child = children[i];
                if (child._localZOrder < 0)
                    child._renderCmd.visit(cmd);
                else
                    break;
            }
            cc.renderer.pushRenderCommand(cmd);
            for (; i < len; i++)
                children[i]._renderCmd.visit(cmd);
        } else {
            cc.renderer.pushRenderCommand(cmd);
        }
        this._dirtyFlag = 0;
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        this._syncStatus(parentCmd);
        node.sortAllChildren();
        cc.renderer.pushRenderCommand(this._startRenderCmd);
        this.rendering();
        cc.renderer.pushRenderCommand(this._RestoreRenderCmd);
        this._cacheDirty = false;
    };
})();
ccs.Bone = ccs.Node.extend({
    _boneData: null,
    _armature: null,
    _childArmature: null,
    _displayManager: null,
    ignoreMovementBoneData: false,
    _tween: null,
    _tweenData: null,
    _parentBone: null,
    _boneTransformDirty: false,
    _worldTransform: null,
    _blendFunc: null,
    blendDirty: false,
    _worldInfo: null,
    _armatureParentBone: null,
    _dataVersion: 0,
    _className: "Bone",
    ctor: function (name) {
        cc.Node.prototype.ctor.call(this);
        this._tweenData = null;
        this._parentBone = null;
        this._armature = null;
        this._childArmature = null;
        this._boneData = null;
        this._tween = null;
        this._displayManager = null;
        this.ignoreMovementBoneData = false;
        this._worldTransform = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
        this._boneTransformDirty = true;
        this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
        this.blendDirty = false;
        this._worldInfo = null;
        this._armatureParentBone = null;
        this._dataVersion = 0;
        ccs.Bone.prototype.init.call(this, name);
    },
    init: function (name) {
        if (name)
            this._name = name;
        this._tweenData = new ccs.FrameData();
        this._tween = new ccs.Tween(this);
        this._displayManager = new ccs.DisplayManager(this);
        this._worldInfo = new ccs.BaseData();
        this._boneData = new ccs.BaseData();
        return true;
    },
    setBoneData: function (boneData) {
        cc.assert(boneData, "_boneData must not be null");
        if(this._boneData !== boneData)
            this._boneData = boneData;
        this.setName(this._boneData.name);
        this._localZOrder = this._boneData.zOrder;
        this._displayManager.initDisplayList(boneData);
    },
    getBoneData: function () {
        return this._boneData;
    },
    setArmature: function (armature) {
        this._armature = armature;
        if (armature) {
            this._tween.setAnimation(this._armature.getAnimation());
            this._dataVersion = this._armature.getArmatureData().dataVersion;
            this._armatureParentBone = this._armature.getParentBone();
        } else
            this._armatureParentBone = null;
    },
    getArmature: function () {
        return this._armature;
    },
    update: function (delta) {
        if (this._parentBone)
            this._boneTransformDirty = this._boneTransformDirty || this._parentBone.isTransformDirty();
        if (this._armatureParentBone && !this._boneTransformDirty)
            this._boneTransformDirty = this._armatureParentBone.isTransformDirty();
        if (this._boneTransformDirty){
            var locTweenData = this._tweenData;
            if (this._dataVersion >= ccs.CONST_VERSION_COMBINED){
                ccs.TransformHelp.nodeConcat(locTweenData, this._boneData);
                locTweenData.scaleX -= 1;
                locTweenData.scaleY -= 1;
            }
            var locWorldInfo = this._worldInfo;
            locWorldInfo.copy(locTweenData);
            locWorldInfo.x = locTweenData.x + this._position.x;
            locWorldInfo.y = locTweenData.y + this._position.y;
            locWorldInfo.scaleX = locTweenData.scaleX * this._scaleX;
            locWorldInfo.scaleY = locTweenData.scaleY * this._scaleY;
            locWorldInfo.skewX = locTweenData.skewX + this._skewX + cc.degreesToRadians(this._rotationX);
            locWorldInfo.skewY = locTweenData.skewY + this._skewY - cc.degreesToRadians(this._rotationY);
            if(this._parentBone)
                this._applyParentTransform(this._parentBone);
            else {
                if (this._armatureParentBone)
                    this._applyParentTransform(this._armatureParentBone);
            }
            ccs.TransformHelp.nodeToMatrix(locWorldInfo, this._worldTransform);
            if (this._armatureParentBone)
                cc.affineTransformConcatIn(this._worldTransform, this._armature.getNodeToParentTransform());
        }
        ccs.displayFactory.updateDisplay(this, delta, this._boneTransformDirty || this._armature.getArmatureTransformDirty());
        for(var i=0; i<this._children.length; i++) {
            var childBone = this._children[i];
            childBone.update(delta);
        }
        this._boneTransformDirty = false;
    },
    _applyParentTransform: function (parent) {
        var locWorldInfo = this._worldInfo;
        var locParentWorldTransform = parent._worldTransform;
        var locParentWorldInfo = parent._worldInfo;
        var x = locWorldInfo.x;
        var y = locWorldInfo.y;
        locWorldInfo.x = x * locParentWorldTransform.a + y * locParentWorldTransform.c + locParentWorldInfo.x;
        locWorldInfo.y = x * locParentWorldTransform.b + y * locParentWorldTransform.d + locParentWorldInfo.y;
        locWorldInfo.scaleX = locWorldInfo.scaleX * locParentWorldInfo.scaleX;
        locWorldInfo.scaleY = locWorldInfo.scaleY * locParentWorldInfo.scaleY;
        locWorldInfo.skewX = locWorldInfo.skewX + locParentWorldInfo.skewX;
        locWorldInfo.skewY = locWorldInfo.skewY + locParentWorldInfo.skewY;
    },
    setBlendFunc: function (blendFunc, dst) {
        var locBlendFunc = this._blendFunc, srcValue, dstValue;
        if(dst === undefined){
            srcValue = blendFunc.src;
            dstValue = blendFunc.dst;
        } else {
            srcValue = blendFunc;
            dstValue = dst;
        }
        if (locBlendFunc.src !== srcValue || locBlendFunc.dst !== dstValue) {
            locBlendFunc.src = srcValue;
            locBlendFunc.dst = dstValue;
            this.blendDirty = true;
        }
    },
    updateColor: function () {
        var display = this._displayManager.getDisplayRenderNode();
        if (display !== null) {
            var cmd = this._renderCmd;
            display.setColor(
                cc.color(
                        cmd._displayedColor.r * this._tweenData.r / 255,
                        cmd._displayedColor.g * this._tweenData.g / 255,
                        cmd._displayedColor.b * this._tweenData.b / 255));
            display.setOpacity(cmd._displayedOpacity * this._tweenData.a / 255);
        }
    },
    updateZOrder: function () {
        if (this._armature.getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED) {
            this.setLocalZOrder(this._tweenData.zOrder + this._boneData.zOrder);
        } else {
            this.setLocalZOrder(this._tweenData.zOrder);
        }
    },
    addChildBone: function (child) {
        cc.assert(child, "Argument must be non-nil");
        cc.assert(!child.parentBone, "child already added. It can't be added again");
        if (this._children.indexOf(child) < 0) {
            this._children.push(child);
            child.setParentBone(this);
        }
    },
    removeChildBone: function (bone, recursion) {
        if (this._children.length > 0 && this._children.getIndex(bone) !== -1 ) {
            if(recursion) {
                var ccbones = bone._children;
                for(var i=0; i<ccbones.length; i++){
                    var ccBone = ccbones[i];
                    bone.removeChildBone(ccBone, recursion);
                }
            }
            bone.setParentBone(null);
            bone.getDisplayManager().setCurrentDecorativeDisplay(null);
            cc.arrayRemoveObject(this._children, bone);
        }
    },
    removeFromParent: function (recursion) {
        if (this._parentBone)
            this._parentBone.removeChildBone(this, recursion);
    },
    setParentBone: function (parent) {
        this._parentBone = parent;
    },
    getParentBone: function(){
        return this._parentBone;
    },
    setChildArmature: function (armature) {
        if (this._childArmature !== armature) {
            if (armature == null && this._childArmature)
                this._childArmature.setParentBone(null);
            this._childArmature = armature;
        }
    },
    getChildArmature: function () {
        return this._childArmature;
    },
    getTween: function () {
        return this._tween;
    },
    setLocalZOrder: function (zOrder) {
        if (this._localZOrder !== zOrder)
            cc.Node.prototype.setLocalZOrder.call(this, zOrder);
    },
    getNodeToArmatureTransform: function(){
        return this._worldTransform;
    },
    getNodeToWorldTransform: function(){
        return cc.affineTransformConcat(this._worldTransform, this._armature.getNodeToWorldTransform());
    },
    getDisplayRenderNode: function () {
        return this._displayManager.getDisplayRenderNode();
    },
    getDisplayRenderNodeType: function () {
        return this._displayManager.getDisplayRenderNodeType();
    },
    addDisplay: function (displayData, index) {
        index = index || 0;
        return this._displayManager.addDisplay(displayData, index);
    },
    removeDisplay: function (index) {
        this._displayManager.removeDisplay(index);
    },
    changeDisplayByIndex: function (index, force) {
        cc.log("changeDisplayByIndex is deprecated. Use changeDisplayWithIndex instead.");
        this.changeDisplayWithIndex(index, force);
    },
    changeDisplayByName: function(name, force){
        cc.log("changeDisplayByName is deprecated. Use changeDisplayWithName instead.");
        this.changeDisplayWithName(name, force);
    },
    changeDisplayWithIndex: function (index, force) {
        this._displayManager.changeDisplayWithIndex(index, force);
    },
    changeDisplayWithName: function (name, force) {
        this._displayManager.changeDisplayWithName(name, force);
    },
    getColliderDetector: function(){
        var decoDisplay = this._displayManager.getCurrentDecorativeDisplay();
        if (decoDisplay){
            var detector = decoDisplay.getColliderDetector();
            if (detector)
                return detector;
        }
        return null;
    },
    setColliderFilter: function (filter) {
        var displayList = this._displayManager.getDecorativeDisplayList();
        for (var i = 0; i < displayList.length; i++) {
            var locDecoDisplay = displayList[i];
            var locDetector = locDecoDisplay.getColliderDetector();
            if (locDetector)
                locDetector.setColliderFilter(filter);
        }
    },
    getColliderFilter: function () {
        var decoDisplay = this.displayManager.getCurrentDecorativeDisplay();
        if (decoDisplay) {
            var detector = decoDisplay.getColliderDetector();
            if (detector)
                return detector.getColliderFilter();
        }
        return null;
    },
    setTransformDirty: function (dirty) {
        this._boneTransformDirty = dirty;
    },
    isTransformDirty: function () {
        return this._boneTransformDirty;
    },
    getDisplayManager: function () {
        return this._displayManager;
    },
    setIgnoreMovementBoneData: function (bool) {
        this._ignoreMovementBoneData = bool;
    },
    isIgnoreMovementBoneData: function(){
        return this._ignoreMovementBoneData;
    },
    getBlendFunc: function () {
        return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
    },
    setBlendDirty: function (dirty) {
        this._blendDirty = dirty;
    },
    isBlendDirty: function () {
        return this._blendDirty;
    },
    getTweenData: function () {
        return this._tweenData;
    },
    getWorldInfo: function(){
        return this._worldInfo;
    },
    getChildrenBone: function () {
        return this._children;
    },
    nodeToArmatureTransform: function () {
        return this.getNodeToArmatureTransform();
    },
    nodeToWorldTransform: function () {
        return this.getNodeToWorldTransform();
    },
    getColliderBodyList: function () {
        var detector = this.getColliderDetector();
        if(detector)
            return detector.getColliderBodyList();
        return null;
    },
    getIgnoreMovementBoneData: function () {
        return this.isIgnoreMovementBoneData();
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new ccs.Bone.CanvasRenderCmd(this);
        else
            return new ccs.Bone.WebGLRenderCmd(this);
    }
});
var _p = ccs.Bone.prototype;
_p.boneData;
cc.defineGetterSetter(_p, "boneData", _p.getBoneData, _p.setBoneData);
_p.armature;
cc.defineGetterSetter(_p, "armature", _p.getArmature, _p.setArmature);
_p.childArmature;
cc.defineGetterSetter(_p, "childArmature", _p.getChildArmature, _p.setChildArmature);
_p.childrenBone;
cc.defineGetterSetter(_p, "childrenBone", _p.getChildrenBone);
_p.tween;
cc.defineGetterSetter(_p, "tween", _p.getTween);
_p.tweenData;
cc.defineGetterSetter(_p, "tweenData", _p.getTweenData);
_p.colliderFilter;
cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter);
_p = null;
ccs.Bone.create = function (name) {
    return new ccs.Bone(name);
};
ccs.Bone.RenderCmd = {
    _updateColor: function () {
        var node = this._node;
        var display = node._displayManager.getDisplayRenderNode();
        if (display !== null) {
            var displayCmd = display._renderCmd;
            display.setColor(this._displayedColor);
            display.setOpacity(this._displayedOpacity);
            displayCmd._syncDisplayColor(node._tweenData);
            displayCmd._syncDisplayOpacity(node._tweenData.a);
            displayCmd._updateColor();
        }
    },
    transform: function (parentCmd, recursive) {
        var node = this._node,
            t = this._transform,
            wt = this._worldTransform,
            pt = parentCmd ? parentCmd._worldTransform : null;
        if (pt) {
            this.originTransform();
            cc.affineTransformConcatIn(t, node._worldTransform);
        }
        if (pt) {
            wt.a  = t.a  * pt.a + t.b  * pt.c;
            wt.b  = t.a  * pt.b + t.b  * pt.d;
            wt.c  = t.c  * pt.a + t.d  * pt.c;
            wt.d  = t.c  * pt.b + t.d  * pt.d;
            wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
            wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
        }
        else {
            wt.a  = t.a;
            wt.b  = t.b;
            wt.c  = t.c;
            wt.d  = t.d;
            wt.tx = t.tx;
            wt.ty = t.ty;
        }
    }
};
(function(){
    ccs.Bone.CanvasRenderCmd  = function(renderable){
        cc.Node.CanvasRenderCmd.call(this, renderable);
        this._needDraw = false;
    };
    var proto = ccs.Bone.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
    cc.inject(ccs.Bone.RenderCmd, proto);
    proto.constructor = ccs.Bone.CanvasRenderCmd;
})();
(function(){
    if(!cc.Node.WebGLRenderCmd)
        return;
    ccs.Bone.WebGLRenderCmd = function(renderable){
        cc.Node.WebGLRenderCmd.call(this, renderable);
        this._needDraw = false;
    };
    var proto = ccs.Bone.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    cc.inject(ccs.Bone.RenderCmd, proto);
    proto.constructor = ccs.Bone.WebGLRenderCmd;
})();
ccs.FRAME_TYPE_MOVE = 0;
ccs.FRAME_TYPE_SCALE = 1;
ccs.FRAME_TYPE_ROTATE = 2;
ccs.FRAME_TYPE_TINT = 3;
ccs.FRAME_TYPE_FADE = 4;
ccs.FRAME_TYPE_MAX = 5;
ccs.FrameEaseType = {
    CUSTOM : -1,
    LINEAR : 0,
    SINE_EASEIN : 1,
    SINE_EASEOUT : 2,
    SINE_EASEINOUT : 3,
    QUAD_EASEIN : 4,
    QUAD_EASEOUT : 5,
    QUAD_EASEINOUT : 6,
    CUBIC_EASEIN : 7,
    CUBIC_EASEOUT : 8,
    CUBIC_EASEINOUT : 9,
    QUART_EASEIN : 10,
    QUART_EASEOUT : 11,
    QUART_EASEINOUT : 12,
    QUINT_EASEIN : 13,
    QUINT_EASEOUT : 14,
    QUINT_EASEINOUT : 15,
    EXPO_EASEIN : 16,
    EXPO_EASEOUT : 17,
    EXPO_EASEINOUT : 18,
    CIRC_EASEIN : 19,
    CIRC_EASEOUT : 20,
    CIRC_EASEINOUT : 21,
    ELASTIC_EASEIN : 22,
    ELASTIC_EASEOUT : 23,
    ELASTIC_EASEINOUT : 24,
    BACK_EASEIN : 25,
    BACK_EASEOUT : 26,
    BACK_EASEINOUT : 27,
    BOUNCE_EASEIN : 28,
    BOUNCE_EASEOUT : 29,
    BOUNCE_EASEINOUT : 30,
    TWEEN_EASING_MAX: 1000
};
ccs.ActionFrame = ccs.Class.extend({
    frameType: 0,
    easingType: 0,
    frameIndex: 0,
    _Parameter: null,
    time: 0,
    ctor: function () {
        this.frameType = 0;
        this.easingType = ccs.FrameEaseType.LINEAR;
        this.frameIndex = 0;
        this.time = 0;
    },
    getAction: function (duration, srcFrame) {
        cc.log("Need a definition of <getAction> for ActionFrame");
        return null;
    },
    _getEasingAction : function (action) {
        if (action === null) {
            console.error("Action cannot be null!");
            return null;
        }
        var resultAction;
        switch (this.easingType) {
            case ccs.FrameEaseType.CUSTOM:
                break;
            case ccs.FrameEaseType.LINEAR:
                resultAction = action;
                break;
            case ccs.FrameEaseType.SINE_EASEIN:
                resultAction = action.easing(cc.easeSineIn());
                break;
            case ccs.FrameEaseType.SINE_EASEOUT:
                resultAction = action.easing(cc.easeSineOut());
                break;
            case ccs.FrameEaseType.SINE_EASEINOUT:
                resultAction = action.easing(cc.easeSineInOut());
                break;
            case ccs.FrameEaseType.QUAD_EASEIN:
                resultAction = action.easing(cc.easeQuadraticActionIn());
                break;
            case ccs.FrameEaseType.QUAD_EASEOUT:
                resultAction = action.easing(cc.easeQuadraticActionOut());
                break;
            case ccs.FrameEaseType.QUAD_EASEINOUT:
                resultAction = action.easing(cc.easeQuadraticActionInOut());
                break;
            case ccs.FrameEaseType.CUBIC_EASEIN:
                resultAction = action.easing(cc.easeCubicActionIn());
                break;
            case ccs.FrameEaseType.CUBIC_EASEOUT:
                resultAction = action.easing(cc.easeCubicActionOut());
                break;
            case ccs.FrameEaseType.CUBIC_EASEINOUT:
                resultAction = action.easing(cc.easeCubicActionInOut());
                break;
            case ccs.FrameEaseType.QUART_EASEIN:
                resultAction = action.easing(cc.easeQuarticActionIn());
                break;
            case ccs.FrameEaseType.QUART_EASEOUT:
                resultAction = action.easing(cc.easeQuarticActionOut());
                break;
            case ccs.FrameEaseType.QUART_EASEINOUT:
                resultAction = action.easing(cc.easeQuarticActionInOut());
                break;
            case ccs.FrameEaseType.QUINT_EASEIN:
                resultAction = action.easing(cc.easeQuinticActionIn());
                break;
            case ccs.FrameEaseType.QUINT_EASEOUT:
                resultAction = action.easing(cc.easeQuinticActionOut());
                break;
            case ccs.FrameEaseType.QUINT_EASEINOUT:
                resultAction = action.easing(cc.easeQuinticActionInOut());
                break;
            case ccs.FrameEaseType.EXPO_EASEIN:
                resultAction = action.easing(cc.easeExponentialIn());
                break;
            case ccs.FrameEaseType.EXPO_EASEOUT:
                resultAction = action.easing(cc.easeExponentialOut());
                break;
            case ccs.FrameEaseType.EXPO_EASEINOUT:
                resultAction = action.easing(cc.easeExponentialInOut());
                break;
            case ccs.FrameEaseType.CIRC_EASEIN:
                resultAction = action.easing(cc.easeCircleActionIn());
                break;
            case ccs.FrameEaseType.CIRC_EASEOUT:
                resultAction = action.easing(cc.easeCircleActionOut());
                break;
            case ccs.FrameEaseType.CIRC_EASEINOUT:
                resultAction = action.easing(cc.easeCircleActionInOut());
                break;
            case ccs.FrameEaseType.ELASTIC_EASEIN:
                resultAction = action.easing(cc.easeElasticIn());
                break;
            case ccs.FrameEaseType.ELASTIC_EASEOUT:
                resultAction = action.easing(cc.easeElasticOut());
                break;
            case ccs.FrameEaseType.ELASTIC_EASEINOUT:
                resultAction = action.easing(cc.easeElasticInOut());
                break;
            case ccs.FrameEaseType.BACK_EASEIN:
                resultAction = action.easing(cc.easeBackIn());
                break;
            case ccs.FrameEaseType.BACK_EASEOUT:
                resultAction = action.easing(cc.easeBackOut());
                break;
            case ccs.FrameEaseType.BACK_EASEINOUT:
                resultAction = action.easing(cc.easeBackInOut());
                break;
            case ccs.FrameEaseType.BOUNCE_EASEIN:
                resultAction = action.easing(cc.easeBounceIn());
                break;
            case ccs.FrameEaseType.BOUNCE_EASEOUT:
                resultAction = action.easing(cc.easeBounceOut());
                break;
            case ccs.FrameEaseType.BOUNCE_EASEINOUT:
                resultAction = action.easing(cc.easeBounceInOut());
                break;
        }
        return resultAction;
    },
    setEasingParameter: function(parameter){
        this._Parameter = [];
        for(var i=0;i<parameter.length;i++)
            this._Parameter.push(parameter[i]);
    },
    setEasingType: function(easingType){
        this.easingType = easingType;
    }
});
ccs.ActionMoveFrame = ccs.ActionFrame.extend({
    _position: null,
    ctor: function () {
        ccs.ActionFrame.prototype.ctor.call(this);
        this._position = cc.p(0, 0);
        this.frameType = ccs.FRAME_TYPE_MOVE;
    },
    setPosition: function (pos, y) {
        if (y === undefined) {
            this._position.x = pos.x;
            this._position.y = pos.y;
        } else {
            this._position.x = pos;
            this._position.y = y;
        }
    },
    getPosition: function () {
        return this._position;
    },
    getAction: function (duration) {
        return this._getEasingAction(cc.moveTo(duration, this._position));
    }
});
ccs.ActionScaleFrame = ccs.ActionFrame.extend({
    _scaleX: 1,
    _scaleY: 1,
    ctor: function () {
        ccs.ActionFrame.prototype.ctor.call(this);
        this._scaleX = 1;
        this._scaleY = 1;
        this.frameType = ccs.FRAME_TYPE_SCALE;
    },
    setScaleX: function (scaleX) {
        this._scaleX = scaleX;
    },
    getScaleX: function () {
        return this._scaleX;
    },
    setScaleY: function (scaleY) {
        this._scaleY = scaleY;
    },
    getScaleY: function () {
        return this._scaleY;
    },
    getAction: function (duration) {
        return this._getEasingAction(cc.scaleTo(duration, this._scaleX, this._scaleY));
    }
});
ccs.ActionRotationFrame = ccs.ActionFrame.extend({
    _rotation: 0,
    ctor: function () {
        ccs.ActionFrame.prototype.ctor.call(this);
        this._rotation = 0;
        this.frameType = ccs.FRAME_TYPE_ROTATE;
    },
    setRotation: function (rotation) {
        this._rotation = rotation;
    },
    getRotation: function () {
        return this._rotation;
    },
    getAction: function (duration, srcFrame) {
        if(srcFrame === undefined)
            return this._getEasingAction(cc.rotateTo(duration, this._rotation));
        else {
            if (!(srcFrame instanceof cc.ActionRotationFrame))
                return this.getAction(duration);
            else{
                var diffRotation = this._rotation - srcFrame._rotation;
                return this._getEasingAction(cc.rotateBy(duration,diffRotation));
            }
        }
    }
});
ccs.ActionFadeFrame = ccs.ActionFrame.extend({
    _opacity: 255,
    ctor: function () {
        ccs.ActionFrame.prototype.ctor.call(this);
        this._opacity = 255;
        this.frameType = ccs.FRAME_TYPE_FADE;
    },
    setOpacity: function (opacity) {
        this._opacity = opacity;
    },
    getOpacity: function () {
        return this._opacity;
    },
    getAction: function (duration) {
        return this._getEasingAction(cc.fadeTo(duration, this._opacity));
    }
});
ccs.ActionTintFrame = ccs.ActionFrame.extend({
    _color: null,
    ctor: function () {
        ccs.ActionFrame.prototype.ctor.call(this);
        this._color = cc.color(255, 255, 255, 255);
        this.frameType = ccs.FRAME_TYPE_TINT;
    },
    setColor: function (color) {
        var locColor = this._color;
        locColor.r = color.r;
        locColor.g = color.g;
        locColor.b = color.b;
    },
    getColor: function () {
        var locColor = this._color;
        return cc.color(locColor.r, locColor.g, locColor.b, locColor.a);
    },
    getAction: function (duration) {
        return this._getEasingAction(cc.tintTo(duration, this._color.r, this._color.g, this._color.b));
    }
});
ccs.actionManager = {
    _actionDic: {},
    initWithDictionary: function (jsonName, dic, root) {
        var path = jsonName;
        var pos = path.lastIndexOf("/");
        var fileName = path.substr(pos + 1, path.length);
        var actionList = dic["actionlist"];
        var locActionList = [];
        for (var i = 0; i < actionList.length; i++) {
            var locAction = new ccs.ActionObject();
            var locActionDic = actionList[i];
            locAction.initWithDictionary(locActionDic, root);
            locActionList.push(locAction);
        }
        this._actionDic[fileName] = locActionList;
    },
    getActionByName: function (jsonName, actionName) {
        var path = jsonName;
        var pos = path.lastIndexOf("/");
        var fileName = path.substr(pos + 1, path.length);
        var actionList = this._actionDic[fileName];
        if (!actionList)
            return null;
        for (var i = 0; i < actionList.length; i++) {
            var locAction = actionList[i];
            if (actionName === locAction.getName())
                return locAction;
        }
        return null;
    },
    playActionByName: function (jsonName, actionName, fun) {
        var action = this.getActionByName(jsonName, actionName);
        if (action)
            action.play(fun);
    },
    stopActionByName: function (jsonName, actionName) {
        var action = this.getActionByName(jsonName, actionName);
        if (action)
            action.stop();
    },
    releaseActions: function () {
        this._actionDic = {};
    },
    clear: function() {
        this._actionDic = {};
    }
};
ccs.ActionNode = ccs.Class.extend({
    _currentFrameIndex: 0,
    _destFrameIndex: 0,
    _unitTime: 0,
    _actionTag: 0,
    _object: null,
    _actionSpawn: null,
    _action: null,
    _frameArray: null,
    _frameArrayNum: 0,
    ctor: function () {
        this._currentFrameIndex = 0;
        this._destFrameIndex = 0;
        this._unitTime = 0.1;
        this._actionTag = 0;
        this._object = null;
        this._actionSpawn = null;
        this._action = null;
        this._frameArray = [];
        this._frameArrayNum = ccs.FRAME_TYPE_MAX;
        for (var i = 0; i < this._frameArrayNum; i++)
            this._frameArray.push([]);
    },
    initWithDictionary: function (dic, root) {
        this.setActionTag(dic["ActionTag"]);
        var actionFrameList = dic["actionframelist"];
        var node = ccui.helper.seekActionWidgetByActionTag(root, dic["ActionTag"]);
        var positionOffset = node instanceof ccui.Widget && !(node instanceof ccui.Layout);
        for (var i = 0; i < actionFrameList.length; i++) {
            var actionFrameDic = actionFrameList[i];
            var frameIndex = actionFrameDic["frameid"];
            var frameTweenType = actionFrameDic["tweenType"];
            if(frameTweenType == null)
                frameTweenType = 0;
            var frameTweenParameterNum = actionFrameDic["tweenParameter"];
            var frameTweenParameter = [];
            for (var j = 0; j < frameTweenParameterNum; j++){
                var value = actionFrameDic["tweenParameter"][j];
                frameTweenParameter.push(value);
            }
            var actionFrame, actionArray;
            if (actionFrameDic["positionx"] !== undefined) {
                var positionX = actionFrameDic["positionx"];
                var positionY = actionFrameDic["positiony"];
                if(positionOffset && node.parent){
                    var AnchorPointIn = node.parent.getAnchorPointInPoints();
                    positionX += AnchorPointIn.x;
                    positionY += AnchorPointIn.y;
                }
                actionFrame = new ccs.ActionMoveFrame();
                actionFrame.frameIndex = frameIndex;
                actionFrame.setEasingType(frameTweenType);
                actionFrame.setEasingParameter(frameTweenParameter);
                actionFrame.setPosition(positionX, positionY);
                actionArray = this._frameArray[ccs.FRAME_TYPE_MOVE];
                actionArray.push(actionFrame);
            }
            if (actionFrameDic["scalex"] !== undefined) {
                var scaleX = actionFrameDic["scalex"];
                var scaleY = actionFrameDic["scaley"];
                actionFrame = new ccs.ActionScaleFrame();
                actionFrame.frameIndex = frameIndex;
                actionFrame.setEasingType(frameTweenType);
                actionFrame.setEasingParameter(frameTweenParameter);
                actionFrame.setScaleX(scaleX);
                actionFrame.setScaleY(scaleY);
                actionArray = this._frameArray[ccs.FRAME_TYPE_SCALE];
                actionArray.push(actionFrame);
            }
            if (actionFrameDic["rotation"] !== undefined) {
                var rotation = actionFrameDic["rotation"];
                actionFrame = new ccs.ActionRotationFrame();
                actionFrame.frameIndex = frameIndex;
                actionFrame.setEasingType(frameTweenType);
                actionFrame.setEasingParameter(frameTweenParameter);
                actionFrame.setRotation(rotation);
                actionArray = this._frameArray[ccs.FRAME_TYPE_ROTATE];
                actionArray.push(actionFrame);
            }
            if (actionFrameDic["opacity"] !== undefined) {
                var opacity = actionFrameDic["opacity"];
                actionFrame = new ccs.ActionFadeFrame();
                actionFrame.frameIndex = frameIndex;
                actionFrame.setEasingType(frameTweenType);
                actionFrame.setEasingParameter(frameTweenParameter);
                actionFrame.setOpacity(opacity);
                actionArray = this._frameArray[ccs.FRAME_TYPE_FADE];
                actionArray.push(actionFrame);
            }
            if (actionFrameDic["colorr"] !== undefined) {
                var colorR = actionFrameDic["colorr"];
                var colorG = actionFrameDic["colorg"];
                var colorB = actionFrameDic["colorb"];
                actionFrame = new ccs.ActionTintFrame();
                actionFrame.frameIndex = frameIndex;
                actionFrame.setEasingType(frameTweenType);
                actionFrame.setEasingParameter(frameTweenParameter);
                actionFrame.setColor(cc.color(colorR, colorG, colorB));
                actionArray = this._frameArray[ccs.FRAME_TYPE_TINT];
                actionArray.push(actionFrame);
            }
            actionFrameDic = null;
        }
        this._initActionNodeFromRoot(root);
    },
    _initActionNodeFromRoot: function (root) {
        if (root instanceof ccui.Widget) {
            var widget = ccui.helper.seekActionWidgetByActionTag(root, this.getActionTag());
            if (widget)
                this.setObject(widget);
        }
    },
    setUnitTime: function (time) {
        this._unitTime = time;
        this._refreshActionProperty();
    },
    getUnitTime: function () {
        return this._unitTime;
    },
    setActionTag: function (tag) {
        this._actionTag = tag;
    },
    getActionTag: function () {
        return this._actionTag;
    },
    setObject: function (node) {
        this._object = node;
    },
    getObject: function () {
        return this._object;
    },
    getActionNode: function () {
        if (this._object instanceof cc.Node)
            return this._object;
        return null;
    },
    insertFrame: function (index, frame) {
        if (frame == null)
            return;
        var frameType = frame.frameType;
        var array = this._frameArray[frameType];
        array.splice(index, 0, frame);
    },
    addFrame: function (frame) {
        if (!frame)
            return;
        var frameType = frame.frameType;
        var array = this._frameArray[frameType];
        array.push(frame);
    },
    deleteFrame: function (frame) {
        if (frame == null)
            return;
        var frameType = frame.frameType;
        var array = this._frameArray[frameType];
        cc.arrayRemoveObject(array, frame);
    },
    clearAllFrame: function () {
        for (var i = 0; i < this._frameArrayNum; i++)
            this._frameArray[i].length = 0;
    },
    _refreshActionProperty: function () {
        if (this._object === null)
            return null;
        var locSpawnArray = [];
        for (var i = 0; i < this._frameArrayNum; i++) {
            var locArray = this._frameArray[i];
            if (locArray.length <= 0)
                continue;
            var locSequenceArray = [];
            for (var j = 0; j < locArray.length; j++) {
                var locFrame = locArray[j];
                var locAction = null;
                if (j !== 0) {
                    var locSrcFrame = locArray[j - 1];
                    var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * this.getUnitTime();
                    locAction = locFrame.getAction(locDuration);
                }
                else {
                    locAction = locFrame.getAction(0);
                }
                if(locAction)
                    locSequenceArray.push(locAction);
            }
            if(locSequenceArray){
                var locSequence = cc.sequence(locSequenceArray);
                if (locSequence !== null)
                    locSpawnArray.push(locSequence);
            }
        }
        this._action = null;
        this._actionSpawn = cc.spawn(locSpawnArray);
        return this._actionSpawn;
    },
    playAction: function (fun) {
        if (this._object === null || this._actionSpawn === null)
            return;
        if(fun)
            this._action = cc.sequence(this._actionSpawn, fun);
        else
            this._action = cc.sequence(this._actionSpawn);
        this._runAction();
    },
    _runAction: function () {
        var node = this.getActionNode();
        if (node !== null && this._action !== null)
            node.runAction(this._action);
    },
    stopAction: function () {
        var node = this.getActionNode();
        if (node !== null && this._action !== null) {
            if(!this._action.isDone())
                node.stopAction(this._action);
        }
    },
    getFirstFrameIndex: function () {
        var locFrameindex = 99999;
        var bFindFrame = false, locFrameArray = this._frameArray;
        for (var i = 0, len = this._frameArrayNum; i < len; i++) {
            var locArray = locFrameArray[i];
            if (locArray.length <= 0)
                continue;
            bFindFrame = true;
            var locFrameIndex = locArray[0].frameIndex;
            locFrameindex = locFrameindex > locFrameIndex ? locFrameIndex : locFrameindex;
        }
        if (!bFindFrame)
            locFrameindex = 0;
        return locFrameindex;
    },
    getLastFrameIndex: function () {
        var locFrameindex = -1;
        var locIsFindFrame = false ,locFrameArray = this._frameArray;
        for (var i = 0, len = this._frameArrayNum; i < len; i++) {
            var locArray = locFrameArray[i];
            if (locArray.length <= 0)
                continue;
            locIsFindFrame = true;
            var locFrame = locArray[locArray.length - 1];
            var locFrameIndex = locFrame.frameIndex;
            locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex;
        }
        if (!locIsFindFrame)
            locFrameindex = 0;
        return locFrameindex;
    },
    updateActionToTimeLine: function (time) {
        var locIsFindFrame = false;
        var locUnitTime = this.getUnitTime();
        for (var i = 0; i < this._frameArrayNum; i++) {
            var locArray = this._frameArray[i];
            if (locArray === null)
                continue;
            for (var j = 0; j < locArray.length; j++) {
                var locFrame = locArray[j];
                if (locFrame.frameIndex * locUnitTime === time) {
                    this._easingToFrame(1.0, 1.0, locFrame);
                    locIsFindFrame = true;
                    break;
                } else if (locFrame.frameIndex * locUnitTime > time) {
                    if (j === 0) {
                        this._easingToFrame(1.0, 1.0, locFrame);
                        locIsFindFrame = false;
                    } else {
                        var locSrcFrame = locArray[j - 1];
                        var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * locUnitTime;
                        var locDelaytime = time - locSrcFrame.frameIndex * locUnitTime;
                        this._easingToFrame(locDuration, 1.0, locSrcFrame);
                        this._easingToFrame(locDuration, locDelaytime / locDuration, locFrame);
                        locIsFindFrame = true;
                    }
                    break;
                }
            }
        }
        return locIsFindFrame;
    },
    _easingToFrame: function (duration, delayTime, destFrame) {
        var action = destFrame.getAction(duration);
        var node = this.getActionNode();
        if (action == null || node == null)
            return;
        action.startWithTarget(node);
        action.update(delayTime);
    },
    isActionDoneOnce: function () {
        if (this._action === null)
            return true;
        return this._action.isDone();
    }
});
ccs.ActionObject = ccs.Class.extend({
    _actionNodeList: null,
    _name: "",
    _loop: false,
    _pause: false,
    _playing: false,
    _unitTime: 0,
    _currentTime: 0,
    _scheduler:null,
    _callback: null,
    _fTotalTime: 0,
    ctor: function () {
        this._actionNodeList = [];
        this._name = "";
        this._loop = false;
        this._pause = false;
        this._playing = false;
        this._unitTime = 0.1;
        this._currentTime = 0;
        this._fTotalTime = 0;
        this._scheduler = cc.director.getScheduler();
    },
    setName: function (name) {
        this._name = name;
    },
    getName: function () {
        return this._name;
    },
    setLoop: function (loop) {
        this._loop = loop;
    },
    getLoop: function () {
        return this._loop;
    },
    setUnitTime: function (time) {
        this._unitTime = time;
        var frameNum = this._actionNodeList.length;
        for (var i = 0; i < frameNum; i++) {
            var locActionNode = this._actionNodeList[i];
            locActionNode.setUnitTime(this._unitTime);
        }
    },
    getUnitTime: function () {
        return this._unitTime;
    },
    getCurrentTime: function () {
        return this._currentTime;
    },
    setCurrentTime: function (time) {
        this._currentTime = time;
    },
    getTotalTime: function(){
        return this._fTotalTime;
    },
    isPlaying: function () {
        return this._playing;
    },
    initWithDictionary: function (dic, root) {
        this.setName(dic["name"]);
        this.setLoop(dic["loop"]);
        this.setUnitTime(dic["unittime"]);
        var actionNodeList = dic["actionnodelist"];
        var maxLength = 0;
        for (var i = 0; i < actionNodeList.length; i++) {
            var actionNode = new ccs.ActionNode();
            var actionNodeDic = actionNodeList[i];
            actionNode.initWithDictionary(actionNodeDic, root);
            actionNode.setUnitTime(this.getUnitTime());
            this._actionNodeList.push(actionNode);
            var length = actionNode.getLastFrameIndex() - actionNode.getFirstFrameIndex();
            if(length > maxLength){
                maxLength = length;
            }
        }
        this._fTotalTime = maxLength * this._unitTime;
    },
    addActionNode: function (node) {
        if (!node)
            return;
        this._actionNodeList.push(node);
        node.setUnitTime(this._unitTime);
    },
    removeActionNode: function (node) {
        if (node == null)
            return;
        cc.arrayRemoveObject(this._actionNodeList, node);
    },
    play: function (fun) {
        this.stop();
        this.updateToFrameByTime(0);
        var locActionNodeList = this._actionNodeList;
        var frameNum = locActionNodeList.length;
        for (var i = 0; i < frameNum; i++) {
            locActionNodeList[i].playAction(fun);
        }
        if (this._loop)
            this._scheduler.schedule(this.simulationActionUpdate, this, 0, cc.REPEAT_FOREVER, 0, false, this.__instanceId + "");
        if(fun !== undefined)
            this._callback = fun;
    },
    pause: function () {
        this._pause = true;
        this._playing = false;
    },
    stop: function () {
        var locActionNodeList = this._actionNodeList;
        for (var i = 0; i < locActionNodeList.length; i++)
            locActionNodeList[i].stopAction();
        this._scheduler.unschedule(this.simulationActionUpdate, this);
        this._pause = false;
        this._playing = false;
    },
    updateToFrameByTime: function (time) {
        this._currentTime = time;
        for (var i = 0; i < this._actionNodeList.length; i++) {
            var locActionNode = this._actionNodeList[i];
            locActionNode.updateActionToTimeLine(time);
        }
    },
    simulationActionUpdate: function (dt) {
        var isEnd = true, locNodeList = this._actionNodeList;
        for(var i = 0, len = locNodeList.length; i < len; i++) {
            if (!locNodeList[i].isActionDoneOnce()){
                isEnd = false;
                break;
            }
        }
        if (isEnd){
            if (this._callback !== null)
                this._callback.execute();
            if (this._loop)
                this.play();
            else{
                this._playing = false;
                this._scheduler.unschedule(this.simulationActionUpdate, this);
            }
        }
    }
});
ccs.ComAttribute = ccs.Component.extend({
    _jsonDict: null,
    _filePath: "",
    ctor: function () {
        cc.Component.prototype.ctor.call(this);
        this._jsonDict = {};
        this._filePath = "";
        this._name = "CCComAttribute";
        ccs.ComAttribute.prototype.init.call(this);
    },
    init: function () {
        this._jsonDict = {};
        return true;
    },
    setInt: function (key, value) {
        if (!key) {
            cc.log("Argument must be non-nil");
            return;
        }
        this._jsonDict[key] = value;
    },
    setDouble: function (key, value) {
        if (!key) {
            cc.log("Argument must be non-nil");
            return;
        }
        this._jsonDict[key] = value;
    },
    setFloat: function (key, value) {
        if (!key) {
            cc.log("Argument must be non-nil");
            return;
        }
        this._jsonDict[key] = value;
    },
    setBool: function (key, value) {
        if (!key) {
            cc.log("Argument must be non-nil");
            return;
        }
        this._jsonDict[key] = value;
    },
    setString: function (key, value) {
        if (!key) {
            cc.log("Argument must be non-nil");
            return;
        }
        this._jsonDict[key] = value;
    },
    setObject: function (key, value) {
        if (!key) {
            cc.log("Argument must be non-nil");
            return;
        }
        this._jsonDict[key] = value;
    },
    getInt: function (key) {
        var ret = this._jsonDict[key];
        return parseInt(ret || 0);
    },
    getDouble: function (key) {
        var ret = this._jsonDict[key];
        return parseFloat(ret || 0.0);
    },
    getFloat: function (key) {
        var ret = this._jsonDict[key];
        return parseFloat(ret || 0.0);
    },
    getBool: function (key) {
        var ret = this._jsonDict[key];
        return Boolean(ret || false);
    },
    getString: function (key) {
        var ret = this._jsonDict[key];
        return ret || "";
    },
    getObject: function (key) {
        return this._jsonDict[key];
    },
    parse:function(filename){
        this._jsonDict = cc.loader.getRes(filename);
    }
});
ccs.ComAttribute.create = function () {
    return new ccs.ComAttribute();
};
ccs.ComAudio = ccs.Component.extend({
    _filePath: "",
    _loop: false,
    ctor: function () {
        cc.Component.prototype.ctor.call(this);
        this._name = "Audio";
        ccs.ComAudio.prototype.init.call(this);
    },
    init: function () {
        return true;
    },
    onExit: function () {
        this.stopBackgroundMusic(true);
        this.stopAllEffects();
    },
    end: function () {
        cc.audioEngine.end();
    },
    preloadBackgroundMusic: function (pszFilePath) {
        cc.loader.load(pszFilePath);
    },
    playBackgroundMusic: function (pszFilePath, loop) {
        if(pszFilePath){
            cc.audioEngine.playMusic(pszFilePath, loop);
        }else{
            cc.audioEngine.playMusic(this._filePath, this._loop);
        }
    },
    stopBackgroundMusic: function (releaseData) {
        cc.audioEngine.stopMusic(releaseData);
    },
    pauseBackgroundMusic: function () {
        cc.audioEngine.pauseMusic();
    },
    resumeBackgroundMusic: function () {
        cc.audioEngine.resumeMusic();
    },
    rewindBackgroundMusic: function () {
        cc.audioEngine.rewindMusic();
    },
    willPlayBackgroundMusic: function () {
        return cc.audioEngine.willPlayMusic();
    },
    isBackgroundMusicPlaying: function () {
        return cc.audioEngine.isMusicPlaying();
    },
    getBackgroundMusicVolume: function () {
        return cc.audioEngine.getMusicVolume();
    },
    setBackgroundMusicVolume: function (volume) {
        cc.audioEngine.setMusicVolume(volume);
    },
    getEffectsVolume: function () {
        return cc.audioEngine.getEffectsVolume();
    },
    setEffectsVolume: function (volume) {
        cc.audioEngine.setEffectsVolume(volume);
    },
    playEffect: function (pszFilePath, loop) {
        if (pszFilePath)
            return cc.audioEngine.playEffect(pszFilePath, loop);
         else
            return cc.audioEngine.playEffect(this._filePath, this._loop);
    },
    pauseEffect: function (soundId) {
        cc.audioEngine.pauseEffect(soundId);
    },
    pauseAllEffects: function () {
        cc.audioEngine.pauseAllEffects();
    },
    resumeEffect: function (soundId) {
        cc.audioEngine.resumeEffect(soundId);
    },
    resumeAllEffects: function () {
        cc.audioEngine.resumeAllEffects();
    },
    stopEffect: function (soundId) {
        cc.audioEngine.stopEffect(soundId);
    },
    stopAllEffects: function () {
        cc.audioEngine.stopAllEffects();
    },
    preloadEffect: function (pszFilePath) {
        cc.loader.getRes(pszFilePath);
        this.setFile(pszFilePath);
        this.setLoop(false);
    },
    unloadEffect: function (pszFilePath) {
        cc.audioEngine.unloadEffect(pszFilePath);
    },
    setFile: function (pszFilePath) {
        this._filePath = pszFilePath;
    },
    setLoop: function (loop) {
        this._loop = loop;
    },
    getFile: function () {
        return this._filePath;
    },
    isLoop: function () {
        return this._loop;
    }
});
ccs.ComAudio.create = function () {
    return new ccs.ComAudio();
};
ccs.ComController = ccs.Component.extend({
    ctor: function () {
        cc.Component.prototype.ctor.call(this);
        this._name = "ComController";
        ccs.ComController.prototype.init.call(this);
    },
    onEnter: function () {
        if (this._owner !== null)
            this._owner.scheduleUpdate();
    },
    isEnabled: function () {
        return this._enabled;
    },
    setEnabled: function (bool) {
        this._enabled = bool;
    }
});
ccs.ComController.create = function () {
    return new ccs.ComController();
};
ccs.ComRender = ccs.Component.extend({
    _render: null,
    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);
    },
    onEnter: function () {
        if (this._owner)
            this._owner.addChild(this._render);
    },
    onExit: function () {
        if (this._owner) {
            this._owner.removeChild(this._render, true);
            this._render = null;
        }
    },
    getNode: function () {
        return this._render;
    },
    setNode: function (node) {
        this._render = node;
    }
});
ccs.ComRender.create = function (node, comName) {
    return new ccs.ComRender(node, comName);
};
ccs.objectFactory = {
    _typeMap: {},
    createObject: function (className) {
        var o = null;
        var t = this._typeMap[className];
        if (t) {
            if(cc.isFunction(t._fun))
                o = new t._fun();
            else
                o = t._fun;
        }
        return o;
    },
    registerType: function (t) {
        this._typeMap[t._className] = t;
    },
    createGUI: function(name){
        var object = null;
        if(name === "Panel")
            name = "Layout";
        else if(name === "TextArea")
            name = "Label";
        else if(name === "TextButton")
            name = "Button";
        var t = this._typeMap[name];
        if(t && t._fun)
            object = t._fun;
        return object;
    },
    removeAll: function(){
        this._typeMap = {};
    }
};
ccs.TInfo = ccs.Class.extend({
    _className: "",
    _fun: null,
    ctor: function (c, f) {
        if (f) {
            this._className = c;
            this._fun = f;
        } else {
            this._className = c._className;
            this._fun = c._fun;
        }
        ccs.objectFactory.registerType(this);
    }
});
ccs.sendEvent = function (event) {
    var triggerObjArr = ccs.triggerManager.get(event);
    if (triggerObjArr == null)
        return;
    for (var i = 0; i < triggerObjArr.length; i++) {
        var triObj = triggerObjArr[i];
        if (triObj != null && triObj.detect())
            triObj.done();
    }
};
ccs.registerTriggerClass = function (className, func) {
    new ccs.TInfo(className, func);
};
ccs.triggerManager = {
    _eventTriggers: {},
    _triggerObjs: {},
    _movementDispatches: [],
    parse: function (triggers) {
        for (var i = 0; i < triggers.length; ++i) {
            var subDict = triggers[i];
            var triggerObj = new ccs.TriggerObj();
            triggerObj.serialize(subDict);
            var events = triggerObj.getEvents();
            for (var j = 0; j < events.length; j++) {
                var event = events[j];
                this.add(event, triggerObj);
            }
            this._triggerObjs[triggerObj.getId()] = triggerObj;
        }
    },
    get: function (event) {
        return this._eventTriggers[event];
    },
    getTriggerObj: function (id) {
        return this._triggerObjs[id];
    },
    add: function (event, triggerObj) {
        var eventTriggers = this._eventTriggers[event];
        if (!eventTriggers)
            eventTriggers = [];
        if (eventTriggers.indexOf(triggerObj) === -1) {
            eventTriggers.push(triggerObj);
            this._eventTriggers[event] = eventTriggers;
        }
    },
    removeAll: function () {
        for (var key in this._eventTriggers) {
            var triObjArr = this._eventTriggers[key];
            for (var j = 0; j < triObjArr.length; j++) {
                var obj = triObjArr[j];
                obj.removeAll();
            }
        }
        this._eventTriggers = {};
    },
    remove: function (event, Obj) {
        if (Obj)
            return this._removeObj(event, Obj);
        var bRet = false;
        do {
            var triObjects = this._eventTriggers[event];
            if (!triObjects)
                break;
            for (var i = 0; i < triObjects.length; i++) {
                var triObject = triObjects[i];
                if (triObject)
                    triObject.removeAll();
            }
            delete this._eventTriggers[event];
            bRet = true;
        } while (0);
        return bRet;
    },
    _removeObj: function (event, Obj) {
        var bRet = false;
        do
        {
            var triObjects = this._eventTriggers[event];
            if (!triObjects) break;
            for (var i = 0; i < triObjects.length; i++) {
                var triObject = triObjects[i];
                if (triObject && triObject == Obj) {
                    triObject.removeAll();
                    triObjects.splice(i, 1);
                    break;
                }
            }
            bRet = true;
        } while (0);
        return bRet;
    },
    removeTriggerObj: function (id) {
        var obj = this.getTriggerObj(id);
        if (!obj)
            return false;
        var events = obj.getEvents();
        for (var i = 0; i < events.length; i++) {
            var event = events[i];
            this.remove(event, obj);
        }
        return true;
    },
    isEmpty: function () {
        return !this._eventTriggers || this._eventTriggers.length <= 0;
    },
    addArmatureMovementCallBack: function (armature, callFunc, target) {
        if (armature == null || target == null || callFunc == null)
            return;
        var locAmd, hasADD = false;
        for (var i = 0; i < this._movementDispatches.length; i++) {
            locAmd = this._movementDispatches[i];
            if (locAmd && locAmd[0] === armature) {
                locAmd.addAnimationEventCallBack(callFunc, target);
                hasADD = true;
            }
        }
        if (!hasADD) {
            var newAmd = new ccs.ArmatureMovementDispatcher();
            armature.getAnimation().setMovementEventCallFunc(newAmd.animationEvent, newAmd);
            newAmd.addAnimationEventCallBack(callFunc, target);
            this._movementDispatches.push([armature, newAmd]);
        }
    },
    removeArmatureMovementCallBack: function (armature, target, callFunc) {
        if (armature == null || target == null || callFunc == null)
            return;
        var locAmd;
        for (var i = 0; i < this._movementDispatches.length; i++) {
            locAmd = this._movementDispatches[i];
            if (locAmd && locAmd[0] === armature)
                locAmd.removeAnimationEventCallBack(callFunc, target);
        }
    },
    removeArmatureAllMovementCallBack: function (armature) {
        if (armature == null)
            return;
        var locAmd;
        for (var i = 0; i < this._movementDispatches.length; i++) {
            locAmd = this._movementDispatches[i];
            if (locAmd && locAmd[0] === armature) {
                this._movementDispatches.splice(i, 1);
                break;
            }
        }
    },
    removeAllArmatureMovementCallBack: function () {
        this._movementDispatches.length = 0;
    },
    version: function () {
        return "1.2.0.0";
    }
};
ccs.ArmatureMovementDispatcher = ccs.Class.extend({
    _mapEventAnimation: null,
    ctor: function () {
        this._mapEventAnimation = [];
    },
    animationEvent: function (armature, movementType, movementID) {
        var locEventAni, locTarget, locFunc;
        for (var i = 0; i < this._mapEventAnimation.length; i++) {
            locEventAni = this._mapEventAnimation[i];
            locTarget = locEventAni[0];
            locFunc = locEventAni[1];
            if (locFunc)
                locFunc.call(locTarget, armature, movementType, movementID);
        }
    },
    addAnimationEventCallBack: function (callFunc, target) {
        this._mapEventAnimation.push([target, callFunc]);
    },
    removeAnimationEventCallBack: function (callFunc, target) {
        var locEventAni;
        for (var i = 0; i < this._mapEventAnimation.length; i++) {
            locEventAni = this._mapEventAnimation[i];
            if (locEventAni[0] === target) {
                this._mapEventAnimation.splice(i, 1);
            }
        }
    }
});
ccs.BaseTriggerCondition = ccs.Class.extend({
    ctor:function(){
    },
    init: function () {
        return true;
    },
    detect: function () {
        return true;
    },
    serialize: function (jsonVal) {
    },
    removeAll: function () {
    }
});
ccs.BaseTriggerAction = ccs.Class.extend({
    ctor:function(){
    },
    init: function () {
        return true;
    },
    done: function () {
    },
    serialize: function (jsonVal) {
    },
    removeAll: function () {
    }
});
ccs.TriggerObj = ccs.Class.extend({
    _cons: null,
    _acts: null,
    _id: 0,
    _enable: true,
    _vInt: null,
    ctor: function () {
        this._id = 0;
        this._enable = true;
        ccs.TriggerObj.prototype.init.call(this);
    },
    init: function () {
        this._cons = [];
        this._acts = [];
        this._vInt = [];
        return true;
    },
    detect: function () {
        if (!this._enable || this._cons.length === 0) {
            return true;
        }
        var ret = true;
        var obj = null;
        for (var i = 0; i < this._cons.length; i++) {
            obj = this._cons[i];
            if (obj && obj.detect)
                ret = ret && obj.detect();
        }
        return ret;
    },
    done: function () {
        if (!this._enable || this._acts.length === 0)
            return;
        var obj;
        for (var i = 0; i < this._acts.length; i++) {
            obj = this._acts[i];
            if (obj && obj.done)
                obj.done();
        }
    },
    removeAll: function () {
        var obj = null;
        for (var i = 0; i < this._cons.length; i++) {
            obj = this._cons[i];
            if (obj)
                obj.removeAll();
        }
        this._cons = [];
        for (var i = 0; i < this._acts.length; i++) {
            obj = this._acts[i];
            if (obj)
                obj.removeAll();
        }
        this._acts = [];
    },
    serialize: function (jsonVal) {
        this._id = jsonVal["id"] || 0;
        var conditions = jsonVal["conditions"] || [];
        for (var i = 0; i < conditions.length; i++) {
            var subDict = conditions[i];
            var classname = subDict["classname"];
            var con = ccs.objectFactory.createObject(classname);
            if (!con) {
                cc.log("class named classname(" + classname + ") can not implement!");
                continue;
            }
            con.serialize(subDict);
            con.init();
            this._cons.push(con);
        }
        var actions = jsonVal["actions"] || [];
        for (var i = 0; i < actions.length; i++) {
            var subDict = actions[i];
            var classname = subDict["classname"];
            var act = ccs.objectFactory.createObject(classname);
            if (!act) {
                cc.log("class named classname(" + classname + ") can not implement!");
                continue;
            }
            act.serialize(subDict);
            act.init();
            this._acts.push(act);
        }
        var events = jsonVal["events"] || [];
        for (var i = 0; i < events.length; i++) {
            var subDict = events[i];
            var event = subDict["id"];
            if (event < 0) {
                continue;
            }
            this._vInt.push(event);
        }
    },
    getId: function () {
        return this._id;
    },
    setEnable: function (enable) {
        this._enable = enable;
    },
    getEvents: function () {
        return this._vInt;
    }
});
ccs.TriggerObj.create = function () {
    return new ccs.TriggerObj();
};
ccs.ActionTimelineData = ccs.Class.extend({
    _actionTag: 0,
    ctor: function(actionTag){
        this._init(actionTag);
    },
    _init: function(actionTag){
        this._actionTag = actionTag;
        return true;
    },
    setActionTag: function(actionTag){
        this._actionTag = actionTag;
    },
    getActionTag: function(){
        return this._actionTag;
    }
});
ccs.AnimationInfo = function(name, start, end){
    this.name = name;
    this.startIndex = start;
    this.endIndex = end;
};
ccs.ComExtensionData = ccs.Component.extend({
    _customProperty: null,
    _timelineData: null,
    _name: "ComExtensionData",
    ctor: function(){
        this._customProperty = "";
        this._timelineData = new ccs.ActionTimelineData(0);
        return true;
    },
    setActionTag: function(actionTag){
        this._timelineData.setActionTag(actionTag);
    },
    getActionTag: function(){
        return this._timelineData.getActionTag();
    },
    setCustomProperty: function(customProperty){
        this._customProperty = customProperty;
    },
    getCustomProperty: function(){
        return this._customProperty;
    }
});
ccs.ComExtensionData.create = function(){
    return new ccs.ComExtensionData();
};
ccs.ActionTimelineData.create = function(actionTag){
    return new ccs.ActionTimelineData(actionTag);
};
ccs.ActionTimeline = cc.Action.extend({
    _timelineMap: null,
    _timelineList: null,
    _duration: 0,
    _time: null,
    _timeSpeed: 1,
    _frameInternal: 1/60,
    _playing: false,
    _currentFrame: 0,
    _startFrame: 0,
    _endFrame: 0,
    _loop: null,
    _frameEventListener: null,
    _animationInfos: null,
    _lastFrameListener: null,
    ctor: function(){
        cc.Action.prototype.ctor.call(this);
        this._timelineMap = {};
        this._timelineList = [];
        this._animationInfos = {};
        this.init();
    },
    _gotoFrame: function(frameIndex){
        var size = this._timelineList.length;
        for(var i = 0; i < size; i++)
        {
            this._timelineList[i]._gotoFrame(frameIndex);
        }
    },
    _stepToFrame: function(frameIndex){
        var size = this._timelineList.length;
        for(var i = 0; i < size; i++){
            this._timelineList[i]._stepToFrame(frameIndex);
        }
    },
    _emitFrameEvent: function(frame){
        if(this._frameEventListener){
            this._frameEventListener(frame);
        }
    },
    init: function(){
        return true;
    },
    gotoFrameAndPlay: function(startIndex, endIndex, currentFrameIndex, loop){
        var i = 0,
            argLen = arguments.length;
        var num = [],
            bool;
        for(i; i<argLen; i++){
            if(typeof arguments[i] === "boolean"){
                bool = arguments[i];
            }else{
                num.push(arguments[i]);
            }
        }
        startIndex = num[0];
        endIndex = num[1] !== undefined ? num[1] : this._duration;
        currentFrameIndex = num[2] || startIndex;
        loop = bool!=null ? bool : true;
        this._startFrame = startIndex;
        this._endFrame = endIndex;
        this._currentFrame = currentFrameIndex;
        this._loop = loop;
        this._time = this._currentFrame * this._frameInternal;
        this.resume();
        this._gotoFrame(this._currentFrame);
    },
    gotoFrameAndPause: function(startIndex){
        this._startFrame = this._currentFrame = startIndex;
        this._time       = this._currentFrame * this._frameInternal;
        this.pause();
        this._gotoFrame(this._currentFrame);
    },
    pause: function(){
        this._playing = false;
    },
    resume: function(){
        this._playing = true;
    },
    isPlaying: function(){
        return this._playing;
    },
    setTimeSpeed: function(speed){
        this._timeSpeed = speed;
    },
    getTimeSpeed: function(){
        return this._timeSpeed;
    },
    setDuration: function(duration){
        this._duration = duration;
    },
    getDuration: function(){
        return this._duration;
    },
    getStartFrame: function(){
        return this._startFrame;
    },
    getEndFrame: function(){
        return this._endFrame;
    },
    setCurrentFrame: function(frameIndex){
        if (frameIndex >= this._startFrame && frameIndex <= this._endFrame){
            this._currentFrame = frameIndex;
            this._time = this._currentFrame * this._frameInternal;
        }else{
            cc.log("frame index is not between start frame and end frame");
        }
    },
    getCurrentFrame: function(){
        return this._currentFrame;
    },
    addTimeline: function(timeline){
        var tag = timeline.getActionTag();
        if (!this._timelineMap[tag]) {
            this._timelineMap[tag] = [];
        }
        if (this._timelineMap[tag].indexOf(timeline) === -1) {
            this._timelineList.push(timeline);
            this._timelineMap[tag].push(timeline);
            timeline.setActionTimeline(this);
        }
    },
    removeTimeline: function(timeline){
        var tag = timeline.getActionTag();
        if (this._timelineMap[tag]) {
            if(this._timelineMap[tag].some(function(item){
                if(item === timeline)
                    return true;
            })) {
                cc.arrayRemoveObject(this._timelineMap[tag], timeline);
                cc.arrayRemoveObject(this._timelineList, timeline);
                timeline.setActionTimeline(null);
            }
        }
    },
    getTimelines: function(){
        return this._timelineList;
    },
    setFrameEventCallFunc: function(listener){
        this._frameEventListener = listener;
    },
    clearFrameEventCallFunc: function(){
        this._frameEventListener = null;
    },
    clone: function(){
        var newAction = new ccs.ActionTimeline();
        newAction.setDuration(this._duration);
        newAction.setTimeSpeed(this._timeSpeed);
        for (var a in this._timelineMap){
            var timelines = this._timelineMap[a];
            for(var b in timelines)
            {
                var timeline = timelines[b];
                var newTimeline = timeline.clone();
                newAction.addTimeline(newTimeline);
            }
        }
        return newAction;
    },
    reverse: function(){
        return null;
    },
    step: function(delta){
        if (!this._playing || this._timelineMap.length === 0 || this._duration === 0)
        {
            return;
        }
        this._time += delta * this._timeSpeed;
        var endoffset = this._time - this._endFrame * this._frameInternal;
        if(endoffset < this._frameInternal){
            this._currentFrame = Math.floor(this._time / this._frameInternal);
            this._stepToFrame(this._currentFrame);
            if(endoffset >= 0 && this._lastFrameListener)
                this._lastFrameListener();
        }else{
            this._playing = this._loop;
            if(!this._playing){
                this._time = this._endFrame * this._frameInternal;
                if (this._currentFrame != this._endFrame){
                    this._currentFrame = this._endFrame;
                    this._stepToFrame(this._currentFrame);
                    if(this._lastFrameListener)
                        this._lastFrameListener();
                }
            }else
                this.gotoFrameAndPlay(this._startFrame, this._endFrame, this._loop);
        }
    },
    _foreachNodeDescendant: function(parent, callback){
        callback(parent);
        var children = parent.getChildren();
        for (var i=0; i<children.length; i++)
        {
            var child = children[i];
            this._foreachNodeDescendant(child, callback);
        }
    },
    startWithTarget: function(target){
        cc.Action.prototype.startWithTarget.call(this, target);
        var self = this;
        var callback = function(child){
            var data = child.getComponent("ComExtensionData");
            if(data) {
                var actionTag = data.getActionTag();
                if(self._timelineMap[actionTag]) {
                    var timelines = self._timelineMap[actionTag];
                    for (var i=0; i<timelines.length; i++) {
                        var timeline = timelines[i];
                        timeline.setNode(child);
                    }
                }
            }
        };
        this._foreachNodeDescendant(target, callback);
    },
    isDone: function(){
        return false;
    },
    play: function(name, loop){
        var info = this._animationInfos[name];
        if (!info)
            return cc.log("Can't find animation info for %s", name);
        this.gotoFrameAndPlay(info.startIndex, info.endIndex, loop);
    },
    addAnimationInfo: function(info){
        this._animationInfos[info.name] = info;
    },
    removeAnimationInfo: function(name){
        delete this._animationInfos[name];
    },
    isAnimationInfoExists: function(name){
        return this._animationInfos[name];
    },
    getAnimationInfo: function(name){
        return this._animationInfos[name];
    },
    setLastFrameCallFunc: function(listener){
        this._lastFrameListener = listener;
    },
    clearLastFrameCallFunc: function(){
        this._lastFrameListener = null;
    }
});
ccs.ActionTimeline.create = function(){
    return new ccs.ActionTimeline();
};
ccs.Frame = ccs.Class.extend({
    _frameIndex: null,
    _tween: null,
    _timeline: null,
    _node: null,
    _tweenType: null,
    _easingParam: null,
    _enterWhenPassed: null,
    ctor: function(){
        this._frameIndex = 0;
        this._tween = true;
        this._timeline = null;
        this._node = null;
        this._enterWhenPassed = false;
        this._easingParam = [];
    },
    _emitEvent: function(){
        if (this._timeline){
            this._timeline.getActionTimeline()._emitFrameEvent(this);
        }
    },
    _cloneProperty: function(frame){
        this._frameIndex = frame.getFrameIndex();
        this._tween = frame.isTween();
        this._tweenType = frame.getTweenType();
        this.setEasingParams(frame.getEasingParams());
    },
    setFrameIndex: function(frameIndex){
        this._frameIndex = frameIndex;
    },
    getFrameIndex: function(){
        return this._frameIndex;
    },
    setTimeline: function(timeline){
        this._timeline = timeline;
    },
    getTimeline: function(timeline){
        return this._timeline;
    },
    setNode: function(node){
        this._node = node;
    },
    getNode: function(){
        return this._node;
    },
    setTween: function(tween){
        this._tween = tween;
    },
    isTween: function(){
        return this._tween;
    },
    onEnter: function(nextFrame){
    },
    apply: function(percent){
        if(!this._tween)
            return;
        if(this._tweenType !== ccs.FrameEaseType.TWEEN_EASING_MAX  && this._tweenType !==  ccs.FrameEaseType.LINEAR)
            percent = this.tweenPercent(percent);
        this._onApply(percent);
    },
    _onApply: function(percent){
    },
    clone: function(){
    },
    tweenPercent: function(percent){
        var func = ccs.Frame.tweenToMap[this._tweenType];
        if(func)
            return func(percent, this._easingParam);
        else
            return percent;
    },
    setEasingParams: function(easingParams){
        if(easingParams){
            this._easingParam.length = 0;
            for(var i=0; i<easingParams.length; i++)
                this._easingParam[i] = easingParams[i];
        }
    },
    getEasingParams: function(){
        return this._easingParam;
    },
    setTweenType: function(tweenType){
        this._tweenType = tweenType;
    },
    getTweenType: function(){
        return this._tweenType;
    },
    isEnterWhenPassed: function(){
        return this._enterWhenPassed;
    }
});
ccs.Frame.tweenToMap = {
    "-1": function(time, easingParam){
        if (easingParam)
        {
            var tt = 1 - time;
            return easingParam[1]*tt*tt*tt + 3*easingParam[3]*time*tt*tt + 3*easingParam[5]*time*time*tt + easingParam[7]*time*time*time;
        }
        return time;
    },
    1: cc._easeSineInObj.easing,//Sine_EaseIn
    2: cc._easeSineOutObj.easing,//Sine_EaseOut
    3: cc._easeSineInOutObj.easing,//Sine_EaseInOut
    4: cc._easeQuadraticActionIn.easing,//Quad_EaseIn
    5: cc._easeQuadraticActionOut.easing,//Quad_EaseOut
    6: cc._easeQuadraticActionInOut.easing,//Quad_EaseInOut
    7: cc._easeCubicActionIn.easing,
    8: cc._easeCubicActionOut.easing,//Cubic_EaseOut
    9: cc._easeCubicActionInOut.easing,//Cubic_EaseInOut
    10: cc._easeCubicActionIn.easing,//Cubic_EaseIn
    11: cc._easeCubicActionOut.easing,//Cubic_EaseOut
    12: cc._easeCubicActionInOut.easing,//Cubic_EaseInOut
    13: cc._easeQuinticActionIn.easing,//Quint_EaseIn
    14: cc._easeQuinticActionOut.easing,//Quint_EaseOut
    15: cc._easeQuinticActionInOut.easing,//Quint_EaseInOut
    16: cc._easeExponentialInObj.easing,//Expo_EaseIn
    17: cc._easeExponentialOutObj.easing,//Expo_EaseOut
    18: cc._easeExponentialInOutObj.easing,//Expo_EaseInOut
    19: cc._easeCircleActionIn.easing,//Circ_EaseIn
    20: cc._easeCircleActionOut.easing,//Circ_EaseOut
    21: cc._easeCircleActionInOut.easing,//Circ_EaseInOut
    22: function(time, easingParam){
        var period = 0.3;
        easingParam != null && ( period = easingParam[0] );
        return cc.easeElasticIn(period).easing(time);
    },//Elastic_EaesIn
    23: function(time, easingParam){
        var period = 0.3;
        easingParam != null && ( period = easingParam[0] );
        return cc.easeElasticOut(period).easing(time);
    },//Elastic_EaesOut
    24: function(time, easingParam){
        var period = 0.3;
        easingParam != null && ( period = easingParam[0] );
        return cc.easeElasticInOut(period).easing(time);
    },//Elastic_EaesInOut
    25: cc._easeBackInObj.easing,
    26: cc._easeBackOutObj.easing,
    27: cc._easeBackInOutObj.easing,
    28: cc._easeBounceInObj.easing,
    29: cc._easeBounceOutObj.easing,
    30: cc._easeBounceInOutObj.easing
};
ccs.VisibleFrame = ccs.Frame.extend({
    _visible: true,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._visible = true;
    },
    onEnter: function(nextFrame){
        if(this._node)
            this._node.setVisible(this._visible);
    },
    clone: function(){
        var frame = new ccs.VisibleFrame();
        frame.setVisible(this._visible);
        frame._cloneProperty(this);
        return frame;
    },
    setVisible: function(visible){
        this._visible = visible;
    },
    isVisible: function(){
        return this._visible;
    }
});
ccs.VisibleFrame.create = function(){
    return new ccs.VisibleFrame();
};
ccs.TextureFrame = ccs.Frame.extend({
    _sprite: null,
    _textureName: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._textureName = "";
    },
    setNode: function(node){
        ccs.Frame.prototype.setNode.call(this, node);
        this._sprite = node;
    },
    onEnter: function(nextFrame){
        if(this._sprite){
            var spriteBlendFunc = this._sprite.getBlendFunc();
            var spriteFrame = cc.spriteFrameCache._spriteFrames[this._textureName];
            if(spriteFrame != null)
                this._sprite.setSpriteFrame(spriteFrame);
            else
                this._sprite.setTexture(this._textureName);
            if(this._sprite.getBlendFunc() !== spriteBlendFunc)
                this._sprite.setBlendFunc(spriteBlendFunc);
        }
    },
    clone: function(){
        var frame = new ccs.TextureFrame();
        frame.setTextureName(this._textureName);
        frame._cloneProperty(this);
        return frame;
    },
    setTextureName: function(textureName){
        this._textureName = textureName;
    },
    getTextureName: function(){
        return this._textureName;
    }
});
ccs.TextureFrame.create = function(){
    return new ccs.TextureFrame();
};
ccs.RotationFrame = ccs.Frame.extend({
    _rotation: null,
    _betwennRotation: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._rotation = 0;
    },
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setRotation(this._rotation);
        if(this._tween){
            this._betwennRotation = nextFrame._rotation - this._rotation;
        }
    },
    _onApply: function(percent){
        if (this._betwennRotation !== 0){
            var rotation = this._rotation + percent * this._betwennRotation;
            this._node.setRotation(rotation);
        }
    },
    clone: function(){
        var frame = new ccs.RotationFrame();
        frame.setRotation(this._rotation);
        frame._cloneProperty(this);
        return frame;
    },
    setRotation: function(rotation){
        this._rotation = rotation;
    },
    getRotation: function(){
        return this._rotation;
    }
});
ccs.RotationFrame.create = function(){
    return new ccs.RotationFrame();
};
ccs.SkewFrame = ccs.Frame.extend({
    _skewX: null,
    _skewY: null,
    _betweenSkewX: null,
    _betweenSkewY: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._skewX = 0;
        this._skewY = 0;
    },
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setSkewX(this._skewX);
        this._node.setSkewY(this._skewY);
        if(this._tween){
            this._betweenSkewX = nextFrame._skewX - this._skewX;
            this._betweenSkewY = nextFrame._skewY - this._skewY;
        }
    },
    _onApply: function(percent){
        if (this._betweenSkewX !== 0 || this._betweenSkewY !== 0)
        {
            var skewx = this._skewX + percent * this._betweenSkewX;
            var skewy = this._skewY + percent * this._betweenSkewY;
            this._node.setSkewX(skewx);
            this._node.setSkewY(skewy);
        }
    },
    clone: function(){
        var frame = new ccs.SkewFrame();
        frame.setSkewX(this._skewX);
        frame.setSkewY(this._skewY);
        frame._cloneProperty(this);
        return frame;
    },
    setSkewX: function(skewx){
        this._skewX = skewx;
    },
    getSkewX: function(){
        return this._skewX;
    },
    setSkewY: function(skewy){
        this._skewY = skewy;
    },
    getSkewY: function(){
        return this._skewY;
    }
});
ccs.SkewFrame.create = function(){
    return new ccs.SkewFrame();
};
ccs.RotationSkewFrame = ccs.SkewFrame.extend({
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setRotationX(this._skewX);
        this._node.setRotationY(this._skewY);
        if (this._tween){
            this._betweenSkewX = nextFrame._skewX - this._skewX;
            this._betweenSkewY = nextFrame._skewY - this._skewY;
        }
    },
    _onApply: function(percent){
        if (this._node && (this._betweenSkewX !== 0 || this._betweenSkewY !== 0)){
            var skewx = this._skewX + percent * this._betweenSkewX;
            var skewy = this._skewY + percent * this._betweenSkewY;
            this._node.setRotationX(skewx);
            this._node.setRotationY(skewy);
        }
    },
    clone: function(){
        var frame = new ccs.RotationSkewFrame();
        frame.setSkewX(this._skewX);
        frame.setSkewY(this._skewY);
        frame._cloneProperty(this);
        return frame;
    }
});
ccs.RotationSkewFrame.create = function(){
    return new ccs.RotationSkewFrame();
};
ccs.PositionFrame = ccs.Frame.extend({
    _position: null,
    _betweenX: null,
    _betweenY: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._position = cc.p(0, 0);
    },
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setPosition(this._position);
        if(this._tween){
            this._betweenX = nextFrame._position.x - this._position.x;
            this._betweenY = nextFrame._position.y - this._position.y;
        }
    },
    _onApply: function(percent){
        if (this._node && (this._betweenX !== 0 || this._betweenY !== 0)){
            var p = cc.p(0, 0);
            p.x = this._position.x + this._betweenX * percent;
            p.y = this._position.y + this._betweenY * percent;
            this._node.setPosition(p);
        }
    },
    clone: function(){
        var frame = new ccs.PositionFrame();
        frame.setPosition(this._position);
        frame._cloneProperty(this);
        return frame;
    },
    setPosition: function(position){
        this._position = position;
    },
    getPosition: function(){
        return this._position;
    },
    setX: function(x){
        this._position.x = x;
    },
    getX: function(){
        return this._position.x;
    },
    setY: function(y){
        this._position.y = y;
    },
    getY: function(){
        return this._position.y;
    }
});
ccs.PositionFrame.create = function(){
    return new ccs.PositionFrame();
};
ccs.ScaleFrame = ccs.Frame.extend({
    _scaleX: null,
    _scaleY: null,
    _betweenScaleX: null,
    _betweenScaleY: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._scaleX = 1;
        this._scaleY = 1;
    },
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setScaleX(this._scaleX);
        this._node.setScaleY(this._scaleY);
        if(this._tween){
            this._betweenScaleX = nextFrame._scaleX - this._scaleX;
            this._betweenScaleY = nextFrame._scaleY - this._scaleY;
        }
    },
    _onApply: function(percent){
        if (this._node && (this._betweenScaleX !== 0 || this._betweenScaleY !== 0)){
            var scaleX = this._scaleX + this._betweenScaleX * percent;
            var scaleY = this._scaleY + this._betweenScaleY * percent;
            this._node.setScaleX(scaleX);
            this._node.setScaleY(scaleY);
        }
    },
    clone: function(){
        var frame = new ccs.ScaleFrame();
        frame.setScaleX(this._scaleX);
        frame.setScaleY(this._scaleY);
        frame._cloneProperty(this);
        return frame;
    },
    setScale: function(scale){
        this._scaleX = scale;
        this._scaleY = scale;
    },
    setScaleX: function(scaleX){
        this._scaleX = scaleX;
    },
    getScaleX: function(){
        return this._scaleX;
    },
    setScaleY: function(scaleY){
        this._scaleY = scaleY;
    },
    getScaleY: function(){
        return this._scaleY;
    }
});
ccs.ScaleFrame.create = function(){
    return new ccs.ScaleFrame();
};
ccs.AnchorPointFrame = ccs.Frame.extend({
    _anchorPoint: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._anchorPoint = cc.p(0, 0);
    },
    onEnter: function(nextFrame){
        if(this._node)
            this._node.setAnchorPoint(this._anchorPoint);
    },
    clone: function(){
        var frame = new ccs.AnchorPointFrame();
        frame.setAnchorPoint(this._anchorPoint);
        frame._cloneProperty(this);
        return frame;
    },
    setAnchorPoint: function(point){
        this._anchorPoint = point;
    },
    getAnchorPoint: function(){
        return this._anchorPoint;
    }
});
ccs.AnchorPointFrame.create = function(){
    return new ccs.AnchorPointFrame();
};
ccs.InnerActionType = {
    LoopAction : 0,
    NoLoopAction : 1,
    SingleFrame : 2
};
ccs.InnerActionFrame = ccs.Frame.extend({
    _innerActionType: null,
    _startFrameIndex: null,
    _endFrameIndex:0,
    _singleFrameIndex: 0,
    _enterWithName: null,
    _animationName: "",
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._enterWithName = false;
        this._innerActionType = ccs.InnerActionType.LoopAction;
        this._startFrameIndex = 0;
    },
    onEnter: function(nextFrame){
        if(!this._node)  return;
        var innerActiontimeline = this._node.getActionByTag(this._node.getTag());
        if(!innerActiontimeline) return;
        if (ccs.InnerActionType.SingleFrame === this._innerActionType){
            innerActiontimeline.gotoFrameAndPause(this._singleFrameIndex);
            return;
        }
        var innerStart = this._startFrameIndex;
        var innerEnd = this._endFrameIndex;
        if (this._enterWithName){
            if (this._animationName === "-- ALL --"){
                innerStart = 0;
                innerEnd = innerActiontimeline.getDuration();
            } else if(innerActiontimeline.isAnimationInfoExists(this._animationName)) {
                var info = innerActiontimeline.getAnimationInfo(this._animationName);
                innerStart = info.startIndex;
                innerEnd = info.endIndex;
            }else{
                cc.log("Animation %s not exists!", this._animationName);
            }
        }
        var duration = this._timeline.getActionTimeline().getDuration();
        var odddiff = duration - this._frameIndex - innerEnd + innerStart;
        if (odddiff < 0){
            innerEnd += odddiff;
        }
        if (ccs.InnerActionType.NoLoopAction === this._innerActionType){
            innerActiontimeline.gotoFrameAndPlay(innerStart, innerEnd, false);
        }else if (ccs.InnerActionType.LoopAction === this._innerActionType){
            innerActiontimeline.gotoFrameAndPlay(innerStart, innerEnd, true);
        }
    },
    setAnimationName: function(animationName){
        this._animationName = animationName;
    },
    setSingleFrameIndex: function(frameIndex){
        this._singleFrameIndex = frameIndex;
    },
    getSingleFrameIndex: function(){
        return this._startFrameIndex;
    },
    setEnterWithName: function(isEnterWithName){
        this._enterWithName = isEnterWithName;
    },
    getEnterWithName: function(){
        return this._enterWithName;
    },
    clone: function(){
        var frame = new ccs.InnerActionFrame();
        frame.setInnerActionType(this._innerActionType);
        frame.setStartFrameIndex(this._startFrameIndex);
        frame.setEnterWithName(this._enterWithName);
        frame.setAnimationName(this._animationName);
        frame.setSingleFrameIndex(this._singleFrameIndex);
        frame._cloneProperty(this);
        return frame;
    },
    setInnerActionType: function(type){
        this._innerActionType = type;
    },
    getInnerActionType: function(){
        return this._innerActionType;
    },
    setStartFrameIndex: function(frameIndex){
        this._startFrameIndex = frameIndex;
    },
    getStartFrameIndex: function(){
        return this._startFrameIndex;
    }
});
ccs.InnerActionFrame.create = function(){
    return new ccs.InnerActionFrame();
};
ccs.ColorFrame = ccs.Frame.extend({
    _alpha: null,
    _color: null,
    _betweenAlpha: null,
    _betweenRed: null,
    _betweenGreen: null,
    _betweenBlue: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._color = cc.color(255, 255, 255);
    },
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setColor(this._color);
        if(this._tween){
            var color = nextFrame._color;
            this._betweenRed   = color.r - this._color.r;
            this._betweenGreen = color.g - this._color.g;
            this._betweenBlue  = color.b - this._color.b;
        }
    },
    _onApply: function(percent){
        if (this._node && this._tween && (this._betweenAlpha !== 0 || this._betweenRed !== 0 || this._betweenGreen !== 0 || this._betweenBlue !== 0)){
            var color = cc.color(255, 255, 255);
            color.r = this._color.r + this._betweenRed   * percent;
            color.g = this._color.g + this._betweenGreen * percent;
            color.b = this._color.b + this._betweenBlue  * percent;
            this._node.setColor(color);
            if(this._alpha !== null){
                var alpha = this._alpha + this._betweenAlpha * percent;
                this._node.setOpacity(alpha);
            }
        }
    },
    clone: function(){
        var frame = new ccs.ColorFrame();
        frame.setColor(this._color);
        frame._cloneProperty(this);
        return frame;
    },
    setColor: function(color){
        this._color = color;
    },
    getColor: function(){
        return this._color;
    }
});
ccs.ColorFrame.create = function(){
    return new ccs.ColorFrame();
};
ccs.AlphaFrame = ccs.Frame.extend({
    _alpha: null,
    _betweenAlpha: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._alpha = 255;
    },
    onEnter: function(nextFrame){
        if(!this._node)
            return;
        this._node.setOpacity(this._alpha);
        if(this._tween){
            this._betweenAlpha = nextFrame._alpha - this._alpha;
        }
    },
    _onApply: function(percent){
        if(!this._node)
            return;
        var alpha = this._alpha + this._betweenAlpha * percent;
        this._node.setOpacity(alpha);
    },
    setAlpha: function(alpha){
        this._alpha = alpha;
    },
    getAlpha: function(){
        return this._alpha;
    },
    clone: function(){
        var frame = new ccs.AlphaFrame();
        frame.setAlpha(this._alpha);
        frame._cloneProperty(this);
        return frame;
    }
});
ccs.EventFrame = ccs.Frame.extend({
    _event: null,
    ctor: function(){
        ccs.Frame.prototype.ctor.call(this);
        this._event = "";
        this._enterWhenPassed = true;
    },
    onEnter: function(nextFrame){
        this._emitEvent();
    },
    clone: function(){
        var frame = new ccs.EventFrame();
        frame.setEvent(this._event);
        frame._cloneProperty(this);
        return frame;
    },
    setEvent: function(event){
        this._event = event;
    },
    getEvent: function(){
        return this._event;
    }
});
ccs.EventFrame.create = function(){
    return new ccs.EventFrame();
};
ccs.ZOrderFrame = ccs.Frame.extend({
    _zorder: 0,
    onEnter: function(nextFrame){
        if(this._node)
            this._node.setLocalZOrder(this._zorder);
    },
    clone: function(){
        var frame = new ccs.ZOrderFrame();
        frame.setZOrder(this._zorder);
        frame._cloneProperty(this);
        return frame;
    },
    setZOrder: function(zorder){
        this._zorder = zorder;
    },
    getZOrder: function(){
        return this._zorder;
    }
});
ccs.ZOrderFrame.create = function(){
    return new ccs.ZOrderFrame();
};
ccs.BlendFuncFrame = ccs.Frame.extend({
    ctor: function () {
        this._super();
        this._blendFunc = null;
    },
    onEnter: function(nextFrame, currentFrameIndex){
        if(this._node && this._blendFunc)
            this._node.setBlendFunc(this._blendFunc);
    },
    clone: function(){
        var frame = new ccs.BlendFuncFrame();
        frame.setBlendFunc(this._blendFunc);
        frame._cloneProperty(this);
        return frame;
    },
    setBlendFunc: function(blendFunc){
        if (blendFunc && blendFunc.src && blendFunc.dst)
            this._blendFunc = blendFunc;
    },
    getBlendFunc: function(){
        return this._blendFunc;
    }
});
ccs.BlendFuncFrame.create = function(){
    return new ccs.BlendFuncFrame();
};
ccs.Timeline = ccs.Class.extend({
    _frames: null,
    _currentKeyFrame: null,
    _currentKeyFrameIndex: null,
    _fromIndex: null,
    _toIndex: null,
    _betweenDuration: null,
    _actionTag: null,
    _ActionTimeline: null,
    _node: null,
    ctor: function(){
        this._frames = [];
        this._currentKeyFrame = null;
        this._currentKeyFrameIndex = 0;
        this._fromIndex = 0;
        this._toIndex = 0;
        this._betweenDuration = 0;
        this._actionTag = 0;
        this._ActionTimeline = null;
        this._node = null;
    },
    _gotoFrame: function(frameIndex){
        if(this._frames.length === 0)
            return;
        this._binarySearchKeyFrame(frameIndex);
        this._apply(frameIndex);
    },
    _stepToFrame: function(frameIndex){
        if(this._frames.length === 0)
            return;
        this._updateCurrentKeyFrame(frameIndex);
        this._apply(frameIndex);
    },
    getFrames: function(){
        return this._frames;
    },
    addFrame: function(frame){
        this._frames.push(frame);
        frame.setTimeline(this)
    },
    insertFrame: function(frame, index){
        this._frames.splice(index, 0, frame);
        frame.setTimeline(this);
    },
    removeFrame: function(frame){
        cc.arrayRemoveObject(this._frames, frame);
        frame.setTimeline(null);
    },
    setActionTag: function(tag){
        this._actionTag = tag;
    },
    getActionTag: function(){
        return this._actionTag;
    },
    setNode: function(node){
        for (var i=0; i<this._frames.length; i++){
            var frame = this._frames[i];
            frame.setNode(node);
        }
    },
    getNode: function(){
        return this._node;
    },
    setActionTimeline: function(action){
        this._ActionTimeline = action;
    },
    getActionTimeline: function(){
        return this._ActionTimeline;
    },
    clone: function(){
        var timeline = new ccs.Timeline();
        timeline._actionTag = this._actionTag;
        for (var i=0;i<this._frames.length;i++)
        {
            var frame = this._frames[i];
            var newFrame = frame.clone();
            timeline.addFrame(newFrame);
        }
        return timeline;
    },
    _apply: function(frameIndex){
        if (this._currentKeyFrame)
        {
            var currentPercent = this._betweenDuration <= 0 ? 0 : (frameIndex - this._currentKeyFrameIndex) / this._betweenDuration;
            this._currentKeyFrame.apply(currentPercent);
        }
    },
    _binarySearchKeyFrame: function(frameIndex){
        var from = null;
        var to   = null;
        var length = this._frames.length;
        var needEnterFrame = false;
        do{
            if (frameIndex < this._frames[0].getFrameIndex()){
                if(this._currentKeyFrameIndex >= this._frames[0].getFrameIndex())
                    needEnterFrame = true;
                this._fromIndex = 0;
                this._toIndex = 0;
                from = to = this._frames[0];
                this._currentKeyFrameIndex = 0;
                this._betweenDuration = this._frames[0].getFrameIndex();
                break;
            }else if(frameIndex >= this._frames[length - 1].getFrameIndex()){
                this._fromIndex = length - 1;
                this._toIndex = 0;
                from = to = this._frames[length - 1];
                this._currentKeyFrameIndex = this._frames[length - 1].getFrameIndex();
                this._betweenDuration = 0;
                break;
            }
            var target = -1;
            var low = 0,
                high = length - 1,
                mid = 0;
            while(low <= high){
                mid = Math.ceil(( low + high )/2);
                if(frameIndex >= this._frames[mid].getFrameIndex() && frameIndex < this._frames[mid + 1].getFrameIndex())
                {
                    target = mid;
                    break;
                }
                if(this._frames[mid].getFrameIndex()>frameIndex)
                    high = mid - 1;
                else
                    low = mid + 1;
            }
            this._fromIndex = target;
            if(length > 1)
                this._toIndex = (target + 1) | 0;
            else
                this._toIndex = (target) | 0;
            from = this._frames[this._fromIndex];
            to   = this._frames[this._toIndex];
            from = this._frames[target];
            to   = this._frames[target+1];
            if(target === 0 && this._currentKeyFrameIndex < from.getFrameIndex())
                needEnterFrame = true;
            this._currentKeyFrameIndex = from.getFrameIndex();
            this._betweenDuration = to.getFrameIndex() - from.getFrameIndex();
        } while (0);
        if(needEnterFrame || this._currentKeyFrame != from) {
            this._currentKeyFrame = from;
            this._currentKeyFrame.onEnter(to);
        }
    },
    _updateCurrentKeyFrame: function(frameIndex){
        if(frameIndex > 60)
            var a = 0;
        if (frameIndex < this._currentKeyFrameIndex || frameIndex >= this._currentKeyFrameIndex + this._betweenDuration)
        {
            var from = null;
            var to = null;
            do
            {
                var length = this._frames.length;
                if (frameIndex < this._frames[0].getFrameIndex())
                {
                    from = to = this._frames[0];
                    this._currentKeyFrameIndex = 0;
                    this._betweenDuration = this._frames[0].getFrameIndex();
                    break;
                }
                else if(frameIndex >= this._frames[length - 1].getFrameIndex())
                {
                    var lastFrameIndex = this._frames[length - 1].getFrameIndex();
                    if(this._currentKeyFrameIndex >= lastFrameIndex)
                        return;
                    frameIndex = lastFrameIndex;
                }
                do{
                    this._fromIndex = this._toIndex;
                    from = this._frames[this._fromIndex];
                    this._currentKeyFrameIndex  = from.getFrameIndex();
                    this._toIndex = this._fromIndex + 1;
                    if (this._toIndex >= length)
                    {
                        this._toIndex = 0;
                    }
                    to = this._frames[this._toIndex];
                    if (frameIndex === from.getFrameIndex())
                        break;
                    if(frameIndex > from.getFrameIndex() && frameIndex < to.getFrameIndex())
                        break;
                    if(from.isEnterWhenPassed())
                        from.onEnter(to);
                }while (true);
                this._betweenDuration = to.getFrameIndex() - from.getFrameIndex();
            } while (0);
            this._currentKeyFrame = from;
            this._currentKeyFrame.onEnter(to);
        }
    }
});
ccs.Timeline.create = function(){
    return new ccs.Timeline();
};
ccs.SkinNode = (function(){
    var Node = cc.Node;
    var proto = {
    };
    var SkinNode = Node.extend(proto);
    SkinNode.create = function(){};
    return SkinNode;
})();
ccs.BoneNode = (function () {
    var Node = cc.Node;
    var SkinNode = ccs.SkinNode;
    var BlendFunc = cc.BlendFunc;
    var type = {
        p: cc.p,
        size: cc.size,
        rect: cc.rect
    };
    var debug = {
        log: cc.log,
        assert: cc.assert
    };
    var BoneNode = Node.extend({
        _customCommand: null,
        _blendFunc: null,
        _rackColor: null,
        _rackLength: null,
        _rackWidth: null,
        _childBones: null,
        _boneSkins: null,
        _rootSkeleton: null,
        _squareVertices: null,
        _squareColors: null,
        _noMVPVertices: null,
        ctor: function (length) {
            Node.prototype.ctor.call(this);
            if (this._squareVertices === null)
                this._squareVertices = [
                    {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}
                ];
            this._rackColor = cc.color.WHITE;
            this._blendFunc = BlendFunc.ALPHA_NON_PREMULTIPLIED;
            this._childBones = [];
            this._boneSkins = [];
            this._rackLength = length === undefined ? 50 : length;
            this._rackWidth = 20;
            this._updateVertices();
        },
        addSkin: function (skin, display, hideOthers) {
            var boneSkins = this._boneSkins;
            debug.assert(skin != null, "Argument must be non-nil");
            if (hideOthers) {
                for (var i = 0; i < boneSkins.length; i++) {
                    boneSkins[i].setVisible(false);
                }
            }
            Node.prototype.addChild.call(this, skin);
            this._boneSkins.push(skin);
            skin.setVisible(display);
        },
        getChildBones: function () {
            return this._childBones;
        },
        getSkins: function () {
            return this._boneSkins;
        },
        displaySkin: function (skin, hideOthers) {
            var boneSkins = this._boneSkins;
            var boneSkin, i;
            if (typeof skin === "string") {
                for (i = 0; i < boneSkins.length; i++) {
                    boneSkin = boneSkins[i];
                    if (skin == boneSkin.getName()) {
                        boneSkin.setVisible(true);
                    } else if (hideOthers) {
                        boneSkin.setVisible(false);
                    }
                }
            } else {
                for (i = 0; i < boneSkins.length; i++) {
                    boneSkin = boneSkins[i];
                    if (boneSkin == skin) {
                        boneSkin.setVisible(true);
                    } else if (hideOthers) {
                        boneSkin.setVisible(false);
                    }
                }
            }
        },
        getVisibleSkins: function () {
            var displayingSkins = [];
            var boneSkins = this._boneSkins;
            for (var boneSkin, i = 0; i < boneSkins.length; i++) {
                boneSkin = boneSkins[i];
                if (boneSkin.isVisible()) {
                    displayingSkins.push(boneSkin);
                }
            }
            return displayingSkins;
        },
        getRootSkeletonNode: function () {
            return this._rootSkeleton;
        },
        getAllSubBones: function () {
            var allBones = [];
            var boneStack = [];
            var childBones = this._childBones;
            for (var i = 0; i < childBones.length; i++) {
                boneStack.push(childBones[i]);
            }
            while (boneStack.length > 0) {
                var top = boneStack.pop();
                allBones.push(top);
                var topChildren = top.getChildBones();
                for (var j = 0; j < topChildren; j++) {
                    boneStack.push(topChildren[j]);
                }
            }
            return allBones;
        },
        getAllSubSkins: function () {
            var allBones = this.getAllSubBones();
            var allSkins = [];
            for (var i = 0; i < allBones.length; i++) {
                var skins = allBones[i].getSkins();
                for (var j = 0; j < skins.length; j++) {
                    allSkins.push(skins[i]);
                }
            }
            return allSkins;
        },
        addChild: function (child, localZOrder, tag) {
            Node.prototype.addChild.call(this, child, localZOrder, tag);
            this._addToChildrenListHelper(child);
        },
        removeChild: function (child, cleanup) {
            if(this._children.indexOf(child) !== -1){
                Node.prototype.removeChild.call(this, child, cleanup);
                this._removeFromChildrenListHelper(child);
            }
        },
        setBlendFunc: function (blendFunc) {
            var ob = this._blendFunc;
            if(blendFunc && ob.src !== blendFunc.src && ob.dst !== blendFunc.dst){
                this._blendFunc = blendFunc;
                var boneSkins = this._boneSkins;
                for (var boneSkin, i = 0; i < boneSkins.length; i++) {
                    boneSkin = boneSkins[i];
                    boneSkin.setBlendFunc(blendFunc);
                }
            }
        },
        getBlendFunc: function () {
            return this._blendFunc;
        },
        setDebugDrawLength: function (length) {
            this._rackLength = length;
            this._updateVertices();
        },
        getDebugDrawLength: function () {
            return this._rackLength;
        },
        setDebugDrawWidth: function (width) {
            this._rackWidth = width;
            this._updateVertices();
        },
        getDebugDrawWidth: function () {
            return this._rackWidth;
        },
        setDebugDrawEnabled: function (isDebugDraw) {
            var renderCmd = this._renderCmd;
            if (renderCmd._debug === isDebugDraw)
                return;
            renderCmd._debug = isDebugDraw;
            cc.renderer.childrenOrderDirty = true;
            if(this._visible && null != this._rootSkeleton){
                this._rootSkeleton._subBonesDirty = true;
                this._rootSkeleton._subBonesOrderDirty = true;
            }
        },
        isDebugDrawEnabled: function () {
            return this._renderCmd._debug;
        },
        setDebugDrawColor: function (color) {
            this._rackColor = color;
        },
        getDebugDrawColor: function () {
            return this._rackColor;
        },
        getVisibleSkinsRect: function () {
            var minx, miny, maxx, maxy = 0;
            minx = miny = maxx = maxy;
            var first = true;
            var displayRect = type.rect(0, 0, 0, 0);
            if (this._renderCmd._debug && this._rootSkeleton != null && this._rootSkeleton._renderCmd._debug) {
                maxx = this._rackWidth;
                maxy = this._rackLength;
                first = false;
            }
            var boneSkins = this._boneSkins;
            for (var skin, i = 0; i < boneSkins.length; i++) {
                skin = boneSkins[i];
                var r = skin.getBoundingBox();
                if (!skin.isVisible() || (r.x === 0 && r.y === 0 && r.width === 0 && r.height === 0))
                    continue;
                if (first) {
                    minx = cc.rectGetMinX(r);
                    miny = cc.rectGetMinY(r);
                    maxx = cc.rectGetMaxX(r);
                    maxy = cc.rectGetMaxY(r);
                    first = false;
                } else {
                    minx = Math.min(cc.rectGetMinX(r), minx);
                    miny = Math.min(cc.rectGetMinY(r), miny);
                    maxx = Math.max(cc.rectGetMaxX(r), maxx);
                    maxy = Math.max(cc.rectGetMaxY(r), maxy);
                }
                displayRect.setRect(minx, miny, maxx - minx, maxy - miny);
            }
            return displayRect;
        },
        getBoundingBox: function () {
            var boundingBox = this.getVisibleSkinsRect();
            return cc.rectApplyAffineTransform(boundingBox, this.getNodeToParentAffineTransform());
        },
        batchBoneDrawToSkeleton: function (bone) {},
        setLocalZOrder: function (localZOrder) {
            Node.prototype.setLocalZOrder.call(this, localZOrder);
            if (this._rootSkeleton != null)
                this._rootSkeleton._subBonesOrderDirty = true;
        },
        setName: function (name) {
            var rootSkeleton = this._rootSkeleton;
            var oldName = this.getName();
            Node.prototype.setName.call(this, name);
            if (rootSkeleton != null) {
                var oIter = rootSkeleton._subBonesMap[oldName];
                var nIter = rootSkeleton._subBonesMap[name];
                if (oIter && !nIter) {
                    delete rootSkeleton._subBonesMap[oIter];
                    rootSkeleton._subBonesMap[name] = oIter;
                }
            }
        },
        setContentSize: function(contentSize){
            Node.prototype.setContentSize.call(this, contentSize);
            this._updateVertices();
        },
        setAnchorPoint: function(anchorPoint){
            Node.prototype.setAnchorPoint.call(this, anchorPoint);
            this._updateVertices();
        },
        setVisible: function (visible) {
            if (this._visible == visible)
                return;
            Node.prototype.setVisible.call(this, visible);
            if (this._rootSkeleton != null){
                this._rootSkeleton._subBonesDirty = true;
                this._rootSkeleton._subBonesOrderDirty = true;
            }
        },
        _addToChildrenListHelper: function (child) {
            if (child instanceof BoneNode) {
                this._addToBoneList(child);
            } else {
                    this._addToSkinList(child);
            }
        },
        _removeFromChildrenListHelper: function (child) {
            if (child instanceof BoneNode) {
                this._removeFromBoneList(child);
            }else{
                if (child instanceof SkinNode)
                    this._removeFromSkinList(skin);
            }
        },
        _removeFromBoneList: function (bone) {
            if(
                this._rootSkeleton != null &&
                bone instanceof ccs.SkeletonNode &&
                bone._rootSkeleton === this._rootSkeleton
            ){
                bone._rootSkeleton = null;
                var subBones = bone.getAllSubBones();
                subBones.push(bone);
                for (var subBone, i = 0; i < subBones.length; i++) {
                    subBone = subBones[i];
                    subBone._rootSkeleton = null;
                    delete this._rootSkeleton._subBonesMap[subBone.getName()];
                    this._rootSkeleton._subBonesDirty = true;
                    this._rootSkeleton._subBonesOrderDirty = true;
                }
            }else{
                this._rootSkeleton._subBonesDirty = true;
                this._rootSkeleton._subBonesOrderDirty = true;
            }
            cc.arrayRemoveObject(this._childBones, bone);
        },
        _setRootSkeleton: function(rootSkeleton){
            this._rootSkeleton = rootSkeleton;
            var subBones = this.getAllSubBones();
            for (var i = 0; i < subBones.length; i++) {
                this._addToBoneList(subBones[i]);
            }
        },
        _addToBoneList: function (bone) {
            if(this._childBones.indexOf(bone) === -1)
                this._childBones.push(bone);
            if (this._rootSkeleton != null) {
                var skeletonNode = bone;
                if (!(skeletonNode instanceof SkinNode) && !bone._rootSkeleton) {// not nest skeleton
                    var subBones = bone.getAllSubBones();
                    subBones.push(bone);
                    for (var subBone, i = 0; i < subBones.length; i++) {
                        subBone = subBones[i];
                        subBone._setRootSkeleton(this._rootSkeleton);
                        var bonename = subBone.getName();
                        if (!this._rootSkeleton._subBonesMap[bonename]){
                            this._rootSkeleton._subBonesMap[subBone.getName()] = subBone;
                            this._rootSkeleton._subBonesDirty = true;
                            this. _rootSkeleton._subBonesOrderDirty = true;
                        }else{
                            cc.log("already has a bone named %s in skeleton %s", bonename, this._rootSkeleton.getName());
                            this._rootSkeleton._subBonesDirty = true;
                            this. _rootSkeleton._subBonesOrderDirty = true;
                        }
                    }
                }
            }
        },
        _visitSkins: function(){
            var cmd = this._renderCmd;
            if (!this._visible)
                return;
            var parentCmd = cmd.getParentRenderCmd();
            if (parentCmd)
                cmd._curLevel = parentCmd._curLevel + 1;
            var i, children = this._boneSkins, child;
            cmd._syncStatus(parentCmd);
            var len = children.length;
            if (len > 0) {
                this.sortAllChildren();
                for (i = 0; i < len; i++) {
                    child = children[i];
                    if (child._localZOrder < 0)
                        child._renderCmd.visit(cmd);
                    else
                        break;
                }
                for (; i < len; i++)
                    children[i]._renderCmd.visit(cmd);
            }
            cmd._dirtyFlag = 0;
        },
        _addToSkinList: function (skin) {
            this._boneSkins.push(skin);
            if (skin.getBlendFunc){
                var blendFunc = skin.getBlendFunc();
                if(this._blendFunc.src !== blendFunc.src && this._blendFunc.dst !== blendFunc.dst)
                    skin.setBlendFunc(this._blendFunc);
            }
        },
        _removeFromSkinList: function (skin) {
            cc.arrayRemoveObject(this._boneSkins, skin);
        },
        sortAllChildren: function () {
            this._sortArray(this._childBones);
            this._sortArray(this._boneSkins);
            Node.prototype.sortAllChildren.call(this);
        },
        _sortArray: function (array) {
            if (!array)
                return;
            var len = array.length, i, j, tmp;
            for (i = 1; i < len; i++) {
                tmp = array[i];
                j = i - 1;
                while (j >= 0) {
                    if (tmp._localZOrder < array[j]._localZOrder) {
                        array[j + 1] = array[j];
                    } else if (tmp._localZOrder === array[j]._localZOrder && tmp.arrivalOrder < array[j].arrivalOrder) {
                        array[j + 1] = array[j];
                    } else {
                        break;
                    }
                    j--;
                }
                array[j + 1] = tmp;
            }
        },
        _updateVertices: function () {
            var squareVertices = this._squareVertices,
                  anchorPointInPoints = this._renderCmd._anchorPointInPoints;
            if (this._rackLength != squareVertices[2].x - anchorPointInPoints.x ||
                squareVertices[3].y != this._rackWidth / 2  - anchorPointInPoints.y) {
                squareVertices[1].x = squareVertices[1].y = squareVertices[3].y = 0;
                squareVertices[0].x = squareVertices[2].x = this._rackLength * .1;
                squareVertices[2].y = this._rackWidth * .5;
                squareVertices[0].y = -squareVertices[2].y;
                squareVertices[3].x = this._rackLength;
                for(var i=0; i<squareVertices.length; i++){
                    squareVertices[i].x += anchorPointInPoints.x;
                    squareVertices[i].y += anchorPointInPoints.y;
                }
                this._renderCmd.updateDebugPoint(squareVertices);
            }
        },
        _createRenderCmd: function () {
            if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
                return new BoneNodeCanvasCmd(this);
            else
                return new BoneNodeWebGLCmd(this);
        }
    });
    BoneNode.create = function (length, color) {
        return new ccui.BoneNode(length, color);
    };
    var BoneNodeCanvasCmd = (function () {
        var BoneNodeCanvasCmd = function (node) {
            Node.CanvasRenderCmd.call(this, node);
            this._debug = false;
            this._color = cc.color.WHITE;
            this._drawNode = new cc.DrawNode();
        };
        var proto = BoneNodeCanvasCmd.prototype = Object.create(Node.CanvasRenderCmd.prototype);
        proto.constructor = BoneNodeCanvasCmd;
        proto.visit = function (parentCmd) {
            var node = this._node;
            node._visit && node._visit(parentCmd);
        };
        proto.updateDebugPoint = function (points) {
            this._drawNode.clear();
            this._drawNode.drawPoly(points, this._color, 0, this._color);
        };
        proto.transform = function (parentCmd, recursive) {
            var rootSkeleton = this._node._rootSkeleton;
            Node.CanvasRenderCmd.prototype.transform.call(this, parentCmd, recursive);
            if (rootSkeleton && rootSkeleton._renderCmd._debug) {
                this._drawNode._renderCmd.transform(this);
            }
        };
        return BoneNodeCanvasCmd;
    })();
    var BoneNodeWebGLCmd = (function () {
        var BoneNodeWebGLCmd = function (node) {
            Node.WebGLRenderCmd.call(this, node);
            this._debug = false;
            this._color = cc.color.WHITE;
            this._drawNode = new cc.DrawNode();
        };
        var proto = BoneNodeWebGLCmd.prototype = Object.create(Node.WebGLRenderCmd.prototype);
        proto.constructor = BoneNodeWebGLCmd;
        proto.visit = function (parentCmd) {
            var node = this._node;
            node._visit && node._visit(parentCmd);
        };
        proto.updateDebugPoint = function (points) {
            this._drawNode.clear();
            this._drawNode.drawPoly(points, this._color, 0, this._color);
        };
        proto.transform = function (parentCmd, recursive) {
            var rootSkeleton = this._node._rootSkeleton;
            Node.WebGLRenderCmd.prototype.transform.call(this, parentCmd, recursive);
            if (rootSkeleton && rootSkeleton._renderCmd._debug) {
                this._drawNode._renderCmd.transform(this);
            }
        };
        return BoneNodeWebGLCmd;
    })();
    return BoneNode;
})();
ccs.SkeletonNode = (function(){
    var BoneNode = ccs.BoneNode;
    var type = {
        p: cc.p,
        size: cc.size,
        rect: cc.rect
    };
    var SkeletonNode = BoneNode.extend({
        _subBonesMap: null,
        _squareVertices: null,
        _squareColors: null,
        _noMVPVertices: null,
        _skinGroupMap: null,
        _sortedAllBonesDirty: false,
        _sortedAllBones: null,
        _batchedBoneVetices: null,
        _batchedBoneColors: null,
        _batchedVeticesCount: null,
        _batchBoneCommand: null,
        _subOrderedAllBones: null,
        ctor: function(){
            this._squareVertices = [
                {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0},
                {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}
            ];
            this._rootSkeleton = this;
            BoneNode.prototype.ctor.call(this);
            this._subBonesMap = {};
            this._subOrderedAllBones = [];
            this._skinGroupMap = {};
            this._rackLength = this._rackWidth = 20;
            this._updateVertices();
        },
        getBoneNode: function(boneName){
            var item = this._subBonesMap[boneName];
            if(item)
                return item;
            return null;
        },
        getAllSubBonesMap: function(){
            return this._subBonesMap;
        },
        changeSkins: function(boneSkinNameMap){
            if(typeof boneSkinNameMap === "object"){
                var boneSkin;
                for(var name in boneSkinNameMap){
                    boneSkin = boneSkinNameMap[name];
                    var bone = this.getBoneNode(name);
                    if(null !== bone)
                        bone.displaySkin(boneSkin, true);
                }
            }else{
                var suit = this._suitMap[boneSkinNameMap];
                if (suit)
                    this.changeSkins(suit, true);
            }
        },
        addSkinGroup: function(groupName, boneSkinNameMap){
            this._skinGroupMap[groupName] = boneSkinNameMap;
        },
        getBoundingBox: function(){
            var minx, miny, maxx, maxy = 0;
            minx = miny = maxx = maxy;
            var boundingBox = this.getVisibleSkinsRect();
            var first = true;
            if(boundingBox.x !== 0 || boundingBox.y !== 0 || boundingBox.width !== 0 || boundingBox.height !== 0){
                minx = cc.rectGetMinX(boundingBox);
                miny = cc.rectGetMinY(boundingBox);
                maxx = cc.rectGetMaxX(boundingBox);
                maxy = cc.rectGetMaxY(boundingBox);
                first = false;
            }
            var allBones = this.getAllSubBones();
            for(var bone, i=0; i<allBones.length; i++){
                bone = allBones[i];
                var r = cc.rectApplyAffineTransform(bone.getVisibleSkinsRect(), bone.getNodeToParentTransform(bone.getRootSkeletonNode()));
                if (r.x === 0 && r.y === 0 && r.width === 0 && r.height === 0)
                    continue;
                if(first){
                    minx = cc.rectGetMinX(r);
                    miny = cc.rectGetMinY(r);
                    maxx = cc.rectGetMaxX(r);
                    maxy = cc.rectGetMaxY(r);
                    first = false;
                }else{
                    minx = Math.min(cc.rectGetMinX(r), minx);
                    miny = Math.min(cc.rectGetMinY(r), miny);
                    maxx = Math.max(cc.rectGetMaxX(r), maxx);
                    maxy = Math.max(cc.rectGetMaxY(r), maxy);
                }
            }
            boundingBox.x = minx;
            boundingBox.y = miny;
            boundingBox.width = maxx - minx;
            boundingBox.height = maxy - miny;
            return cc.rectApplyAffineTransform(boundingBox, this.getNodeToParentTransform());
        },
        _visit: function(parentCmd){
            if(!this._visible)
                return;
            var cmd = this._renderCmd;
            parentCmd = parentCmd || cmd.getParentRenderCmd();
            cmd._syncStatus(parentCmd);
            var i, node;
            if(this._children.length !== 0){
                for (i=0; i < this._children.length; i++){
                    node = this._children[i];
                    node._renderCmd.visit(cmd);
                }
            }
            this._checkSubBonesDirty();
            var subOrderedAllBones = this._subOrderedAllBones,
                subOrderedBone, subOrderedBoneCmd;
            for (i=0; i<subOrderedAllBones.length; i++){
                subOrderedBone = subOrderedAllBones[i];
                subOrderedBone._visitSkins();
            }
            if(cmd._debug)
                for (i=0; i<subOrderedAllBones.length; i++){
                    subOrderedBoneCmd = subOrderedAllBones[i]._renderCmd;
                    cc.renderer.pushRenderCommand(subOrderedBoneCmd._drawNode._renderCmd);
                }
            this._dirtyFlag = 0;
        },
        _checkSubBonesDirty: function(){
            if (this._subBonesDirty){
                this._updateOrderedAllbones();
                this._subBonesDirty = false;
            }
            if (this._subBonesOrderDirty){
                this._sortOrderedAllBones();
                this._subBonesOrderDirty = false;
            }
        },
        _updateOrderedAllbones: function(){
            this._subOrderedAllBones.length = 0;
            var boneStack = [];
            var childBones = this._childBones;
            for (var bone, i=0; i<childBones.length; i++){
                bone = childBones[i];
                if (bone.isVisible())
                    boneStack.push(bone);
            }
            while(boneStack.length > 0){
                var top = boneStack.pop();
                var topCmd = top._renderCmd;
                topCmd._syncStatus(topCmd.getParentRenderCmd());
                this._subOrderedAllBones.push(top);
                var topChildren = top.getChildBones();
                for (var childbone, i=0; i<topChildren.length; i++){
                    childbone = topChildren[i];
                    if (childbone.isVisible())
                        boneStack.push(childbone);
                }
            }
        },
        _sortOrderedAllBones: function(){
            this._sortArray(this._subOrderedAllBones);
        },
        _updateVertices: function(){
            var squareVertices = this._squareVertices,
                anchorPointInPoints = this._renderCmd._anchorPointInPoints;
            if(this._rackLength != squareVertices[6].x - anchorPointInPoints.x ||
                this._rackWidth != squareVertices[3].y - anchorPointInPoints.y){
                var radiusl = this._rackLength * .5;
                var radiusw = this._rackWidth * .5;
                var radiusl_2 = radiusl * .25;
                var radiusw_2 = radiusw * .25;
                squareVertices[5].y = squareVertices[2].y = squareVertices[1].y = squareVertices[6].y
                    = squareVertices[0].x = squareVertices[4].x = squareVertices[7].x = squareVertices[3].x = .0;
                squareVertices[5].x = -radiusl; squareVertices[0].y = -radiusw;
                squareVertices[6].x = radiusl;  squareVertices[3].y = radiusw;
                squareVertices[1].x = radiusl_2; squareVertices[7].y = radiusw_2;
                squareVertices[2].x = -radiusl_2; squareVertices[4].y = -radiusw_2;
                for(var i=0; i<squareVertices.length; i++){
                    squareVertices[i].x += anchorPointInPoints.x;
                    squareVertices[i].y += anchorPointInPoints.y;
                }
            }
        },
        _updateAllDrawBones: function(){
            this._subDrawBones = {};
            for(var name in this._subBonesMap){
                var bone = this._subBonesMap[name];
                if (bone.isVisible() && bone.isDebugDrawEnabled())
                    this._subDrawBones.push(bone);
            }
            this._sortArray(this._sortedAllBones);
            this._subDrawBones = false;
        }
    });
    SkeletonNode.create = function(){
        return new SkeletonNode;
    };
    return SkeletonNode;
})();
ccs._load = (function(){
    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;
    };
    var extname = function(fileName){
        var arr = fileName.match(extnameReg);
        return ( arr && arr[1] ) ? arr[1] : null;
    };
    var extnameReg = /\.([^\.]+)$/;
    var parserReg = /([^\.](\.\*)?)*$/;
    var getParser = function(parser, version){
        if(parser[version])
            return parser[version];
        else if(version === "*")
            return null;
        else
            return getParser(parser, version.replace(parserReg, "*"));
    };
    return load;
})();
ccs._parser = cc.Class.extend({
    ctor: function(){
        this.parsers = {};
    },
    _dirnameReg: /\S*\//,
    _dirname: function(path){
        var arr = path.match(this._dirnameReg);
        return (arr && arr[0]) ? arr[0] : "";
    },
    getClass: function(json){
        return json["classname"];
    },
    getNodeJson: function(json){
        return json["widgetTree"];
    },
    parse: function(file, json, resourcePath){
        resourcePath = resourcePath || this._dirname(file);
        this.pretreatment(json, resourcePath);
        var node = this.parseNode(this.getNodeJson(json), resourcePath, file);
        node && this.deferred(json, resourcePath, node, file);
        return node;
    },
    pretreatment: function(json, resourcePath, file){},
    deferred: function(json, resourcePath, node, file){},
    parseNode: function(json, resourcePath){
        var parser = this.parsers[this.getClass(json)];
        var widget = null;
        if(parser)
            widget = parser.call(this, json, resourcePath);
        else
            cc.log("Can't find the parser : %s", this.getClass(json));
        return widget;
    },
    registerParser: function(widget, parse){
        this.parsers[widget] = parse;
    }
});
ccs.load = function(file, path){
    var object = {
        node: null,
        action: null
    };
    object.node = ccs._load(file, null, path);
    object.action = ccs._load(file, "action", path);
    if(object.action && object.action.tag === -1 && object.node)
        object.action.tag = object.node.tag;
    return object;
};
ccs.load.validate = {};
ccs.load.preload = true;
ccs.loadWithVisibleSize = function(file, path){
    var object = ccs.load(file, path);
    var size = cc.director.getVisibleSize();
    if(object.node && size){
        object.node.setContentSize(size.width, size.height);
        ccui.helper.doLayout(object.node);
    }
    return object;
};
ccs.actionTimelineCache = {
    createAction: function(file){
        return ccs._load(file, "action");
    }
};
ccs.csLoader = {
    createNode: function(file){
        return ccs._load(file);
    }
};
cc.loader.register(["json"], {
    load : function(realUrl, url, res, cb){
        cc.loader.loadJson(realUrl, function(error, data){
            var path = cc.path;
            if(data && data["Content"] && data["Content"]["Content"]["UsedResources"]){
                var UsedResources = data["Content"]["Content"]["UsedResources"],
                    dirname = path.dirname(url),
                    list = [],
                    tmpUrl, normalUrl;
                for(var i=0; i<UsedResources.length; i++){
                    if (!ccs.load.preload && /\.(png|jpg$)/.test(UsedResources[i]))
                        continue;
                    tmpUrl = path.join(dirname, UsedResources[i]);
                    normalUrl = path._normalize(tmpUrl);
                    if(!ccs.load.validate[normalUrl]){
                        ccs.load.validate[normalUrl] = true;
                        list.push(normalUrl);
                    }
                }
                cc.loader.load(list, function(){
                    cb(error, data);
                });
            }else{
                cb(error, data);
            }
        });
    }
});
(function(load, baseParser){
    var Parser = baseParser.extend({
        getNodeJson: function(json){
            return json["action"];
        },
        parseNode: function(json, resourcePath, file){
            if(!json)
                return null;
            var self = this,
                action = new ccs.ActionTimeline();
            action.setDuration(json["duration"]);
            action.setTimeSpeed(json["speed"] || 1);
            var timelines = json["timelines"];
            timelines.forEach(function(timeline){
                var parser = self.parsers[timeline["frameType"]];
                var frame;
                if(parser)
                    frame = parser.call(self, timeline, resourcePath);
                else
                    cc.log("parser does not exist : %s", timeline["frameType"]);
                if(frame)
                    action.addTimeline(frame);
                if(timeline["frameType"] === "ColorFrame"){
                    action.addTimeline(
                        self.parsers["AlphaFrame"].call(self, timeline, resourcePath)
                    );
                }
            });
            return action;
        }
    });
    var parser = new Parser();
    var frameList = [
        {
            name: "PositionFrame",
            handle: function(options){
                var frame = new ccs.PositionFrame();
                var x = options["x"];
                var y = options["y"];
                frame.setPosition(cc.p(x,y));
                return frame;
            }
        },
        {
            name: "VisibleFrame",
            handle: function(options){
                var frame = new ccs.VisibleFrame();
                var visible = options["value"];
                frame.setVisible(visible);
                return frame;
            }
        },
        {
            name: "ScaleFrame",
            handle: function(options){
                var frame = new ccs.ScaleFrame();
                var scalex = options["x"];
                var scaley = options["y"];
                frame.setScaleX(scalex);
                frame.setScaleY(scaley);
                return frame;
            }
        },
        {
            name: "RotationFrame",
            handle: function(options){
                var frame = new ccs.RotationFrame();
                var rotation = options["rotation"];
                frame.setRotation(rotation);
                return frame;
            }
        },
        {
            name: "SkewFrame",
            handle: function(options){
                var frame = new ccs.SkewFrame();
                var skewx = options["x"];
                var skewy = options["y"];
                frame.setSkewX(skewx);
                frame.setSkewY(skewy);
                return frame;
            }
        },
        {
            name: "RotationSkewFrame",
            handle: function(options){
                var frame = new ccs.RotationSkewFrame();
                var skewx = options["x"];
                var skewy = options["y"];
                frame.setSkewX(skewx);
                frame.setSkewY(skewy);
                return frame;
            }
        },
        {
            name: "AnchorFrame",
            handle: function(options){
                var frame = new ccs.AnchorPointFrame();
                var anchorx = options["x"];
                var anchory = options["y"];
                frame.setAnchorPoint(cc.p(anchorx, anchory));
                return frame;
            }
        },
        {
            name: "InnerActionFrame",
            handle: function(options){
                var frame = new ccs.InnerActionFrame();
                var type = options["innerActionType"];
                var startFrame = options["startFrame"];
                frame.setInnerActionType(type);
                frame.setStartFrameIndex(startFrame);
                return frame;
            }
        },
        {
            name: "ColorFrame",
            handle: function(options){
                var frame = new ccs.ColorFrame();
                var red   = options["red"];
                var green = options["green"];
                var blue  = options["blue"];
                frame.setColor(cc.color(red, green, blue));
                var alphaFrame = new ccs.AlphaFrame();
                var alpha = options["alpha"];
                alphaFrame.setAlpha(alpha);
                return frame;
            }
        },
        {
            name: "AlphaFrame",
            handle: function(options){
                var frame = new ccs.AlphaFrame();
                var alpha = options["alpha"];
                frame.setAlpha(alpha);
                return frame;
            }
        },
        {
            name: "TextureFrame",
            handle: function(options){
                var frame = new ccs.TextureFrame();
                var texture = options["value"];
                if(texture != null) {
                    var path = texture;
                    var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
                    if(spriteFrame == null){
                        var jsonPath = ccs.csLoader.getJsonPath();
                        path = jsonPath + texture;
                    }
                    frame.setTextureName(path);
                }
                return frame;
            }
        },
        {
            name: "EventFrame",
            handle: function(options){
                var frame = new ccs.EventFrame();
                var evnt = options["value"];
                if(evnt != null)
                    frame.setEvent(evnt);
                return frame;
            }
        },
        {
            name: "ZOrderFrame",
            handle: function(options){
                var frame = new ccs.ZOrderFrame();
                var zorder = options["value"];
                frame.setZOrder(zorder);
                return frame;
            }
        }
    ];
    frameList.forEach(function(item){
        parser.registerParser(item.name, function(options, resourcePath){
            var timeline = new ccs.Timeline();
            timeline.setActionTag(options["actionTag"]);
            var frames = options["frames"];
            if(frames && frames.length){
                frames.forEach(function(frameData){
                    var frame = item.handle(frameData);
                    frame.setFrameIndex(frameData["frameIndex"]);
                    frame.setTween(frameData["tween"]);
                    timeline.addFrame(frame);
                });
            }
            return timeline;
        });
    });
    load.registerParser("action", "0.*", parser);
    load.registerParser("action", "1.*", parser);
})(ccs._load, ccs._parser);
(function(load, baseParser){
    var Parser = baseParser.extend({
        getNodeJson: function(json){
            return json["Content"]["Content"]["Animation"];
        },
        parseNode: function(json, resourcePath, file){
            if(!json)
                return null;
            var self = this,
                action = new ccs.ActionTimeline();
            action.setDuration(json["Duration"]);
            action.setTimeSpeed(json["Speed"] || 1);
            var timelines = json["Timelines"];
            timelines.forEach(function(timeline){
                var parser = self.parsers[timeline["Property"]];
                var frame;
                if(parser)
                    frame = parser.call(self, timeline, resourcePath);
                else
                    cc.log("parser does not exist : %s", timeline["Property"]);
                if(frame)
                    action.addTimeline(frame);
            });
            return action;
        },
        deferred: function(json, resourcePath, action, file){
            var animationlist = json["Content"]["Content"]["AnimationList"];
            var length = animationlist ? animationlist.length : 0;
            for (var i = 0; i < length; i++){
                var animationdata = animationlist[i];
                var info = { name: null, startIndex: null, endIndex: null };
                info.name = animationdata["Name"];
                info.startIndex = animationdata["StartIndex"];
                info.endIndex = animationdata["EndIndex"];
                action.addAnimationInfo(info);
            }
        }
    });
    var parser = new Parser();
    var frameList = [
        {
            name: "Position",
            handle: function(options){
                var frame = new ccs.PositionFrame();
                var x = options["X"];
                var y = options["Y"];
                frame.setPosition(cc.p(x,y));
                return frame;
            }
        },
        {
            name: "VisibleForFrame",
            handle: function(options){
                var frame = new ccs.VisibleFrame();
                var visible = options["Value"];
                frame.setVisible(visible);
                return frame;
            }
        },
        {
            name: "Scale",
            handle: function(options){
                var frame = new ccs.ScaleFrame();
                var scalex = options["X"];
                var scaley = options["Y"];
                frame.setScaleX(scalex);
                frame.setScaleY(scaley);
                return frame;
            }
        },
        {
            name: "Rotation",
            handle: function(options){
                var frame = new ccs.RotationFrame();
                var rotation = options["Rotation"] || options["Value"] || 0;
                frame.setRotation(rotation);
                return frame;
            }
        },
        {
            name: "Skew",
            handle: function(options){
                var frame = new ccs.SkewFrame();
                var skewx = options["X"];
                var skewy = options["Y"];
                frame.setSkewX(skewx);
                frame.setSkewY(skewy);
                return frame;
            }
        },
        {
            name: "RotationSkew",
            handle: function(options){
                var frame = new ccs.RotationSkewFrame();
                var skewx = options["X"];
                var skewy = options["Y"];
                frame.setSkewX(skewx);
                frame.setSkewY(skewy);
                return frame;
            }
        },
        {
            name: "Anchor",
            handle: function(options){
                var frame = new ccs.AnchorPointFrame();
                var anchorx = options["X"];
                var anchory = options["Y"];
                frame.setAnchorPoint(cc.p(anchorx, anchory));
                return frame;
            }
        },{
            name: "AnchorPoint",
            handle: function(options){
                var frame = new ccs.AnchorPointFrame();
                var anchorx = options["X"];
                var anchory = options["Y"];
                frame.setAnchorPoint(cc.p(anchorx, anchory));
                return frame;
            }
        },{
            name: "InnerAction",
            handle: function(options){
                var frame = new ccs.InnerActionFrame();
                var type = options["InnerActionType"];
                var startFrame = options["StartFrame"];
                frame.setInnerActionType(type);
                frame.setStartFrameIndex(startFrame);
                return frame;
            }
        },
        {
            name: "CColor",
            handle: function(options){
                var frame = new ccs.ColorFrame();
                var color = options["Color"];
                if(!color) color = {};
                color["R"] = color["R"] === undefined ? 255 : color["R"];
                color["G"] = color["G"] === undefined ? 255 : color["G"];
                color["B"] = color["B"] === undefined ? 255 : color["B"];
                frame.setColor(cc.color(color["R"], color["G"], color["B"]));
                return frame;
            }
        },
        {
            name: "Alpha",
            handle: function(options){
                var frame = new ccs.AlphaFrame();
                var alpha = options["Value"];
                frame.setAlpha(alpha);
                return frame;
            }
        },
        {
            name: "FileData",
            handle: function(options, resourcePath){
                var frame, texture, plist, path, spriteFrame;
                frame = new ccs.TextureFrame();
                texture = options["TextureFile"];
                if(texture != null) {
                    plist = texture["Plist"];
                    path = texture["Path"];
                    spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
                    if(!spriteFrame && plist){
                        if(cc.loader.getRes(resourcePath + plist)){
                            cc.spriteFrameCache.addSpriteFrames(resourcePath + plist);
                            spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
                        }else{
                            cc.log("%s need to be preloaded", resourcePath + plist);
                        }
                    }
                    if(spriteFrame == null){
                        path = resourcePath + path;
                    }
                    frame.setTextureName(path);
                }
                return frame;
            }
        },
        {
            name: "FrameEvent",
            handle: function(options){
                var frame = new ccs.EventFrame();
                var evnt = options["Value"];
                if(evnt != null)
                    frame.setEvent(evnt);
                return frame;
            }
        },
        {
            name: "ZOrder",
            handle: function(options){
                var frame = new ccs.ZOrderFrame();
                var zorder = options["Value"];
                frame.setZOrder(zorder);
                return frame;
            }
        },
        {
            name: "ActionValue",
            handle: function (options) {
                var frame = new ccs.InnerActionFrame();
                var innerActionType = options["InnerActionType"];
                var currentAnimationFrame = options["CurrentAniamtionName"];
                var singleFrameIndex = options["SingleFrameIndex"];
                var frameIndex = options["FrameIndex"];
                if(frameIndex !== undefined)
                    frame.setFrameIndex(frameIndex);
                frame.setInnerActionType(ccs.InnerActionType[innerActionType]);
                frame.setSingleFrameIndex(singleFrameIndex);
                frame.setEnterWithName(true);
                if (currentAnimationFrame)
                     frame.setAnimationName(currentAnimationFrame);
                return frame;
            }
        },
        {
            name: "BlendFunc",
            handle: function(options){
                var frame = new ccs.BlendFuncFrame();
                var blendFunc = options["BlendFunc"];
                if(blendFunc && blendFunc["Src"] !== undefined && blendFunc["Dst"] !== undefined)
                    frame.setBlendFunc(new cc.BlendFunc(blendFunc["Src"], blendFunc["Dst"]));
                return frame;
            }
        }
    ];
    var loadEasingDataWithFlatBuffers = function(frame, options){
        var type = options["Type"];
        frame.setTweenType(type);
        var points = options["Points"];
        var result = [];
        if(points){
            points.forEach(function(p){
                result.push(p["X"]);
                result.push(p["Y"]);
            });
            frame.setEasingParams(result);
        }
    };
    frameList.forEach(function(item){
        parser.registerParser(item.name, function(options, resourcePath){
            var timeline = new ccs.Timeline();
            timeline.setActionTag(options["ActionTag"]);
            var frames = options["Frames"];
            if(frames && frames.length){
                frames.forEach(function(frameData){
                    var frame = item.handle(frameData, resourcePath);
                    frame.setFrameIndex(frameData["FrameIndex"]);
                    var tween = frameData["Tween"] != null ? frameData["Tween"] : true;
                    frame.setTween(tween);
                    var easingData = frameData["EasingData"];
                    if(easingData)
                        loadEasingDataWithFlatBuffers(frame, easingData);
                    timeline.addFrame(frame);
                });
            }
            return timeline;
        });
    });
    load.registerParser("action", "2.*", parser);
    load.registerParser("action", "*", parser);
})(ccs._load, ccs._parser);
(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);
(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));
                            }
                            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"];
        var path = options["resourcePath"];
        var tmx = null;
        if (tmxFile && "" !== tmxFile){
            tmx = new cc.TMXTiledMap(tmxFile);
        }else if (tmxString && "" !== tmxString && path && "" !== path){
            tmx = new cc.TMXTiledMap(tmxString, path);
        }
        return tmx;
    };
    var uiParser = load.getParser("ccui")["*"];
    parser.initWidget = function(options, resourcePath){
        var type = options["classname"];
        var parser = uiParser.parsers[type];
        if(!parser)
            return cc.log("%s parser is not found", type);
        var node = parser.call(uiParser, options, resourcePath);
        if(node){
            var rotationSkewX = options["rotationSkewX"];
            var rotationSkewY = options["rotationSkewY"];
            var skewx         = options["skewX"];
            var skewy         = options["skewY"];
            if(rotationSkewX != 0)
                node.setRotationX(rotationSkewX);
            if(rotationSkewY != 0)
                node.setRotationY(rotationSkewY);
            if(skewx != 0)
                node.setSkewX(skewx);
            if(skewy != 0)
                node.setSkewY(skewy);
            var actionTag = options["actionTag"];
            node.setUserObject(new ccs.ActionTimelineData(actionTag));
        }
        return node;
    };
    var register = [
        {name: "Node", handle: parser.initNode},
        {name: "SubGraph", handle: parser.initSubGraph},
        {name: "Sprite", handle: parser.initSprite},
        {name: "Particle", handle: parser.initParticle},
        {name: "TMXTiledMap", handle: parser.initTMXTiledMap},
        {name: "Widget", handle: parser.initWidget},
        {name: "Panel", handle: parser.initWidget},
        {name: "Button", handle: parser.initWidget},
        {name: "CheckBox", handle: parser.initWidget},
        {name: "ImageView", handle: parser.initWidget},
        {name: "LabelAtlas", handle: parser.initWidget},
        {name: "LabelBMFont", handle: parser.initWidget},
        {name: "Label", handle: parser.initWidget},
        {name: "ListView", handle: parser.initWidget},
        {name: "LoadingBar", handle: parser.initWidget},
        {name: "PageView", handle: parser.initWidget},
        {name: "ScrollView", handle: parser.initWidget},
        {name: "Slider", handle: parser.initWidget},
        {name: "TextField", handle: parser.initWidget}
    ];
    register.forEach(function(item){
        parser.registerParser(item.name, function(options, parse, resourcePath){
            var node = item.handle.call(this, options["options"]);
            this.parseComponent(node, options["components"]);
            this.parseChild(parse, node, options, resourcePath);
            return node;
        });
    });
    load.registerParser("timeline", "0.*", parser);
    load.registerParser("timeline", "1.*", parser);
})(ccs._load, ccs._parser);
(function(load, baseParser){
    var DEBUG = false;
    var Parser = baseParser.extend({
        parse: function(file, json, path){
            var resourcePath;
            if(path !== undefined)
                resourcePath = path;
            else
                resourcePath = this._dirname(file);
            this.pretreatment(json, resourcePath, file);
            var node = this.parseNode(this.getNodeJson(json), resourcePath);
            this.deferred(json, resourcePath, node, file);
            return node;
        },
        getNodeJson: function(json){
            var content = json["Content"];
            if(content["ObjectData"])
                return content["ObjectData"];
            return content["Content"]["ObjectData"];
        },
        getClass: function(json){
            return json["ctype"];
        }
    });
    var parser = new Parser();
    var getParam = function(value, dValue){
        if(value === undefined)
            return dValue;
        else
            return value;
    };
    parser.generalAttributes = function(node, json){
        if(json["Name"] != null)
            node.setName(json["Name"]);
        var position = json["Position"];
        if(position != null && (position["X"] != null || position["Y"] != null))
            node.setPosition(cc.p(position["X"]||0, position["Y"]||0));
        var scale = json["Scale"];
        if(scale != null){
            if(scale["ScaleX"] != null)
                node.setScaleX(scale["ScaleX"]);
            if(scale["ScaleY"] != null)
                node.setScaleY(scale["ScaleY"]);
        }
        var rotationSkewX = json["RotationSkewX"];
        if (rotationSkewX != null)
            node.setRotationX(rotationSkewX);
        var rotationSkewY = json["RotationSkewY"];
        if (json["RotationSkewY"] != null)
            node.setRotationY(rotationSkewY);
        var anchor = json["AnchorPoint"];
        if(anchor != null){
            if(anchor["ScaleX"] == null)
                anchor["ScaleX"] = 0;
            if(anchor["ScaleY"] == null)
                anchor["ScaleY"] = 0;
            if(anchor["ScaleX"] != 0.5 || anchor["ScaleY"] != 0.5)
                node.setAnchorPoint(cc.p(anchor["ScaleX"], anchor["ScaleY"]));
        }
        if (json["ZOrder"] != null)
            node.setLocalZOrder(json["ZOrder"]);
        var visible = getParam(json["VisibleForFrame"], true);
        node.setVisible(visible);
        var size = json["Size"];
        if(size)
            setContentSize(node, size);
        if (json["Alpha"] != null)
            node.setOpacity(json["Alpha"]);
        node.setTag(json["Tag"] || 0);
        var actionTag = json["ActionTag"] || 0;
        var extensionData = new ccs.ComExtensionData();
        var customProperty = json["UserData"];
        if(customProperty !== undefined)
            extensionData.setCustomProperty(customProperty);
        extensionData.setActionTag(actionTag);
        if (node.getComponent("ComExtensionData"))
            node.removeComponent("ComExtensionData");
        node.addComponent(extensionData);
        node.setCascadeColorEnabled(true);
        node.setCascadeOpacityEnabled(true);
        setLayoutComponent(node, json);
    };
    parser.parseChild = function(node, children, resourcePath){
        if(!node || !children) return;
        for (var i = 0; i < children.length; i++) {
            var child = this.parseNode(children[i], resourcePath);
            if(child){
                if(node instanceof ccui.PageView){
                    if(child instanceof ccui.Layout)
                        node.addPage(child);
                } else {
                    if(node instanceof ccui.ListView){
                        if(child instanceof ccui.Widget)
                            node.pushBackCustomItem(child);
                    } else {
                        if(!(node instanceof ccui.Layout) && child instanceof ccui.Widget) {
                            if(child.getPositionType() === ccui.Widget.POSITION_PERCENT) {
                                var position = child.getPositionPercent();
                                var anchor = node.getAnchorPoint();
                                child.setPositionPercent(cc.p(position.x + anchor.x, position.y + anchor.y));
                            }
                        }
                        node.addChild(child);
                    }
                }
            }
        }
    };
    parser.initSingleNode = function(json){
        var node = new cc.Node();
        this.generalAttributes(node, json);
        var color = json["CColor"];
        if(color != null)
            node.setColor(getColor(color));
        return node;
    };
    parser.initSprite = function(json, resourcePath){
        var node =  new cc.Sprite();
        loadTexture(json["FileData"], resourcePath, function(path, type){
            if(type === 0)
                node.setTexture(path);
            else if(type === 1){
                var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
                if(spriteFrame)
                    node.setSpriteFrame(spriteFrame);
            }
        });
        var blendData = json["BlendFunc"];
        if(json["BlendFunc"]) {
            var blendFunc = cc.BlendFunc.ALPHA_PREMULTIPLIED;
            if (blendData["Src"] !== undefined)
                blendFunc.src = blendData["Src"];
            if (blendData["Dst"] !== undefined)
                blendFunc.dst = blendData["Dst"];
            node.setBlendFunc(blendFunc);
        }
        if(json["FlipX"])
            node.setFlippedX(true);
        if(json["FlipY"])
            node.setFlippedY(true);
        this.generalAttributes(node, json);
        var color = json["CColor"];
        if(color != null)
            node.setColor(getColor(color));
        return node;
    };
    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;
    };
    parser.widgetAttributes = function (widget, json, enableContent) {
        widget.setCascadeColorEnabled(true);
        widget.setCascadeOpacityEnabled(true);
        widget.setUnifySizeEnabled(false);
        widget.ignoreContentAdaptWithSize(false);
        !enableContent && setContentSize(widget, json["Size"]);
        var name = json["Name"];
        if (name)
            widget.setName(name);
        var actionTag = json["ActionTag"] || 0;
        widget.setActionTag(actionTag);
        var extensionData = new ccs.ComExtensionData();
        var customProperty = json["UserData"];
        if(customProperty !== undefined)
            extensionData.setCustomProperty(customProperty);
        extensionData.setActionTag(actionTag);
        if (widget.getComponent("ComExtensionData"))
            widget.removeComponent("ComExtensionData");
        widget.addComponent(extensionData);
        var rotationSkewX = json["RotationSkewX"];
        if (rotationSkewX)
            widget.setRotationX(rotationSkewX);
        var rotationSkewY = json["RotationSkewY"];
        if (rotationSkewY)
            widget.setRotationY(rotationSkewY);
        var 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 = 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 callBackType = json["CallBackType"];
        if (callBackType != null)
            widget.setCallbackType(callBackType);
        var callBackName = json["CallBackName"];
        if (callBackName)
            widget.setCallbackName(callBackName);
        var position = json["Position"];
        if (position != null)
            widget.setPosition(position["X"] || 0, position["Y"] || 0);
        var scale = json["Scale"];
        if (scale != null) {
            var scaleX = getParam(scale["ScaleX"], 1);
            var scaleY = getParam(scale["ScaleY"], 1);
            widget.setScaleX(scaleX);
            widget.setScaleY(scaleY);
        }
        var anchorPoint = json["AnchorPoint"];
        if (anchorPoint != null)
            widget.setAnchorPoint(anchorPoint["ScaleX"] || 0, anchorPoint["ScaleY"] || 0);
        var color = json["CColor"];
        if (color != null)
            widget.setColor(getColor(color));
        setLayoutComponent(widget, json);
        bindCallback(widget, json);
    };
    var bindCallback = function(widget, json){
        var callBackType = json["CallBackType"];
        var callBackName = json["CallBackName"];
        var callBack = function(e){
            if(typeof widget[callBackName] === "function")
                widget[callBackName](e);
        };
        if(callBackType === "Click"){
            widget.addClickEventListener(callBack);
        }else if(callBackType === "Touch"){
            widget.addTouchEventListener(callBack);
        }else if(callBackType === "Event"){
            widget.addCCSEventListener(callBack);
        }
    };
    var setLayoutComponent = function(widget, json){
        var layoutComponent = ccui.LayoutComponent.bindLayoutComponent(widget);
        if(!layoutComponent)
            return;
        var positionXPercentEnabled = json["PositionPercentXEnable"] || json["PositionPercentXEnabled"] || false;
        var positionYPercentEnabled = json["PositionPercentYEnable"] || json["PositionPercentYEnabled"] || false;
        var positionXPercent = 0,
            positionYPercent = 0,
            PrePosition = json["PrePosition"];
        if (PrePosition != null) {
            positionXPercent = PrePosition["X"] || 0;
            positionYPercent = PrePosition["Y"] || 0;
        }
        var sizeXPercentEnable = json["PercentWidthEnable"] || json["PercentWidthEnabled"]  || false;
        var sizeYPercentEnable = json["PercentHeightEnable"]|| json["PercentHeightEnabled"]  || false;
        var sizeXPercent = 0,
            sizeYPercent = 0,
            PreSize = json["PreSize"];
        if (PrePosition != null) {
            sizeXPercent = PreSize["X"] || 0;
            sizeYPercent = PreSize["Y"] || 0;
        }
        var stretchHorizontalEnabled = json["StretchWidthEnable"] || false;
        var stretchVerticalEnabled = json["StretchHeightEnable"] || false;
        var horizontalEdge = json["HorizontalEdge"];// = ccui.LayoutComponent.horizontalEdge.LEFT;
        var verticalEdge = json["VerticalEdge"];
        var leftMargin = json["LeftMargin"] || 0;
        var rightMargin = json["RightMargin"] || 0;
        var topMargin = json["TopMargin"] || 0;
        var bottomMargin = json["BottomMargin"] || 0;
        layoutComponent.setPositionPercentXEnabled(positionXPercentEnabled);
        layoutComponent.setPositionPercentYEnabled(positionYPercentEnabled);
        layoutComponent.setPositionPercentX(positionXPercent);
        layoutComponent.setPositionPercentY(positionYPercent);
        layoutComponent.setPercentWidthEnabled(sizeXPercentEnable);
        layoutComponent.setPercentHeightEnabled(sizeYPercentEnable);
        layoutComponent.setPercentWidth(sizeXPercent);
        layoutComponent.setPercentHeight(sizeYPercent);
        layoutComponent.setPercentWidthEnabled(sizeXPercentEnable || sizeYPercentEnable);
        layoutComponent.setStretchWidthEnabled(stretchHorizontalEnabled);
        layoutComponent.setStretchHeightEnabled(stretchVerticalEnabled);
        var horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.NONE;
        if (horizontalEdge === "LeftEdge") {
            horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.LEFT;
        } else if (horizontalEdge === "RightEdge") {
            horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.RIGHT;
        } else if (horizontalEdge === "BothEdge") {
            horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.CENTER;
        }
        layoutComponent.setHorizontalEdge(horizontalEdgeType);
        var verticalEdgeType = ccui.LayoutComponent.verticalEdge.NONE;
        if (verticalEdge === "TopEdge") {
            verticalEdgeType = ccui.LayoutComponent.verticalEdge.TOP;
        } else if (verticalEdge === "BottomEdge") {
            verticalEdgeType = ccui.LayoutComponent.verticalEdge.BOTTOM;
        } else if (verticalEdge === "BothEdge") {
            verticalEdgeType = ccui.LayoutComponent.verticalEdge.CENTER;
        }
        layoutComponent.setVerticalEdge(verticalEdgeType);
        layoutComponent.setTopMargin(topMargin);
        layoutComponent.setBottomMargin(bottomMargin);
        layoutComponent.setLeftMargin(leftMargin);
        layoutComponent.setRightMargin(rightMargin);
        layoutComponent.setVerticalEdge(verticalEdgeType);
        layoutComponent.setTopMargin(topMargin);
        layoutComponent.setBottomMargin(bottomMargin);
        layoutComponent.setLeftMargin(leftMargin);
        layoutComponent.setRightMargin(rightMargin);
    };
    var setLayoutBackground = function(layout, single, first, end){
        if( layout.getBackGroundColorType() === 2 ){
            first = first || {};
            end = end || {};
            layout.setBackGroundColor(getColor(first), getColor(end));
        }else{
            single = single || {};
            layout.setBackGroundColor(getColor(single));
        }
    };
    var setLayoutBackgroundVector = function(widget, vector){
        var x = vector["ScaleX"] || 0;
        var y = vector["ScaleY"] || 0;
        widget.setBackGroundColorVector(cc.p(x, y));
    };
    parser.initPanel = function(json, resourcePath){
        var widget = new ccui.Layout();
        this.widgetAttributes(widget, json);
        var clipEnabled = json["ClipAble"] || false;
        if(clipEnabled != null)
            widget.setClippingEnabled(clipEnabled);
        var colorType = getParam(json["ComboBoxIndex"], 0);
        widget.setBackGroundColorType(colorType);
        var bgColorOpacity = getParam(json["BackColorAlpha"], 255);
        if(bgColorOpacity != null)
            widget.setBackGroundColorOpacity(bgColorOpacity);
        var backGroundScale9Enabled = json["Scale9Enable"];
        if(backGroundScale9Enabled != null)
            widget.setBackGroundImageScale9Enabled(backGroundScale9Enabled);
        var opacity = getParam(json["Alpha"], 255);
        widget.setOpacity(opacity);
        loadTexture(json["FileData"], resourcePath, function(path, type){
            widget.setBackGroundImage(path, type);
        });
        if(backGroundScale9Enabled){
            var scale9OriginX = json["Scale9OriginX"] || 0;
            var scale9OriginY = json["Scale9OriginY"] || 0;
            var scale9Width = json["Scale9Width"] || 0;
            var scale9Height = json["Scale9Height"] || 0;
            widget.setBackGroundImageCapInsets(cc.rect(
                scale9OriginX, scale9OriginY, scale9Width, scale9Height
            ));
            setContentSize(widget, json["Size"]);
        }else{
            if (!widget.isIgnoreContentAdaptWithSize()){
                setContentSize(widget, json["Size"]);
            }
        }
        setLayoutBackground(widget, json["SingleColor"], json["FirstColor"], json["EndColor"]);
        setLayoutBackgroundVector(widget, json["ColorVector"]);
        return widget;
    };
    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"];
            if(path != null){
                if (cc.sys.isNative) {
                    fontName = cc.path.join(cc.loader.resPath, resourcePath, path);
                } else {
                    fontName = path.match(/([^\/]+)\.(\S+)/);
                    fontName = fontName ? fontName[1] : "";
                }
                widget.setFontName(fontName);
            }
        }
        if(json["OutlineEnabled"] && json["OutlineColor"] && widget.enableOutline)
            widget.enableOutline(getColor(json["OutlineColor"]), getParam(json["OutlineSize"], 1));
        if(json["ShadowEnabled"] && json["ShadowColor"] && widget.enableShadow)
            widget.enableShadow(
                getColor(json["ShadowColor"]),
                cc.size(getParam(json["ShadowOffsetX"], 2), getParam(json["ShadowOffsetY"], -2)),
                json["ShadowBlurRadius"] || 0
            );
        var isCustomSize = json["IsCustomSize"];
        if(isCustomSize != null)
            widget.ignoreContentAdaptWithSize(!isCustomSize);
        widget.setUnifySizeEnabled(false);
        var color = json["CColor"];
        json["CColor"] = null;
        widget.setTextColor(getColor(color));
        this.widgetAttributes(widget, json, widget.isIgnoreContentAdaptWithSize());
        json["CColor"] = color;
        return widget;
    };
    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"];
            if(path != null){
                if (cc.sys.isNative) {
                    fontName = cc.path.join(cc.loader.resPath, resourcePath, path);
                } else {
                    fontName = path.match(/([^\/]+)\.(\S+)/);
                    fontName = fontName ? fontName[1] : "";
                }
                widget.setTitleFontName(fontName);
            }
        }
        var label = widget.getTitleRenderer();
        if(label && json["ShadowEnabled"] && json["ShadowColor"] && label.enableShadow){
            label.enableShadow(
                getColor(json["ShadowColor"]),
                cc.size(getParam(json["ShadowOffsetX"], 2), getParam(json["ShadowOffsetY"], -2)),
                json["ShadowBlurRadius"] || 0
            );
        }
        if(label && json["OutlineEnabled"] && json["OutlineColor"] && label.enableStroke)
            label.enableStroke(getColor(json["OutlineColor"]), getParam(json["OutlineSize"], 1));
        this.widgetAttributes(widget, json);
        if(scale9Enabled) {
            widget.setUnifySizeEnabled(false);
            widget.ignoreContentAdaptWithSize(false);
            var capInsets = cc.rect(
                    json["Scale9OriginX"] || 0,
                    json["Scale9OriginY"] || 0,
                    json["Scale9Width"] || 0,
                    json["Scale9Height"] || 0
            );
            widget.setCapInsets(capInsets);
        }
        setContentSize(widget, json["Size"]);
        return widget;
    };
    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;
    };
    parser.initScrollView = function(json, resourcePath){
        var widget = new ccui.ScrollView();
        this.widgetAttributes(widget, json);
        loadTexture(json["FileData"], resourcePath, function(path, type){
            widget.setBackGroundImage(path, type);
        });
        var clipEnabled = json["ClipAble"] || false;
        widget.setClippingEnabled(clipEnabled);
        var colorType = getParam(json["ComboBoxIndex"], 0);
        widget.setBackGroundColorType(colorType);
        var bgColorOpacity = json["BackColorAlpha"];
        if(bgColorOpacity != null)
            widget.setBackGroundColorOpacity(bgColorOpacity);
        var backGroundScale9Enabled = json["Scale9Enable"];
        if(backGroundScale9Enabled){
            widget.setBackGroundImageScale9Enabled(true);
            var scale9OriginX = json["Scale9OriginX"] || 0;
            var scale9OriginY = json["Scale9OriginY"] || 0;
            var scale9Width = json["Scale9Width"] || 0;
            var scale9Height = json["Scale9Height"] || 0;
            widget.setBackGroundImageCapInsets(cc.rect(
                scale9OriginX, scale9OriginY, scale9Width, scale9Height
            ));
            setContentSize(widget, json["Size"]);
        }else if(!widget.isIgnoreContentAdaptWithSize()){
            setContentSize(widget, json["Size"]);
        }
        setLayoutBackground(widget, json["SingleColor"], json["FirstColor"], json["EndColor"]);
        setLayoutBackgroundVector(widget, json["ColorVector"]);
        var innerNodeSize = json["InnerNodeSize"];
        var innerSize = cc.size(
            innerNodeSize["Width"] || 0,
            innerNodeSize["Height"] || 0
        );
        widget.setInnerContainerSize(innerSize);
        var direction = 0;
        if(json["ScrollDirectionType"] === "Vertical") direction = 1;
        if(json["ScrollDirectionType"] === "Horizontal") direction = 2;
        if(json["ScrollDirectionType"] === "Vertical_Horizontal") direction = 3;
        widget.setDirection(direction);
        var bounceEnabled = getParam(json["IsBounceEnabled"], false);
        widget.setBounceEnabled(bounceEnabled);
        return widget;
    };
    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;
    };
    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;
    };
    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;
    };
    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;
    };
    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"];
        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;
    };
    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);
        widget.ignoreContentAdaptWithSize(true);
        return widget;
    };
    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;
    };
    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);
        }
        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"];
            if(path != null){
                if (cc.sys.isNative) {
                    fontName = cc.path.join(cc.loader.resPath, resourcePath, path);
                } else {
                    fontName = path.match(/([^\/]+)\.(\S+)/);
                    fontName = fontName ? fontName[1] : "";
                }
                widget.setFontName(fontName);
            }
        }
        widget.setUnifySizeEnabled(false);
        widget.ignoreContentAdaptWithSize(false);
        var color = json["CColor"];
        if(color != null)
            widget.setTextColor(getColor(color));
        if (!widget.isIgnoreContentAdaptWithSize()){
            setContentSize(widget, json["Size"]);
            if (cc.sys.isNative)
                widget.getVirtualRenderer().setLineBreakWithoutSpace(true);
        }
        return widget;
    };
    parser.initSimpleAudio = function(json, resourcePath){
        var node = new ccs.ComAudio();
        var loop = json["Loop"] || false;
        node.setLoop(loop);
        loadTexture(json["FileData"], resourcePath, function(path, type){
            node.setFile(path);
        });
    };
    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;
    };
    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 "";
    };
    parser.initArmature = function(json, resourcePath){
        var node = new ccs.Armature();
        var isLoop = json["IsLoop"];
        var isAutoPlay = json["IsAutoPlay"];
        var currentAnimationName = json["CurrentAnimationName"];
        loadTexture(json["FileData"], resourcePath, function(path, type){
            var plists, pngs;
            var armJson = cc.loader.getRes(path);
            if(!armJson)
                cc.log("%s need to be preloaded", path);
            else{
                plists = armJson["config_file_path"];
                pngs = armJson["config_png_path"];
                plists.forEach(function(plist, index){
                    if(pngs[index])
                        cc.spriteFrameCache.addSpriteFrames(plist, pngs[index]);
                });
            }
            ccs.armatureDataManager.addArmatureFileInfo(path);
            node.init(getFileName(path));
            if(isAutoPlay)
                node.getAnimation().play(currentAnimationName, -1, isLoop);
            else{
                node.getAnimation().play(currentAnimationName);
                node.getAnimation().gotoAndPause(0);
            }
        });
        delete json["AnchorPoint"];
        delete json["Size"];
        parser.generalAttributes(node, json);
        node.setColor(getColor(json["CColor"]));
        return node;
    };
    parser.initBoneNode = function(json, resourcePath){
        var node = new ccs.BoneNode();
        var length = json["Length"];
        if(length !== undefined)
            node.setDebugDrawLength(length);
        var blendFunc = json["BlendFunc"];
        if(blendFunc && blendFunc["Src"] !== undefined && blendFunc["Dst"] !== undefined)
            node.setBlendFunc(new cc.BlendFunc(blendFunc["Src"], blendFunc["Dst"]));
        parser.generalAttributes(node, json);
        var color = json["CColor"];
        if(color && (color["R"] !== undefined || color["G"] !== undefined || color["B"] !== undefined))
            node.setColor(getColor(color));
        return node;
    };
    parser.initSkeletonNode = function(json){
        var node = new ccs.SkeletonNode();
        parser.generalAttributes(node, json);
        var color = json["CColor"];
        if(color && (color["R"] !== undefined || color["G"] !== undefined || color["B"] !== undefined))
            node.setColor(getColor(color));
        return node;
    };
    var loadedPlist = {};
    var loadTexture = function(json, resourcePath, cb){
        if(json != null){
            var path = json["Path"];
            var type;
            if(json["Type"] === "Default" || json["Type"] === "Normal")
                type = 0;
            else
                type = 1;
            var plist = json["Plist"];
            if(plist){
                if(cc.loader.getRes(resourcePath + plist)){
                    loadedPlist[resourcePath + plist] = true;
                    cc.spriteFrameCache.addSpriteFrames(resourcePath + plist);
                }else{
                    if(!loadedPlist[resourcePath + plist] && !cc.spriteFrameCache.getSpriteFrame(path))
                        cc.log("%s need to be preloaded", resourcePath + plist);
                }
            }
            if(type !== 0){
                if(cc.spriteFrameCache.getSpriteFrame(path))
                    cb(path, type);
                else
                    cc.log("failed to get spriteFrame: %s", path);
            }else
                cb(resourcePath + path, type);
        }
    };
    var getColor = function(json){
        if(!json) return;
        var r = json["R"] != null ? json["R"] : 255;
        var g = json["G"] != null ? json["G"] : 255;
        var b = json["B"] != null ? json["B"] : 255;
        var a = json["A"] != null ? json["A"] : 255;
        return cc.color(r, g, b, a);
    };
    var setContentSize = function(node, size){
        var x = size["X"] || 0;
        var y = size["Y"] || 0;
        if(size)
            node.setContentSize(cc.size(x, y));
    };
    var register = [
        {name: "SingleNodeObjectData", handle: parser.initSingleNode},
        {name: "NodeObjectData", handle: parser.initSingleNode},
        {name: "LayerObjectData", handle: parser.initSingleNode},
        {name: "GameNodeObjectData", handle: parser.initSingleNode},
        {name: "GameLayerObjectData", handle: parser.initSingleNode},
        {name: "SpriteObjectData", handle: parser.initSprite},
        {name: "ParticleObjectData", handle: parser.initParticle},
        {name: "PanelObjectData", handle: parser.initPanel},
        {name: "TextObjectData", handle: parser.initText},
        {name: "ButtonObjectData", handle: parser.initButton},
        {name: "CheckBoxObjectData", handle: parser.initCheckBox},
        {name: "ScrollViewObjectData", handle: parser.initScrollView},
        {name: "ImageViewObjectData", handle: parser.initImageView},
        {name: "LoadingBarObjectData", handle: parser.initLoadingBar},
        {name: "SliderObjectData", handle: parser.initSlider},
        {name: "PageViewObjectData", handle: parser.initPageView},
        {name: "ListViewObjectData", handle: parser.initListView},
        {name: "TextAtlasObjectData", handle: parser.initTextAtlas},
        {name: "TextBMFontObjectData", handle: parser.initTextBMFont},
        {name: "TextFieldObjectData", handle: parser.initTextField},
        {name: "SimpleAudioObjectData", handle: parser.initSimpleAudio},
        {name: "GameMapObjectData", handle: parser.initGameMap},
        {name: "ProjectNodeObjectData", handle: parser.initProjectNode},
        {name: "ArmatureNodeObjectData", handle: parser.initArmature},
        {name: "BoneNodeObjectData", handle: parser.initBoneNode},
        {name: "SkeletonNodeObjectData", handle: parser.initSkeletonNode}
    ];
    register.forEach(function(item){
        parser.registerParser(item.name, function(options, resourcePath){
            var node = item.handle.call(this, options, resourcePath);
            this.parseChild(node, options["Children"], resourcePath);
            DEBUG && node && (node.__parserName = item.name);
            return node;
        });
    });
    load.registerParser("timeline", "2.*", parser);
    load.registerParser("timeline", "*", parser);
})(ccs._load, ccs._parser);
(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"]));
        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);
        }
    };
    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);
        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"]);
        }
    };
    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"]);
    };
    parser.CheckBoxAttributes = function(widget, options, resourcePath){
        var backGroundDic = options["backGroundBoxData"];
        getPath(resourcePath, backGroundDic["resourceType"], backGroundDic["path"], function(path, type){
            widget.loadTextureBackGround(path, type);
        });
        var backGroundSelectedDic = options["backGroundBoxSelectedData"];
        getPath(
            resourcePath,
            backGroundSelectedDic["resourceType"] || backGroundDic["resourceType"],
            backGroundSelectedDic["path"] || backGroundDic["path"],
            function(path, type){
            widget.loadTextureBackGroundSelected(path, type);
        });
        var frontCrossDic = options["frontCrossData"];
        getPath(resourcePath, frontCrossDic["resourceType"], frontCrossDic["path"], function(path, type){
            widget.loadTextureFrontCross(path, type);
        });
        var backGroundDisabledDic = options["backGroundBoxDisabledData"];
        getPath(
            resourcePath,
            backGroundDisabledDic["resourceType"] || frontCrossDic["resourceType"],
            backGroundDisabledDic["path"] || frontCrossDic["path"],
            function(path, type){
            widget.loadTextureBackGroundDisabled(path, type);
        });
        var frontCrossDisabledDic = options["frontCrossDisabledData"];
        getPath(resourcePath, frontCrossDisabledDic["resourceType"], frontCrossDisabledDic["path"], function(path, type){
            widget.loadTextureFrontCrossDisabled(path, type);
        });
        if (options["selectedState"])
            widget.setSelected(options["selectedState"]);
    };
    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));
        }
    };
    parser.TextAtlasAttributes = function(widget, options, resourcePath){
        var sv = options["stringValue"];
        var cmf = options["charMapFileData"];
        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;
            }
        }
    };
    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);
    };
    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"]);
        }
    };
    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);
    };
    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"]);
    };
    parser.PageViewAttributes = parser.LayoutAttributes;
    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"]);
    };
    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);
        });
    };
    parser.TextFieldAttributes = function(widget, options, resourcePath){
        var ph = options["placeHolder"];
        if(ph)
            widget.setPlaceHolder(ph);
        widget.setString(options["text"]||"");
        var fs = options["fontSize"];
        if(fs)
            widget.setFontSize(fs);
        var fn = options["fontName"];
        if (fn != null){
            if(cc.sys.isNative){
                if(regTTF.test(fn)){
                    widget.setFontName(cc.path.join(cc.loader.resPath, resourcePath, fn));
                }else{
                    widget.setFontName(fn);
                }
            }else{
                widget.setFontName(fn.replace(regTTF, ''));
            }
        }
        var tsw = options["touchSizeWidth"];
        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){
        }
        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 r = options["colorR"];
        var g = options["colorG"];
        var b = options["colorB"];
        if (r !== undefined && g !== undefined && b !== undefined) {
            widget.setTextColor(cc.color(r, g, b));
        }
    };
    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);
(function(){
    ccs.uiReader = {
        _fileDesignSizes: {},
        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");
        },
        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;
            });
        },
        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;
        },
        storeFileDesignSize: function (fileName, size) {
            this._fileDesignSizes[fileName] = size;
        },
        getFileDesignSize: function (fileName) {
            return this._fileDesignSizes[fileName];
        },
        getFilePath: function(){
            return this._filePath;
        },
        setFilePath: function(path){
            this._filePath = path;
        },
        getParseObjectMap: function(){
            return ccs._load.getParser("ccui")["*"]["parsers"];
        },
        getParseCallBackMap: function(){
            return ccs._load.getParser("ccui")["*"]["parsers"];
        },
        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,
        createNodeWithSceneFile: function(file){
            var node = ccs._load(file, "scene");
            this._node = node;
            return node;
        },
        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;
        },
        version: function(){
            return "*";
        },
        setTarget: function(){},
        clear: function(){
            ccs.triggerManager.removeAll();
            cc.audioEngine.end();
        }
    };
})();
(function(){
    ccs.Armature.WebGLRenderCmd = function(renderableObject){
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._parentCmd = null;
        this._realAnchorPointInPoints = new cc.Point(0,0);
    };
    var proto = ccs.Armature.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    cc.inject(ccs.Armature.RenderCmd, proto);
    proto.constructor = ccs.Armature.WebGLRenderCmd;
    proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
        var node = this._node, cmd;
        var parentCmd = this._parentCmd || this;
        var locChildren = node._children;
        var alphaPremultiplied = cc.BlendFunc.ALPHA_PREMULTIPLIED, alphaNonPremultipled = cc.BlendFunc.ALPHA_NON_PREMULTIPLIED;
        for (var i = 0, len = locChildren.length; i < len; i++) {
            var selBone = locChildren[i];
            var boneCmd = selBone._renderCmd;
            if (selBone && selBone.getDisplayRenderNode) {
                var selNode = selBone.getDisplayRenderNode();
                if (null === selNode)
                    continue;
                cmd = selNode._renderCmd;
                switch (selBone.getDisplayRenderNodeType()) {
                    case ccs.DISPLAY_TYPE_SPRITE:
                        if (selNode instanceof ccs.Skin) {
                            selNode.setShaderProgram(this._shaderProgram);
                            this._updateColorAndOpacity(cmd, selBone);
                            cmd.transform(parentCmd);
                            var func = selBone.getBlendFunc();
                            if (func.src !== alphaPremultiplied.src || func.dst !== alphaPremultiplied.dst)
                                selNode.setBlendFunc(selBone.getBlendFunc());
                            else {
                                var tex = selNode.getTexture();
                                if (node._blendFunc.src === alphaPremultiplied.src &&
                                    node._blendFunc.dst === alphaPremultiplied.dst &&
                                    tex && !tex.hasPremultipliedAlpha()) {
                                    selNode.setBlendFunc(alphaNonPremultipled);
                                }
                                else {
                                    selNode.setBlendFunc(node._blendFunc);
                                }
                            }
                            cc.renderer._uploadBufferData(cmd);
                        }
                        break;
                    case ccs.DISPLAY_TYPE_ARMATURE:
                        selNode.setShaderProgram(this._shaderProgram);
                        cmd._parentCmd = this;
                    default:
                        boneCmd._syncStatus(parentCmd);
                        cmd._syncStatus(boneCmd);
                        if (cmd.uploadData) {
                            cc.renderer._uploadBufferData(cmd);
                        }
                        else if (cmd.rendering) {
                            cc.renderer._batchRendering();
                            cmd.rendering(cc._renderContext);
                        }
                        break;
                }
            } else if (selBone instanceof cc.Node) {
                selBone.setShaderProgram(this._shaderProgram);
                boneCmd._syncStatus(parentCmd);
                if (boneCmd.uploadData) {
                    cc.renderer._uploadBufferData(boneCmd);
                }
                else if (boneCmd.rendering) {
                    cc.renderer._batchRendering();
                    boneCmd.rendering(cc._renderContext);
                }
            }
        }
        this._parentCmd = null;
        return 0;
    };
    proto.initShaderCache = function(){
        this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
    };
    proto.setShaderProgram = function(shaderProgram){
        this._shaderProgram = shaderProgram;
    };
    proto._updateColorAndOpacity = function(skinRenderCmd, bone){
        var parentColor = bone._renderCmd._displayedColor, parentOpacity = bone._renderCmd._displayedOpacity;
        var flags = cc.Node._dirtyFlags, locFlag = skinRenderCmd._dirtyFlag;
        var colorDirty = locFlag & flags.colorDirty,
            opacityDirty = locFlag & flags.opacityDirty;
        if(colorDirty)
            skinRenderCmd._updateDisplayColor(parentColor);
        if(opacityDirty)
            skinRenderCmd._updateDisplayOpacity(parentOpacity);
        if(colorDirty || opacityDirty)
            skinRenderCmd._updateColor();
    };
    proto.visit = function(parentCmd){
        var node = this._node;
        if (!node._visible)
            return;
        parentCmd = parentCmd || this.getParentRenderCmd();
        if (parentCmd)
            this._curLevel = parentCmd._curLevel + 1;
        this._syncStatus(parentCmd);
        node.sortAllChildren();
        var renderer = cc.renderer,
            children = node._children, child,
            i, len = children.length;
        if (isNaN(node._customZ)) {
            node._vertexZ = renderer.assignedZ;
            renderer.assignedZ += renderer.assignedZStep;
        }
        for (i = 0; i < len; i++) {
            child = children[i];
            if (child._localZOrder < 0) {
                if (isNaN(child._customZ)) {
                    child._vertexZ = renderer.assignedZ;
                    renderer.assignedZ += renderer.assignedZStep;
                }
            }
            else {
                break;
            }
        }
        renderer.pushRenderCommand(this);
        for (; i < len; i++) {
            child = children[i];
            if (isNaN(child._customZ)) {
                child._vertexZ = renderer.assignedZ;
                renderer.assignedZ += renderer.assignedZStep;
            }
        }
        this._dirtyFlag = 0;
    };
})();
cc.pool = {
    _pool: {},
    _releaseCB: function () {
        this.release();
    },
    _autoRelease: function (obj) {
        var running = obj._running === undefined ? false : !obj._running;
        cc.director.getScheduler().schedule(this._releaseCB, obj, 0, 0, 0, running)
    },
    putInPool: function (obj) {
        var pid = obj.constructor.prototype['__pid'];
        if (!pid) {
            var desc = { writable: true, enumerable: false, configurable: true };
            desc.value = ClassManager.getNewID();
            Object.defineProperty(obj.constructor.prototype, '__pid', desc);
        }
        if (!this._pool[pid]) {
            this._pool[pid] = [];
        }
        obj.retain && obj.retain();
        obj.unuse && obj.unuse();
        this._pool[pid].push(obj);
    },
    hasObject: function (objClass) {
        var pid = objClass.prototype['__pid'];
        var list = this._pool[pid];
        if (!list || list.length === 0) {
            return false;
        }
        return true;
    },
    removeObject: function (obj) {
        var pid = obj.constructor.prototype['__pid'];
        if (pid) {
            var list = this._pool[pid];
            if (list) {
                for (var i = 0; i < list.length; i++) {
                    if (obj === list[i]) {
                        obj.release && obj.release();
                        list.splice(i, 1);
                    }
                }
            }
        }
    },
    getFromPool: function (objClass) {
        if (this.hasObject(objClass)) {
            var pid = objClass.prototype['__pid'];
            var list = this._pool[pid];
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            var obj = list.pop();
            obj.reuse && obj.reuse.apply(obj, args);
            cc.sys.isNative && obj.release && this._autoRelease(obj);
            return obj;
        }
    },
    drainAllPools: function () {
        for (var i in this._pool) {
            for (var j = 0; j < this._pool[i].length; j++) {
                var obj = this._pool[i][j];
                obj.release && obj.release();
            }
        }
        this._pool = {};
    }
};
(function(){
    if(cc === undefined){
        return;
    }
    var PluginManager = function(){};
    PluginManager.prototype = {
        constructor: PluginManager,
        getInstance: function(){
            return this;
        },
        loadPlugin: function(pluginName){
        },
        unloadPlugin: function(pluginName){
        }
    };
    var PluginAssembly = function(){};
    PluginAssembly.prototype = {
        constructor: PluginAssembly,
        setDebugMode: function(debug){},
        startSession: function(appKey){},
        setCaptureUncaughtException: function(Capture){},
        callFuncWithParam: function(funName){
            if(typeof this[funName] === 'function'){
                return this[funName].apply(this, Array.prototype.splice.call(arguments, 1));
            }else{
                cc.log("function is not define");
            }
        },
        callStringFuncWithParam: function(funName){
            this.callFuncWithParam.apply(arguments);
        },
        getPluginName: function(){
            return this._name;
        },
        getPluginVersion: function(){
            return this._version;
        }
    };
    PluginAssembly.extend = function(name, porp){
        var p, prototype = {};
        for(p in PluginAssembly.prototype){
            prototype[p] = PluginAssembly.prototype[p];
        }
        for(p in porp){
            prototype[p] = porp[p];
        }
        var tmp = eval("(function " + name + "Plugin(){})");
        prototype.constructor = tmp;
        tmp.prototype = prototype;
        return tmp;
    };
    var Param = function(type, value){
        var paramType = plugin.PluginParam.ParamType,tmpValue;
        switch(type){
            case paramType.TypeInt:
                tmpValue = parseInt(value);
                break;
            case paramType.TypeFloat:
                tmpValue = parseFloat(value);
                break;
            case paramType.TypeBool:
                tmpValue = Boolean(value);
                break;
            case paramType.TypeString:
                tmpValue = String(value);
                break;
            case paramType.TypeStringMap:
                tmpValue = value//JSON.stringify(value);
                break;
            default:
                tmpValue = value;
        }
        return tmpValue
    };
    Param.ParamType = {
        TypeInt:1,
        TypeFloat:2,
        TypeBool:3,
        TypeString:4,
        TypeStringMap:5
    };
    Param.AdsResultCode = {
        AdsReceived:0,
        FullScreenViewShown:1,
        FullScreenViewDismissed:2,
        PointsSpendSucceed:3,
        PointsSpendFailed:4,
        NetworkError:5,
        UnknownError:6
    };
    Param.PayResultCode = {
        PaySuccess:0,
        PayFail:1,
        PayCancel:2,
        PayTimeOut:3
    };
    Param.ShareResultCode = {
        ShareSuccess:0,
        ShareFail:1,
        ShareCancel:2,
        ShareTimeOut:3
    };
    var PluginList = {};
    var Plugin = {
        extend: function(name, extend){
            var config = (cc.game.config && cc.game.config.plugin) || {};
            PluginList[name] = new (PluginAssembly.extend(name, extend));
            typeof PluginList[name].ctor === "function" && PluginList[name].ctor(config[name]);
        },
        PluginList: PluginList,
        PluginParam: Param,
        PluginManager: new PluginManager()
    };
    window.plugin = Plugin;
})();
(function () {
    var box2dAPI = {
        _ignoreBodyRotation:false,
        _body:null,
        _PTMRatio:32,
        _rotation:1,
        ctor:function(fileName, rect){
            cc.Sprite.prototype.ctor.call(this);
            if (fileName === undefined) {
                cc.PhysicsSprite.prototype.init.call(this);
            }else if (cc.isString(fileName)) {
                if (fileName[0] === "#") {
                    var frameName = fileName.substr(1, fileName.length - 1);
                    var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
                    this.initWithSpriteFrame(spriteFrame);
                } else {
                    this.init(fileName, rect);
                }
            }else if (cc.isObject(fileName)) {
                if (fileName instanceof cc.Texture2D) {
                    this.initWithTexture(fileName, rect);
                } else if (fileName instanceof cc.SpriteFrame) {
                    this.initWithSpriteFrame(fileName);
                }
            }
        },
        setBody:function (body) {
            this._body = body;
        },
        getBody:function () {
            return this._body;
        },
        setPTMRatio:function (r) {
            this._PTMRatio = r;
        },
        getPTMRatio:function () {
            return this._PTMRatio;
        },
        getPosition:function () {
            var pos = this._body.GetPosition();
            var locPTMRatio =this._PTMRatio;
            return cc.p(pos.x * locPTMRatio, pos.y * locPTMRatio);
        },
        setPosition:function (p) {
            var angle = this._body.GetAngle();
            var locPTMRatio =this._PTMRatio;
            this._body.setTransform(Box2D.b2Vec2(p.x / locPTMRatio, p.y / locPTMRatio), angle);
            this.setNodeDirty();
        },
        getRotation:function () {
            return (this._ignoreBodyRotation ? cc.radiansToDegrees(this._rotationRadians) : cc.radiansToDegrees(this._body.GetAngle()));
        },
        setRotation:function (r) {
            if (this._ignoreBodyRotation) {
                this._rotation = r;
            } else {
                var locBody = this._body;
                var p = locBody.GetPosition();
                locBody.SetTransform(p, cc.degreesToRadians(r));
            }
            this.setNodeDirty();
        },
        _syncPosition:function () {
            var locPosition = this._position,
                pos = this._body.GetPosition(),
                x = pos.x * this._PTMRatio,
                y = pos.y * this._PTMRatio;
            if (locPosition.x !== pos.x || locPosition.y !== pos.y) {
                cc.Sprite.prototype.setPosition.call(this, x, y);
            }
        },
        _syncRotation:function () {
            this._rotationRadians = this._body.GetAngle();
            var a = cc.radiansToDegrees(this._rotationRadians);
            if (this._rotationX !== a) {
                cc.Sprite.prototype.setRotation.call(this, a);
            }
        },
        setIgnoreBodyRotation: function(b) {
            this._ignoreBodyRotation = b;
        }
    };
    var chipmunkAPI = {
        _ignoreBodyRotation:false,
        _body:null,
        _rotation:1,
        ctor:function(fileName, rect){
            cc.Sprite.prototype.ctor.call(this);
            if (fileName === undefined) {
                cc.PhysicsSprite.prototype.init.call(this);
            }else if (cc.isString(fileName)) {
                if (fileName[0] === "#") {
                    var frameName = fileName.substr(1, fileName.length - 1);
                    var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
                    this.initWithSpriteFrame(spriteFrame);
                } else {
                    this.init(fileName, rect);
                }
            }else if (cc.isObject(fileName)) {
                if (fileName instanceof cc.Texture2D) {
                    this.initWithTexture(fileName, rect);
                } else if (fileName instanceof cc.SpriteFrame) {
                    this.initWithSpriteFrame(fileName);
                }
            }
            cc.renderer.pushRenderCommand(this._renderCmd);
        },
        visit: function(){
            cc.renderer.pushRenderCommand(this._renderCmd);
            cc.Sprite.prototype.visit.call(this);
        },
        setBody:function (body) {
            this._body = body;
        },
        getBody:function () {
            return this._body;
        },
        getPosition:function () {
            var locBody = this._body;
            return {x:locBody.p.x, y:locBody.p.y};
        },
        getPositionX:function () {
            return this._body.p.x;
        },
        getPositionY:function () {
            return this._body.p.y;
        },
        setPosition:function (newPosOrxValue, yValue) {
            if (yValue === undefined) {
                this._body.p.x = newPosOrxValue.x;
                this._body.p.y = newPosOrxValue.y;
            } else {
                this._body.p.x = newPosOrxValue;
                this._body.p.y = yValue;
            }
        },
        setPositionX:function (xValue) {
            this._body.p.x = xValue;
        },
        setPositionY:function (yValue) {
            this._body.p.y = yValue;
        },
        _syncPosition:function () {
            var locPosition = this._position, locBody = this._body;
            if (locPosition.x !== locBody.p.x || locPosition.y !== locBody.p.y) {
                cc.Sprite.prototype.setPosition.call(this, locBody.p.x, locBody.p.y);
            }
        },
        getRotation:function () {
            return this._ignoreBodyRotation ? this._rotationX : -cc.radiansToDegrees(this._body.a);
        },
        setRotation:function (r) {
            if (this._ignoreBodyRotation) {
                cc.Sprite.prototype.setRotation.call(this, r);
            } else {
                this._body.a = -cc.degreesToRadians(r);
            }
        },
        _syncRotation:function () {
            var a = -cc.radiansToDegrees(this._body.a);
            if (this._rotationX !== a) {
                cc.Sprite.prototype.setRotation.call(this, a);
            }
        },
        getNodeToParentTransform:function () {
            return this._renderCmd.getNodeToParentTransform();
        },
        isDirty:function(){
           return !this._body.isSleeping();
        },
        setDirty: function(){ },
        setIgnoreBodyRotation: function(b) {
            this._ignoreBodyRotation = b;
        },
        _createRenderCmd: function(){
            if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
                return new cc.PhysicsSprite.CanvasRenderCmd(this);
            else
                return new cc.PhysicsSprite.WebGLRenderCmd(this);
        }
    };
    cc.PhysicsSprite = cc.Sprite.extend(chipmunkAPI);
    cc.PhysicsSprite._className = "PhysicsSprite";
    var _p = cc.PhysicsSprite.prototype;
    _p.body;
    cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
    _p.dirty;
    cc.defineGetterSetter(_p, "dirty", _p.isDirty, _p.setDirty);
    cc.PhysicsSprite.create = function (fileName, rect) {
        return new cc.PhysicsSprite(fileName, rect);
    };
    cc.PhysicsSprite.createWithSpriteFrameName = cc.PhysicsSprite.create;
    cc.PhysicsSprite.createWithSpriteFrame = cc.PhysicsSprite.create;
})();
(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){
        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);
    };
})();
cc.__convertVerts = function (verts) {
    var ret = [];
    for (var i = 0; i < verts.length / 2; i++) {
        ret[i] = {x:verts[i * 2], y:verts[i * 2 + 1]};
    }
    return ret;
};
cc.ColorForBody = function (body) {
    if (body.isRogue() || body.isSleeping()) {
        return cc.color(128, 128, 128, 128);
    } else if (body.nodeIdleTime > body.space.sleepTimeThreshold) {
        return cc.color(84, 84, 84, 128);
    } else {
        return cc.color(255, 0, 0, 128);
    }
};
cc.DrawShape = function (shape, renderer) {
    var body = shape.body;
    var color = cc.ColorForBody(body);
    switch (shape.collisionCode) {
        case cp.CircleShape.prototype.collisionCode:
            this.drawDot(shape.tc, Math.max(shape.r, 1.0), color);
            this.drawSegment(shape.tc, cp.v.add(shape.tc, cp.v.mult(body.rot, shape.r)), 1.0, color);
            break;
        case cp.SegmentShape.prototype.collisionCode:
            this.drawSegment(shape.ta, shape.tb, Math.max(shape.r, 2.0), color);
            break;
        case cp.PolyShape.prototype.collisionCode:
            var line = cc.color(color.r, color.g, color.b, cc.lerp(color.a, 255, 0.5));
            this.drawPoly(cc.__convertVerts(shape.tVerts), color, 1.0, line);
            break;
        default:
            cc.log("cc.DrawShape(): Bad assertion in DrawShape()");
            break;
    }
};
cc.DrawConstraint = function (constraint, renderer) {
    var body_a = constraint.a;
    var body_b = constraint.b;
    var a, b;
    if (constraint instanceof cp.PinJoint) {
        a = body_a.local2World(constraint.anchr1);
        b = body_b.local2World(constraint.anchr2);
        this.drawDot(a, 3.0, cc.CONSTRAINT_COLOR);
        this.drawDot(b, 3.0, cc.CONSTRAINT_COLOR);
        this.drawSegment(a, b, 1.0, cc.CONSTRAINT_COLOR);
    } else if (constraint instanceof cp.SlideJoint) {
        a = body_a.local2World(constraint.anchr1);
        b = body_b.local2World(constraint.anchr2);
        this.drawDot(a, 3.0, cc.CONSTRAINT_COLOR);
        this.drawDot(b, 3.0, cc.CONSTRAINT_COLOR);
        this.drawSegment(a, b, 1.0, cc.CONSTRAINT_COLOR);
    } else if (constraint instanceof cp.PivotJoint) {
        a = body_a.local2World(constraint.anchr1);
        b = body_b.local2World(constraint.anchr2);
        this.drawDot(a, 3.0, cc.CONSTRAINT_COLOR);
        this.drawDot(b, 3.0, cc.CONSTRAINT_COLOR);
    } else if (constraint instanceof cp.GrooveJoint) {
        a = body_a.local2World(constraint.grv_a);
        b = body_a.local2World(constraint.grv_b);
        var c = body_b.local2World(constraint.anchr2);
        this.drawDot(c, 3.0, cc.CONSTRAINT_COLOR);
        this.drawSegment(a, b, 1.0, cc.CONSTRAINT_COLOR);
    } else if (constraint instanceof cp.DampedSpring) {
    } else {
    }
};
cc.CONSTRAINT_COLOR = cc.color(0, 255, 0, 128);
cc.PhysicsDebugNode = cc.DrawNode.extend({
    _space:null,
    _className:"PhysicsDebugNode",
    ctor: function (space) {
        cc.DrawNode.prototype.ctor.call(this);
        this._space = space;
    },
    getSpace:function () {
        return this._space;
    },
    setSpace:function (space) {
        this._space = space;
    },
    draw:function (context) {
        if (!this._space)
            return;
        this._space.eachShape(cc.DrawShape.bind(this));
        this._space.eachConstraint(cc.DrawConstraint.bind(this));
        cc.DrawNode.prototype.draw.call(this);
        this.clear();
    },
    _createRenderCmd: function(){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new cc.PhysicsDebugNode.CanvasRenderCmd(this);
        else
            return new cc.PhysicsDebugNode.WebGLRenderCmd(this);
    }
});
cc.PhysicsDebugNode.create = function (space) {
    return new cc.PhysicsDebugNode(space);
};
(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;
})();
(function(){
    cc.PhysicsDebugNode.WebGLRenderCmd = function (renderableObject) {
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
    };
    cc.PhysicsDebugNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
    cc.PhysicsDebugNode.WebGLRenderCmd.prototype.constructor = cc.PhysicsDebugNode.WebGLRenderCmd;
    cc.PhysicsDebugNode.WebGLRenderCmd.prototype.rendering = function (ctx) {
        var node = this._node;
        if (!node._space)
            return;
        node._space.eachShape(cc.DrawShape.bind(node));
        node._space.eachConstraint(cc.DrawConstraint.bind(node));
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        node._render();
        node.clear();
    };
})();
(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.spUploadData = cc.Sprite.WebGLRenderCmd.prototype.uploadData;
    proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
        var node  = this._node;
        node._syncPosition();
        if(!node._ignoreBodyRotation)
            node._syncRotation();
        this.transform(this.getParentRenderCmd(), true);
        return this.spUploadData(f32buffer, ui32buffer, vertexDataOffset);
    };
})();
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module,exports){module.exports=_dereq_("./lib/")},{"./lib/":2}],2:[function(_dereq_,module,exports){var url=_dereq_("./url");var parser=_dereq_("socket.io-parser");var Manager=_dereq_("./manager");var debug=_dereq_("debug")("socket.io-client");module.exports=exports=lookup;var cache=exports.managers={};function lookup(uri,opts){if(typeof uri=="object"){opts=uri;uri=undefined}opts=opts||{};var parsed=url(uri);var source=parsed.source;var id=parsed.id;var io;if(opts.forceNew||opts["force new connection"]||false===opts.multiplex){debug("ignoring socket cache for %s",source);io=Manager(source,opts)}else{if(!cache[id]){debug("new io instance for %s",source);cache[id]=Manager(source,opts)}io=cache[id]}return io.socket(parsed.path)}exports.protocol=parser.protocol;exports.connect=lookup;exports.Manager=_dereq_("./manager");exports.Socket=_dereq_("./socket")},{"./manager":3,"./socket":5,"./url":6,debug:10,"socket.io-parser":46}],3:[function(_dereq_,module,exports){var url=_dereq_("./url");var eio=_dereq_("engine.io-client");var Socket=_dereq_("./socket");var Emitter=_dereq_("component-emitter");var parser=_dereq_("socket.io-parser");var on=_dereq_("./on");var bind=_dereq_("component-bind");var object=_dereq_("object-component");var debug=_dereq_("debug")("socket.io-client:manager");var indexOf=_dereq_("indexof");var Backoff=_dereq_("backo2");module.exports=Manager;function Manager(uri,opts){if(!(this instanceof Manager))return new Manager(uri,opts);if(uri&&"object"==typeof uri){opts=uri;uri=undefined}opts=opts||{};opts.path=opts.path||"/socket.io";this.nsps={};this.subs=[];this.opts=opts;this.reconnection(opts.reconnection!==false);this.reconnectionAttempts(opts.reconnectionAttempts||Infinity);this.reconnectionDelay(opts.reconnectionDelay||1e3);this.reconnectionDelayMax(opts.reconnectionDelayMax||5e3);this.randomizationFactor(opts.randomizationFactor||.5);this.backoff=new Backoff({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()});this.timeout(null==opts.timeout?2e4:opts.timeout);this.readyState="closed";this.uri=uri;this.connected=[];this.encoding=false;this.packetBuffer=[];this.encoder=new parser.Encoder;this.decoder=new parser.Decoder;this.autoConnect=opts.autoConnect!==false;if(this.autoConnect)this.open()}Manager.prototype.emitAll=function(){this.emit.apply(this,arguments);for(var nsp in this.nsps){this.nsps[nsp].emit.apply(this.nsps[nsp],arguments)}};Manager.prototype.updateSocketIds=function(){for(var nsp in this.nsps){this.nsps[nsp].id=this.engine.id}};Emitter(Manager.prototype);Manager.prototype.reconnection=function(v){if(!arguments.length)return this._reconnection;this._reconnection=!!v;return this};Manager.prototype.reconnectionAttempts=function(v){if(!arguments.length)return this._reconnectionAttempts;this._reconnectionAttempts=v;return this};Manager.prototype.reconnectionDelay=function(v){if(!arguments.length)return this._reconnectionDelay;this._reconnectionDelay=v;this.backoff&&this.backoff.setMin(v);return this};Manager.prototype.randomizationFactor=function(v){if(!arguments.length)return this._randomizationFactor;this._randomizationFactor=v;this.backoff&&this.backoff.setJitter(v);return this};Manager.prototype.reconnectionDelayMax=function(v){if(!arguments.length)return this._reconnectionDelayMax;this._reconnectionDelayMax=v;this.backoff&&this.backoff.setMax(v);return this};Manager.prototype.timeout=function(v){if(!arguments.length)return this._timeout;this._timeout=v;return this};Manager.prototype.maybeReconnectOnOpen=function(){if(!this.reconnecting&&this._reconnection&&this.backoff.attempts===0){this.reconnect()}};Manager.prototype.open=Manager.prototype.connect=function(fn){debug("readyState %s",this.readyState);if(~this.readyState.indexOf("open"))return this;debug("opening %s",this.uri);this.engine=eio(this.uri,this.opts);var socket=this.engine;var self=this;this.readyState="opening";this.skipReconnect=false;var openSub=on(socket,"open",function(){self.onopen();fn&&fn()});var errorSub=on(socket,"error",function(data){debug("connect_error");self.cleanup();self.readyState="closed";self.emitAll("connect_error",data);if(fn){var err=new Error("Connection error");err.data=data;fn(err)}else{self.maybeReconnectOnOpen()}});if(false!==this._timeout){var timeout=this._timeout;debug("connect attempt will timeout after %d",timeout);var timer=setTimeout(function(){debug("connect attempt timed out after %d",timeout);openSub.destroy();socket.close();socket.emit("error","timeout");self.emitAll("connect_timeout",timeout)},timeout);this.subs.push({destroy:function(){clearTimeout(timer)}})}this.subs.push(openSub);this.subs.push(errorSub);return this};Manager.prototype.onopen=function(){debug("open");this.cleanup();this.readyState="open";this.emit("open");var socket=this.engine;this.subs.push(on(socket,"data",bind(this,"ondata")));this.subs.push(on(this.decoder,"decoded",bind(this,"ondecoded")));this.subs.push(on(socket,"error",bind(this,"onerror")));this.subs.push(on(socket,"close",bind(this,"onclose")))};Manager.prototype.ondata=function(data){this.decoder.add(data)};Manager.prototype.ondecoded=function(packet){this.emit("packet",packet)};Manager.prototype.onerror=function(err){debug("error",err);this.emitAll("error",err)};Manager.prototype.socket=function(nsp){var socket=this.nsps[nsp];if(!socket){socket=new Socket(this,nsp);this.nsps[nsp]=socket;var self=this;socket.on("connect",function(){socket.id=self.engine.id;if(!~indexOf(self.connected,socket)){self.connected.push(socket)}})}return socket};Manager.prototype.destroy=function(socket){var index=indexOf(this.connected,socket);if(~index)this.connected.splice(index,1);if(this.connected.length)return;this.close()};Manager.prototype.packet=function(packet){debug("writing packet %j",packet);var self=this;if(!self.encoding){self.encoding=true;this.encoder.encode(packet,function(encodedPackets){for(var i=0;i<encodedPackets.length;i++){self.engine.write(encodedPackets[i])}self.encoding=false;self.processPacketQueue()})}else{self.packetBuffer.push(packet)}};Manager.prototype.processPacketQueue=function(){if(this.packetBuffer.length>0&&!this.encoding){var pack=this.packetBuffer.shift();this.packet(pack)}};Manager.prototype.cleanup=function(){var sub;while(sub=this.subs.shift())sub.destroy();this.packetBuffer=[];this.encoding=false;this.decoder.destroy()};Manager.prototype.close=Manager.prototype.disconnect=function(){this.skipReconnect=true;this.backoff.reset();this.readyState="closed";this.engine&&this.engine.close()};Manager.prototype.onclose=function(reason){debug("close");this.cleanup();this.backoff.reset();this.readyState="closed";this.emit("close",reason);if(this._reconnection&&!this.skipReconnect){this.reconnect()}};Manager.prototype.reconnect=function(){if(this.reconnecting||this.skipReconnect)return this;var self=this;if(this.backoff.attempts>=this._reconnectionAttempts){debug("reconnect failed");this.backoff.reset();this.emitAll("reconnect_failed");this.reconnecting=false}else{var delay=this.backoff.duration();debug("will wait %dms before reconnect attempt",delay);this.reconnecting=true;var timer=setTimeout(function(){if(self.skipReconnect)return;debug("attempting reconnect");self.emitAll("reconnect_attempt",self.backoff.attempts);self.emitAll("reconnecting",self.backoff.attempts);if(self.skipReconnect)return;self.open(function(err){if(err){debug("reconnect attempt error");self.reconnecting=false;self.reconnect();self.emitAll("reconnect_error",err.data)}else{debug("reconnect success");self.onreconnect()}})},delay);this.subs.push({destroy:function(){clearTimeout(timer)}})}};Manager.prototype.onreconnect=function(){var attempt=this.backoff.attempts;this.reconnecting=false;this.backoff.reset();this.updateSocketIds();this.emitAll("reconnect",attempt)}},{"./on":4,"./socket":5,"./url":6,backo2:7,"component-bind":8,"component-emitter":9,debug:10,"engine.io-client":11,indexof:42,"object-component":43,"socket.io-parser":46}],4:[function(_dereq_,module,exports){module.exports=on;function on(obj,ev,fn){obj.on(ev,fn);return{destroy:function(){obj.removeListener(ev,fn)}}}},{}],5:[function(_dereq_,module,exports){var parser=_dereq_("socket.io-parser");var Emitter=_dereq_("component-emitter");var toArray=_dereq_("to-array");var on=_dereq_("./on");var bind=_dereq_("component-bind");var debug=_dereq_("debug")("socket.io-client:socket");var hasBin=_dereq_("has-binary");module.exports=exports=Socket;var events={connect:1,connect_error:1,connect_timeout:1,disconnect:1,error:1,reconnect:1,reconnect_attempt:1,reconnect_failed:1,reconnect_error:1,reconnecting:1};var emit=Emitter.prototype.emit;function Socket(io,nsp){this.io=io;this.nsp=nsp;this.json=this;this.ids=0;this.acks={};if(this.io.autoConnect)this.open();this.receiveBuffer=[];this.sendBuffer=[];this.connected=false;this.disconnected=true}Emitter(Socket.prototype);Socket.prototype.subEvents=function(){if(this.subs)return;var io=this.io;this.subs=[on(io,"open",bind(this,"onopen")),on(io,"packet",bind(this,"onpacket")),on(io,"close",bind(this,"onclose"))]};Socket.prototype.open=Socket.prototype.connect=function(){if(this.connected)return this;this.subEvents();this.io.open();if("open"==this.io.readyState)this.onopen();return this};Socket.prototype.send=function(){var args=toArray(arguments);args.unshift("message");this.emit.apply(this,args);return this};Socket.prototype.emit=function(ev){if(events.hasOwnProperty(ev)){emit.apply(this,arguments);return this}var args=toArray(arguments);var parserType=parser.EVENT;if(hasBin(args)){parserType=parser.BINARY_EVENT}var packet={type:parserType,data:args};if("function"==typeof args[args.length-1]){debug("emitting packet with ack id %d",this.ids);this.acks[this.ids]=args.pop();packet.id=this.ids++}if(this.connected){this.packet(packet)}else{this.sendBuffer.push(packet)}return this};Socket.prototype.packet=function(packet){packet.nsp=this.nsp;this.io.packet(packet)};Socket.prototype.onopen=function(){debug("transport is open - connecting");if("/"!=this.nsp){this.packet({type:parser.CONNECT})}};Socket.prototype.onclose=function(reason){debug("close (%s)",reason);this.connected=false;this.disconnected=true;delete this.id;this.emit("disconnect",reason)};Socket.prototype.onpacket=function(packet){if(packet.nsp!=this.nsp)return;switch(packet.type){case parser.CONNECT:this.onconnect();break;case parser.EVENT:this.onevent(packet);break;case parser.BINARY_EVENT:this.onevent(packet);break;case parser.ACK:this.onack(packet);break;case parser.BINARY_ACK:this.onack(packet);break;case parser.DISCONNECT:this.ondisconnect();break;case parser.ERROR:this.emit("error",packet.data);break}};Socket.prototype.onevent=function(packet){var args=packet.data||[];debug("emitting event %j",args);if(null!=packet.id){debug("attaching ack callback to event");args.push(this.ack(packet.id))}if(this.connected){emit.apply(this,args)}else{this.receiveBuffer.push(args)}};Socket.prototype.ack=function(id){var self=this;var sent=false;return function(){if(sent)return;sent=true;var args=toArray(arguments);debug("sending ack %j",args);var type=hasBin(args)?parser.BINARY_ACK:parser.ACK;self.packet({type:type,id:id,data:args})}};Socket.prototype.onack=function(packet){debug("calling ack %s with %j",packet.id,packet.data);var fn=this.acks[packet.id];fn.apply(this,packet.data);delete this.acks[packet.id]};Socket.prototype.onconnect=function(){this.connected=true;this.disconnected=false;this.emit("connect");this.emitBuffered()};Socket.prototype.emitBuffered=function(){var i;for(i=0;i<this.receiveBuffer.length;i++){emit.apply(this,this.receiveBuffer[i])}this.receiveBuffer=[];for(i=0;i<this.sendBuffer.length;i++){this.packet(this.sendBuffer[i])}this.sendBuffer=[]};Socket.prototype.ondisconnect=function(){debug("server disconnect (%s)",this.nsp);this.destroy();this.onclose("io server disconnect")};Socket.prototype.destroy=function(){if(this.subs){for(var i=0;i<this.subs.length;i++){this.subs[i].destroy()}this.subs=null}this.io.destroy(this)};Socket.prototype.close=Socket.prototype.disconnect=function(){if(this.connected){debug("performing disconnect (%s)",this.nsp);this.packet({type:parser.DISCONNECT})}this.destroy();if(this.connected){this.onclose("io client disconnect")}return this}},{"./on":4,"component-bind":8,"component-emitter":9,debug:10,"has-binary":38,"socket.io-parser":46,"to-array":50}],6:[function(_dereq_,module,exports){(function(global){var parseuri=_dereq_("parseuri");var debug=_dereq_("debug")("socket.io-client:url");module.exports=url;function url(uri,loc){var obj=uri;var loc=loc||global.location;if(null==uri)uri=loc.protocol+"//"+loc.host;if("string"==typeof uri){if("/"==uri.charAt(0)){if("/"==uri.charAt(1)){uri=loc.protocol+uri}else{uri=loc.hostname+uri}}if(!/^(https?|wss?):\/\//.test(uri)){debug("protocol-less url %s",uri);if("undefined"!=typeof loc){uri=loc.protocol+"//"+uri}else{uri="https://"+uri}}debug("parse %s",uri);obj=parseuri(uri)}if(!obj.port){if(/^(http|ws)$/.test(obj.protocol)){obj.port="80"}else if(/^(http|ws)s$/.test(obj.protocol)){obj.port="443"}}obj.path=obj.path||"/";obj.id=obj.protocol+"://"+obj.host+":"+obj.port;obj.href=obj.protocol+"://"+obj.host+(loc&&loc.port==obj.port?"":":"+obj.port);return obj}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{debug:10,parseuri:44}],7:[function(_dereq_,module,exports){module.exports=Backoff;function Backoff(opts){opts=opts||{};this.ms=opts.min||100;this.max=opts.max||1e4;this.factor=opts.factor||2;this.jitter=opts.jitter>0&&opts.jitter<=1?opts.jitter:0;this.attempts=0}Backoff.prototype.duration=function(){var ms=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var rand=Math.random();var deviation=Math.floor(rand*this.jitter*ms);ms=(Math.floor(rand*10)&1)==0?ms-deviation:ms+deviation}return Math.min(ms,this.max)|0};Backoff.prototype.reset=function(){this.attempts=0};Backoff.prototype.setMin=function(min){this.ms=min};Backoff.prototype.setMax=function(max){this.max=max};Backoff.prototype.setJitter=function(jitter){this.jitter=jitter}},{}],8:[function(_dereq_,module,exports){var slice=[].slice;module.exports=function(obj,fn){if("string"==typeof fn)fn=obj[fn];if("function"!=typeof fn)throw new Error("bind() requires a function");var args=slice.call(arguments,2);return function(){return fn.apply(obj,args.concat(slice.call(arguments)))}}},{}],9:[function(_dereq_,module,exports){module.exports=Emitter;function Emitter(obj){if(obj)return mixin(obj)}function mixin(obj){for(var key in Emitter.prototype){obj[key]=Emitter.prototype[key]}return obj}Emitter.prototype.on=Emitter.prototype.addEventListener=function(event,fn){this._callbacks=this._callbacks||{};(this._callbacks[event]=this._callbacks[event]||[]).push(fn);return this};Emitter.prototype.once=function(event,fn){var self=this;this._callbacks=this._callbacks||{};function on(){self.off(event,on);fn.apply(this,arguments)}on.fn=fn;this.on(event,on);return this};Emitter.prototype.off=Emitter.prototype.removeListener=Emitter.prototype.removeAllListeners=Emitter.prototype.removeEventListener=function(event,fn){this._callbacks=this._callbacks||{};if(0==arguments.length){this._callbacks={};return this}var callbacks=this._callbacks[event];if(!callbacks)return this;if(1==arguments.length){delete this._callbacks[event];return this}var cb;for(var i=0;i<callbacks.length;i++){cb=callbacks[i];if(cb===fn||cb.fn===fn){callbacks.splice(i,1);break}}return this};Emitter.prototype.emit=function(event){this._callbacks=this._callbacks||{};var args=[].slice.call(arguments,1),callbacks=this._callbacks[event];if(callbacks){callbacks=callbacks.slice(0);for(var i=0,len=callbacks.length;i<len;++i){callbacks[i].apply(this,args)}}return this};Emitter.prototype.listeners=function(event){this._callbacks=this._callbacks||{};return this._callbacks[event]||[]};Emitter.prototype.hasListeners=function(event){return!!this.listeners(event).length}},{}],10:[function(_dereq_,module,exports){module.exports=debug;function debug(name){if(!debug.enabled(name))return function(){};return function(fmt){fmt=coerce(fmt);var curr=new Date;var ms=curr-(debug[name]||curr);debug[name]=curr;fmt=name+" "+fmt+" +"+debug.humanize(ms);window.console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}}debug.names=[];debug.skips=[];debug.enable=function(name){try{localStorage.debug=name}catch(e){}var split=(name||"").split(/[\s,]+/),len=split.length;for(var i=0;i<len;i++){name=split[i].replace("*",".*?");if(name[0]==="-"){debug.skips.push(new RegExp("^"+name.substr(1)+"$"))}else{debug.names.push(new RegExp("^"+name+"$"))}}};debug.disable=function(){debug.enable("")};debug.humanize=function(ms){var sec=1e3,min=60*1e3,hour=60*min;if(ms>=hour)return(ms/hour).toFixed(1)+"h";if(ms>=min)return(ms/min).toFixed(1)+"m";if(ms>=sec)return(ms/sec|0)+"s";return ms+"ms"};debug.enabled=function(name){for(var i=0,len=debug.skips.length;i<len;i++){if(debug.skips[i].test(name)){return false}}for(var i=0,len=debug.names.length;i<len;i++){if(debug.names[i].test(name)){return true}}return false};function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}try{if(window.localStorage)debug.enable(localStorage.debug)}catch(e){}},{}],11:[function(_dereq_,module,exports){module.exports=_dereq_("./lib/")},{"./lib/":12}],12:[function(_dereq_,module,exports){module.exports=_dereq_("./socket");module.exports.parser=_dereq_("engine.io-parser")},{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){(function(global){var transports=_dereq_("./transports");var Emitter=_dereq_("component-emitter");var debug=_dereq_("debug")("engine.io-client:socket");var index=_dereq_("indexof");var parser=_dereq_("engine.io-parser");var parseuri=_dereq_("parseuri");var parsejson=_dereq_("parsejson");var parseqs=_dereq_("parseqs");module.exports=Socket;function noop(){}function Socket(uri,opts){if(!(this instanceof Socket))return new Socket(uri,opts);opts=opts||{};if(uri&&"object"==typeof uri){opts=uri;uri=null}if(uri){uri=parseuri(uri);opts.host=uri.host;opts.secure=uri.protocol=="https"||uri.protocol=="wss";opts.port=uri.port;if(uri.query)opts.query=uri.query}this.secure=null!=opts.secure?opts.secure:global.location&&"https:"==location.protocol;if(opts.host){var pieces=opts.host.split(":");opts.hostname=pieces.shift();if(pieces.length){opts.port=pieces.pop()}else if(!opts.port){opts.port=this.secure?"443":"80"}}this.agent=opts.agent||false;this.hostname=opts.hostname||(global.location?location.hostname:"localhost");this.port=opts.port||(global.location&&location.port?location.port:this.secure?443:80);this.query=opts.query||{};if("string"==typeof this.query)this.query=parseqs.decode(this.query);this.upgrade=false!==opts.upgrade;this.path=(opts.path||"/engine.io").replace(/\/$/,"")+"/";this.forceJSONP=!!opts.forceJSONP;this.jsonp=false!==opts.jsonp;this.forceBase64=!!opts.forceBase64;this.enablesXDR=!!opts.enablesXDR;this.timestampParam=opts.timestampParam||"t";this.timestampRequests=opts.timestampRequests;this.transports=opts.transports||["polling","websocket"];this.readyState="";this.writeBuffer=[];this.callbackBuffer=[];this.policyPort=opts.policyPort||843;this.rememberUpgrade=opts.rememberUpgrade||false;this.binaryType=null;this.onlyBinaryUpgrades=opts.onlyBinaryUpgrades;this.pfx=opts.pfx||null;this.key=opts.key||null;this.passphrase=opts.passphrase||null;this.cert=opts.cert||null;this.ca=opts.ca||null;this.ciphers=opts.ciphers||null;this.rejectUnauthorized=opts.rejectUnauthorized||null;this.open()}Socket.priorWebsocketSuccess=false;Emitter(Socket.prototype);Socket.protocol=parser.protocol;Socket.Socket=Socket;Socket.Transport=_dereq_("./transport");Socket.transports=_dereq_("./transports");Socket.parser=_dereq_("engine.io-parser");Socket.prototype.createTransport=function(name){debug('creating transport "%s"',name);var query=clone(this.query);query.EIO=parser.protocol;query.transport=name;if(this.id)query.sid=this.id;var transport=new transports[name]({agent:this.agent,hostname:this.hostname,port:this.port,secure:this.secure,path:this.path,query:query,forceJSONP:this.forceJSONP,jsonp:this.jsonp,forceBase64:this.forceBase64,enablesXDR:this.enablesXDR,timestampRequests:this.timestampRequests,timestampParam:this.timestampParam,policyPort:this.policyPort,socket:this,pfx:this.pfx,key:this.key,passphrase:this.passphrase,cert:this.cert,ca:this.ca,ciphers:this.ciphers,rejectUnauthorized:this.rejectUnauthorized});return transport};function clone(obj){var o={};for(var i in obj){if(obj.hasOwnProperty(i)){o[i]=obj[i]}}return o}Socket.prototype.open=function(){var transport;if(this.rememberUpgrade&&Socket.priorWebsocketSuccess&&this.transports.indexOf("websocket")!=-1){transport="websocket"}else if(0==this.transports.length){var self=this;setTimeout(function(){self.emit("error","No transports available")},0);return}else{transport=this.transports[0]}this.readyState="opening";var transport;try{transport=this.createTransport(transport)}catch(e){this.transports.shift();this.open();return}transport.open();this.setTransport(transport)};Socket.prototype.setTransport=function(transport){debug("setting transport %s",transport.name);var self=this;if(this.transport){debug("clearing existing transport %s",this.transport.name);this.transport.removeAllListeners()}this.transport=transport;transport.on("drain",function(){self.onDrain()}).on("packet",function(packet){self.onPacket(packet)}).on("error",function(e){self.onError(e)}).on("close",function(){self.onClose("transport close")})};Socket.prototype.probe=function(name){debug('probing transport "%s"',name);var transport=this.createTransport(name,{probe:1}),failed=false,self=this;Socket.priorWebsocketSuccess=false;function onTransportOpen(){if(self.onlyBinaryUpgrades){var upgradeLosesBinary=!this.supportsBinary&&self.transport.supportsBinary;failed=failed||upgradeLosesBinary}if(failed)return;debug('probe transport "%s" opened',name);transport.send([{type:"ping",data:"probe"}]);transport.once("packet",function(msg){if(failed)return;if("pong"==msg.type&&"probe"==msg.data){debug('probe transport "%s" pong',name);self.upgrading=true;self.emit("upgrading",transport);if(!transport)return;Socket.priorWebsocketSuccess="websocket"==transport.name;debug('pausing current transport "%s"',self.transport.name);self.transport.pause(function(){if(failed)return;if("closed"==self.readyState)return;debug("changing transport and sending upgrade packet");cleanup();self.setTransport(transport);transport.send([{type:"upgrade"}]);self.emit("upgrade",transport);transport=null;self.upgrading=false;self.flush()})}else{debug('probe transport "%s" failed',name);var err=new Error("probe error");err.transport=transport.name;self.emit("upgradeError",err)}})}function freezeTransport(){if(failed)return;failed=true;cleanup();transport.close();transport=null}function onerror(err){var error=new Error("probe error: "+err);error.transport=transport.name;freezeTransport();debug('probe transport "%s" failed because of error: %s',name,err);self.emit("upgradeError",error)}function onTransportClose(){onerror("transport closed")}function onclose(){onerror("socket closed")}function onupgrade(to){if(transport&&to.name!=transport.name){debug('"%s" works - aborting "%s"',to.name,transport.name);freezeTransport()}}function cleanup(){transport.removeListener("open",onTransportOpen);transport.removeListener("error",onerror);transport.removeListener("close",onTransportClose);self.removeListener("close",onclose);self.removeListener("upgrading",onupgrade)}transport.once("open",onTransportOpen);transport.once("error",onerror);transport.once("close",onTransportClose);this.once("close",onclose);this.once("upgrading",onupgrade);transport.open()};Socket.prototype.onOpen=function(){debug("socket open");this.readyState="open";Socket.priorWebsocketSuccess="websocket"==this.transport.name;this.emit("open");this.flush();if("open"==this.readyState&&this.upgrade&&this.transport.pause){debug("starting upgrade probes");for(var i=0,l=this.upgrades.length;i<l;i++){this.probe(this.upgrades[i])}}};Socket.prototype.onPacket=function(packet){if("opening"==this.readyState||"open"==this.readyState){debug('socket receive: type "%s", data "%s"',packet.type,packet.data);this.emit("packet",packet);this.emit("heartbeat");switch(packet.type){case"open":this.onHandshake(parsejson(packet.data));break;case"pong":this.setPing();break;case"error":var err=new Error("server error");err.code=packet.data;this.emit("error",err);break;case"message":this.emit("data",packet.data);this.emit("message",packet.data);break}}else{debug('packet received with socket readyState "%s"',this.readyState)}};Socket.prototype.onHandshake=function(data){this.emit("handshake",data);this.id=data.sid;this.transport.query.sid=data.sid;this.upgrades=this.filterUpgrades(data.upgrades);this.pingInterval=data.pingInterval;this.pingTimeout=data.pingTimeout;this.onOpen();if("closed"==this.readyState)return;this.setPing();this.removeListener("heartbeat",this.onHeartbeat);this.on("heartbeat",this.onHeartbeat)};Socket.prototype.onHeartbeat=function(timeout){clearTimeout(this.pingTimeoutTimer);var self=this;self.pingTimeoutTimer=setTimeout(function(){if("closed"==self.readyState)return;self.onClose("ping timeout")},timeout||self.pingInterval+self.pingTimeout)};Socket.prototype.setPing=function(){var self=this;clearTimeout(self.pingIntervalTimer);self.pingIntervalTimer=setTimeout(function(){debug("writing ping packet - expecting pong within %sms",self.pingTimeout);self.ping();self.onHeartbeat(self.pingTimeout)},self.pingInterval)};Socket.prototype.ping=function(){this.sendPacket("ping")};Socket.prototype.onDrain=function(){for(var i=0;i<this.prevBufferLen;i++){if(this.callbackBuffer[i]){this.callbackBuffer[i]()}}this.writeBuffer.splice(0,this.prevBufferLen);this.callbackBuffer.splice(0,this.prevBufferLen);this.prevBufferLen=0;if(this.writeBuffer.length==0){this.emit("drain")}else{this.flush()}};Socket.prototype.flush=function(){if("closed"!=this.readyState&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){debug("flushing %d packets in socket",this.writeBuffer.length);this.transport.send(this.writeBuffer);this.prevBufferLen=this.writeBuffer.length;this.emit("flush")}};Socket.prototype.write=Socket.prototype.send=function(msg,fn){this.sendPacket("message",msg,fn);return this};Socket.prototype.sendPacket=function(type,data,fn){if("closing"==this.readyState||"closed"==this.readyState){return}var packet={type:type,data:data};this.emit("packetCreate",packet);this.writeBuffer.push(packet);this.callbackBuffer.push(fn);this.flush()};Socket.prototype.close=function(){if("opening"==this.readyState||"open"==this.readyState){this.readyState="closing";var self=this;function close(){self.onClose("forced close");debug("socket closing - telling transport to close");self.transport.close()}function cleanupAndClose(){self.removeListener("upgrade",cleanupAndClose);self.removeListener("upgradeError",cleanupAndClose);close()}function waitForUpgrade(){self.once("upgrade",cleanupAndClose);self.once("upgradeError",cleanupAndClose)}if(this.writeBuffer.length){this.once("drain",function(){if(this.upgrading){waitForUpgrade()}else{close()}})}else if(this.upgrading){waitForUpgrade()}else{close()}}return this};Socket.prototype.onError=function(err){debug("socket error %j",err);Socket.priorWebsocketSuccess=false;this.emit("error",err);this.onClose("transport error",err)};Socket.prototype.onClose=function(reason,desc){if("opening"==this.readyState||"open"==this.readyState||"closing"==this.readyState){debug('socket close with reason: "%s"',reason);var self=this;clearTimeout(this.pingIntervalTimer);clearTimeout(this.pingTimeoutTimer);setTimeout(function(){self.writeBuffer=[];self.callbackBuffer=[];self.prevBufferLen=0},0);this.transport.removeAllListeners("close");this.transport.close();this.transport.removeAllListeners();this.readyState="closed";this.id=null;this.emit("close",reason,desc)}};Socket.prototype.filterUpgrades=function(upgrades){var filteredUpgrades=[];for(var i=0,j=upgrades.length;i<j;i++){if(~index(this.transports,upgrades[i]))filteredUpgrades.push(upgrades[i])}return filteredUpgrades}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./transport":14,"./transports":15,"component-emitter":9,debug:22,"engine.io-parser":25,indexof:42,parsejson:34,parseqs:35,parseuri:36}],14:[function(_dereq_,module,exports){var parser=_dereq_("engine.io-parser");var Emitter=_dereq_("component-emitter");module.exports=Transport;function Transport(opts){this.path=opts.path;this.hostname=opts.hostname;this.port=opts.port;this.secure=opts.secure;this.query=opts.query;this.timestampParam=opts.timestampParam;this.timestampRequests=opts.timestampRequests;this.readyState="";this.agent=opts.agent||false;this.socket=opts.socket;this.enablesXDR=opts.enablesXDR;this.pfx=opts.pfx;this.key=opts.key;this.passphrase=opts.passphrase;this.cert=opts.cert;this.ca=opts.ca;this.ciphers=opts.ciphers;this.rejectUnauthorized=opts.rejectUnauthorized}Emitter(Transport.prototype);Transport.timestamps=0;Transport.prototype.onError=function(msg,desc){var err=new Error(msg);err.type="TransportError";err.description=desc;this.emit("error",err);return this};Transport.prototype.open=function(){if("closed"==this.readyState||""==this.readyState){this.readyState="opening";this.doOpen()}return this};Transport.prototype.close=function(){if("opening"==this.readyState||"open"==this.readyState){this.doClose();this.onClose()}return this};Transport.prototype.send=function(packets){if("open"==this.readyState){this.write(packets)}else{throw new Error("Transport not open")}};Transport.prototype.onOpen=function(){this.readyState="open";this.writable=true;this.emit("open")};Transport.prototype.onData=function(data){var packet=parser.decodePacket(data,this.socket.binaryType);this.onPacket(packet)};Transport.prototype.onPacket=function(packet){this.emit("packet",packet)};Transport.prototype.onClose=function(){this.readyState="closed";this.emit("close")}},{"component-emitter":9,"engine.io-parser":25}],15:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_("xmlhttprequest");var XHR=_dereq_("./polling-xhr");var JSONP=_dereq_("./polling-jsonp");var websocket=_dereq_("./websocket");exports.polling=polling;exports.websocket=websocket;function polling(opts){var xhr;var xd=false;var xs=false;var jsonp=false!==opts.jsonp;if(global.location){var isSSL="https:"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}xd=opts.hostname!=location.hostname||port!=opts.port;xs=opts.secure!=isSSL}opts.xdomain=xd;opts.xscheme=xs;xhr=new XMLHttpRequest(opts);if("open"in xhr&&!opts.forceJSONP){return new XHR(opts)}else{if(!jsonp)throw new Error("JSONP disabled");return new JSONP(opts)}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,xmlhttprequest:20}],16:[function(_dereq_,module,exports){(function(global){var Polling=_dereq_("./polling");var inherit=_dereq_("component-inherit");module.exports=JSONPPolling;var rNewline=/\n/g;var rEscapedNewline=/\\n/g;var callbacks;var index=0;function empty(){}function JSONPPolling(opts){Polling.call(this,opts);
    this.query=this.query||{};if(!callbacks){if(!global.___eio)global.___eio=[];callbacks=global.___eio}this.index=callbacks.length;var self=this;callbacks.push(function(msg){self.onData(msg)});this.query.j=this.index;if(global.document&&global.addEventListener){global.addEventListener("beforeunload",function(){if(self.script)self.script.onerror=empty},false)}}inherit(JSONPPolling,Polling);JSONPPolling.prototype.supportsBinary=false;JSONPPolling.prototype.doClose=function(){if(this.script){this.script.parentNode.removeChild(this.script);this.script=null}if(this.form){this.form.parentNode.removeChild(this.form);this.form=null;this.iframe=null}Polling.prototype.doClose.call(this)};JSONPPolling.prototype.doPoll=function(){var self=this;var script=document.createElement("script");if(this.script){this.script.parentNode.removeChild(this.script);this.script=null}script.async=true;script.src=this.uri();script.onerror=function(e){self.onError("jsonp poll error",e)};var insertAt=document.getElementsByTagName("script")[0];insertAt.parentNode.insertBefore(script,insertAt);this.script=script;var isUAgecko="undefined"!=typeof navigator&&/gecko/i.test(navigator.userAgent);if(isUAgecko){setTimeout(function(){var iframe=document.createElement("iframe");document.body.appendChild(iframe);document.body.removeChild(iframe)},100)}};JSONPPolling.prototype.doWrite=function(data,fn){var self=this;if(!this.form){var form=document.createElement("form");var area=document.createElement("textarea");var id=this.iframeId="eio_iframe_"+this.index;var iframe;form.className="socketio";form.style.position="absolute";form.style.top="-1000px";form.style.left="-1000px";form.target=id;form.method="POST";form.setAttribute("accept-charset","utf-8");area.name="d";form.appendChild(area);document.body.appendChild(form);this.form=form;this.area=area}this.form.action=this.uri();function complete(){initIframe();fn()}function initIframe(){if(self.iframe){try{self.form.removeChild(self.iframe)}catch(e){self.onError("jsonp polling iframe removal error",e)}}try{var html='<iframe src="javascript:0" name="'+self.iframeId+'">';iframe=document.createElement(html)}catch(e){iframe=document.createElement("iframe");iframe.name=self.iframeId;iframe.src="javascript:0"}iframe.id=self.iframeId;self.form.appendChild(iframe);self.iframe=iframe}initIframe();data=data.replace(rEscapedNewline,"\\\n");this.area.value=data.replace(rNewline,"\\n");try{this.form.submit()}catch(e){}if(this.iframe.attachEvent){this.iframe.onreadystatechange=function(){if(self.iframe.readyState=="complete"){complete()}}}else{this.iframe.onload=complete}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_("xmlhttprequest");var Polling=_dereq_("./polling");var Emitter=_dereq_("component-emitter");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling-xhr");module.exports=XHR;module.exports.Request=Request;function empty(){}function XHR(opts){Polling.call(this,opts);if(global.location){var isSSL="https:"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}this.xd=opts.hostname!=global.location.hostname||port!=opts.port;this.xs=opts.secure!=isSSL}}inherit(XHR,Polling);XHR.prototype.supportsBinary=true;XHR.prototype.request=function(opts){opts=opts||{};opts.uri=this.uri();opts.xd=this.xd;opts.xs=this.xs;opts.agent=this.agent||false;opts.supportsBinary=this.supportsBinary;opts.enablesXDR=this.enablesXDR;opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;return new Request(opts)};XHR.prototype.doWrite=function(data,fn){var isBinary=typeof data!=="string"&&data!==undefined;var req=this.request({method:"POST",data:data,isBinary:isBinary});var self=this;req.on("success",fn);req.on("error",function(err){self.onError("xhr post error",err)});this.sendXhr=req};XHR.prototype.doPoll=function(){debug("xhr poll");var req=this.request();var self=this;req.on("data",function(data){self.onData(data)});req.on("error",function(err){self.onError("xhr poll error",err)});this.pollXhr=req};function Request(opts){this.method=opts.method||"GET";this.uri=opts.uri;this.xd=!!opts.xd;this.xs=!!opts.xs;this.async=false!==opts.async;this.data=undefined!=opts.data?opts.data:null;this.agent=opts.agent;this.isBinary=opts.isBinary;this.supportsBinary=opts.supportsBinary;this.enablesXDR=opts.enablesXDR;this.pfx=opts.pfx;this.key=opts.key;this.passphrase=opts.passphrase;this.cert=opts.cert;this.ca=opts.ca;this.ciphers=opts.ciphers;this.rejectUnauthorized=opts.rejectUnauthorized;this.create()}Emitter(Request.prototype);Request.prototype.create=function(){var opts={agent:this.agent,xdomain:this.xd,xscheme:this.xs,enablesXDR:this.enablesXDR};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;var xhr=this.xhr=new XMLHttpRequest(opts);var self=this;try{debug("xhr open %s: %s",this.method,this.uri);xhr.open(this.method,this.uri,this.async);if(this.supportsBinary){xhr.responseType="arraybuffer"}if("POST"==this.method){try{if(this.isBinary){xhr.setRequestHeader("Content-type","application/octet-stream")}else{xhr.setRequestHeader("Content-type","text/plain;charset=UTF-8")}}catch(e){}}if("withCredentials"in xhr){xhr.withCredentials=true}if(this.hasXDR()){xhr.onload=function(){self.onLoad()};xhr.onerror=function(){self.onError(xhr.responseText)}}else{xhr.onreadystatechange=function(){if(4!=xhr.readyState)return;if(200==xhr.status||1223==xhr.status){self.onLoad()}else{setTimeout(function(){self.onError(xhr.status)},0)}}}debug("xhr data %s",this.data);xhr.send(this.data)}catch(e){setTimeout(function(){self.onError(e)},0);return}if(global.document){this.index=Request.requestsCount++;Request.requests[this.index]=this}};Request.prototype.onSuccess=function(){this.emit("success");this.cleanup()};Request.prototype.onData=function(data){this.emit("data",data);this.onSuccess()};Request.prototype.onError=function(err){this.emit("error",err);this.cleanup(true)};Request.prototype.cleanup=function(fromError){if("undefined"==typeof this.xhr||null===this.xhr){return}if(this.hasXDR()){this.xhr.onload=this.xhr.onerror=empty}else{this.xhr.onreadystatechange=empty}if(fromError){try{this.xhr.abort()}catch(e){}}if(global.document){delete Request.requests[this.index]}this.xhr=null};Request.prototype.onLoad=function(){var data;try{var contentType;try{contentType=this.xhr.getResponseHeader("Content-Type").split(";")[0]}catch(e){}if(contentType==="application/octet-stream"){data=this.xhr.response}else{if(!this.supportsBinary){data=this.xhr.responseText}else{data="ok"}}}catch(e){this.onError(e)}if(null!=data){this.onData(data)}};Request.prototype.hasXDR=function(){return"undefined"!==typeof global.XDomainRequest&&!this.xs&&this.enablesXDR};Request.prototype.abort=function(){this.cleanup()};if(global.document){Request.requestsCount=0;Request.requests={};if(global.attachEvent){global.attachEvent("onunload",unloadHandler)}else if(global.addEventListener){global.addEventListener("beforeunload",unloadHandler,false)}}function unloadHandler(){for(var i in Request.requests){if(Request.requests.hasOwnProperty(i)){Request.requests[i].abort()}}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling":18,"component-emitter":9,"component-inherit":21,debug:22,xmlhttprequest:20}],18:[function(_dereq_,module,exports){var Transport=_dereq_("../transport");var parseqs=_dereq_("parseqs");var parser=_dereq_("engine.io-parser");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling");module.exports=Polling;var hasXHR2=function(){var XMLHttpRequest=_dereq_("xmlhttprequest");var xhr=new XMLHttpRequest({xdomain:false});return null!=xhr.responseType}();function Polling(opts){var forceBase64=opts&&opts.forceBase64;if(!hasXHR2||forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(Polling,Transport);Polling.prototype.name="polling";Polling.prototype.doOpen=function(){this.poll()};Polling.prototype.pause=function(onPause){var pending=0;var self=this;this.readyState="pausing";function pause(){debug("paused");self.readyState="paused";onPause()}if(this.polling||!this.writable){var total=0;if(this.polling){debug("we are currently polling - waiting to pause");total++;this.once("pollComplete",function(){debug("pre-pause polling complete");--total||pause()})}if(!this.writable){debug("we are currently writing - waiting to pause");total++;this.once("drain",function(){debug("pre-pause writing complete");--total||pause()})}}else{pause()}};Polling.prototype.poll=function(){debug("polling");this.polling=true;this.doPoll();this.emit("poll")};Polling.prototype.onData=function(data){var self=this;debug("polling got data %s",data);var callback=function(packet,index,total){if("opening"==self.readyState){self.onOpen()}if("close"==packet.type){self.onClose();return false}self.onPacket(packet)};parser.decodePayload(data,this.socket.binaryType,callback);if("closed"!=this.readyState){this.polling=false;this.emit("pollComplete");if("open"==this.readyState){this.poll()}else{debug('ignoring poll - transport state "%s"',this.readyState)}}};Polling.prototype.doClose=function(){var self=this;function close(){debug("writing close packet");self.write([{type:"close"}])}if("open"==this.readyState){debug("transport open - closing");close()}else{debug("transport not open - deferring close");this.once("open",close)}};Polling.prototype.write=function(packets){var self=this;this.writable=false;var callbackfn=function(){self.writable=true;self.emit("drain")};var self=this;parser.encodePayload(packets,this.supportsBinary,function(data){self.doWrite(data,callbackfn)})};Polling.prototype.uri=function(){var query=this.query||{};var schema=this.secure?"https":"http";var port="";if(false!==this.timestampRequests){query[this.timestampParam]=+new Date+"-"+Transport.timestamps++}if(!this.supportsBinary&&!query.sid){query.b64=1}query=parseqs.encode(query);if(this.port&&("https"==schema&&this.port!=443||"http"==schema&&this.port!=80)){port=":"+this.port}if(query.length){query="?"+query}return schema+"://"+this.hostname+port+this.path+query}},{"../transport":14,"component-inherit":21,debug:22,"engine.io-parser":25,parseqs:35,xmlhttprequest:20}],19:[function(_dereq_,module,exports){var Transport=_dereq_("../transport");var parser=_dereq_("engine.io-parser");var parseqs=_dereq_("parseqs");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:websocket");var WebSocket=_dereq_("ws");module.exports=WS;function WS(opts){var forceBase64=opts&&opts.forceBase64;if(forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(WS,Transport);WS.prototype.name="websocket";WS.prototype.supportsBinary=true;WS.prototype.doOpen=function(){if(!this.check()){return}var self=this;var uri=this.uri();var protocols=void 0;var opts={agent:this.agent};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;this.ws=new WebSocket(uri,protocols,opts);if(this.ws.binaryType===undefined){this.supportsBinary=false}this.ws.binaryType="arraybuffer";this.addEventListeners()};WS.prototype.addEventListeners=function(){var self=this;this.ws.onopen=function(){self.onOpen()};this.ws.onclose=function(){self.onClose()};this.ws.onmessage=function(ev){self.onData(ev.data)};this.ws.onerror=function(e){self.onError("websocket error",e)}};if("undefined"!=typeof navigator&&/iPad|iPhone|iPod/i.test(navigator.userAgent)){WS.prototype.onData=function(data){var self=this;setTimeout(function(){Transport.prototype.onData.call(self,data)},0)}}WS.prototype.write=function(packets){var self=this;this.writable=false;for(var i=0,l=packets.length;i<l;i++){parser.encodePacket(packets[i],this.supportsBinary,function(data){try{self.ws.send(data)}catch(e){debug("websocket closed before onclose event")}})}function ondrain(){self.writable=true;self.emit("drain")}setTimeout(ondrain,0)};WS.prototype.onClose=function(){Transport.prototype.onClose.call(this)};WS.prototype.doClose=function(){if(typeof this.ws!=="undefined"){this.ws.close()}};WS.prototype.uri=function(){var query=this.query||{};var schema=this.secure?"wss":"ws";var port="";if(this.port&&("wss"==schema&&this.port!=443||"ws"==schema&&this.port!=80)){port=":"+this.port}if(this.timestampRequests){query[this.timestampParam]=+new Date}if(!this.supportsBinary){query.b64=1}query=parseqs.encode(query);if(query.length){query="?"+query}return schema+"://"+this.hostname+port+this.path+query};WS.prototype.check=function(){return!!WebSocket&&!("__initialize"in WebSocket&&this.name===WS.prototype.name)}},{"../transport":14,"component-inherit":21,debug:22,"engine.io-parser":25,parseqs:35,ws:37}],20:[function(_dereq_,module,exports){var hasCORS=_dereq_("has-cors");module.exports=function(opts){var xdomain=opts.xdomain;var xscheme=opts.xscheme;var enablesXDR=opts.enablesXDR;try{if("undefined"!=typeof XMLHttpRequest&&(!xdomain||hasCORS)){return new XMLHttpRequest}}catch(e){}try{if("undefined"!=typeof XDomainRequest&&!xscheme&&enablesXDR){return new XDomainRequest}}catch(e){}if(!xdomain){try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}},{"has-cors":40}],21:[function(_dereq_,module,exports){module.exports=function(a,b){var fn=function(){};fn.prototype=b.prototype;a.prototype=new fn;a.prototype.constructor=a}},{}],22:[function(_dereq_,module,exports){exports=module.exports=_dereq_("./debug");exports.log=log;exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"];function useColors(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}exports.formatters.j=function(v){return JSON.stringify(v)};function formatArgs(){var args=arguments;var useColors=this.useColors;args[0]=(useColors?"%c":"")+this.namespace+(useColors?" %c":" ")+args[0]+(useColors?"%c ":" ")+"+"+exports.humanize(this.diff);if(!useColors)return args;var c="color: "+this.color;args=[args[0],c,"color: inherit"].concat(Array.prototype.slice.call(args,1));var index=0;var lastC=0;args[0].replace(/%[a-z%]/g,function(match){if("%"===match)return;index++;if("%c"===match){lastC=index}});args.splice(lastC,0,c);return args}function log(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function save(namespaces){try{if(null==namespaces){localStorage.removeItem("debug")}else{localStorage.debug=namespaces}}catch(e){}}function load(){var r;try{r=localStorage.debug}catch(e){}return r}exports.enable(load())},{"./debug":23}],23:[function(_dereq_,module,exports){exports=module.exports=debug;exports.coerce=coerce;exports.disable=disable;exports.enable=enable;exports.enabled=enabled;exports.humanize=_dereq_("ms");exports.names=[];exports.skips=[];exports.formatters={};var prevColor=0;var prevTime;function selectColor(){return exports.colors[prevColor++%exports.colors.length]}function debug(namespace){function disabled(){}disabled.enabled=false;function enabled(){var self=enabled;var curr=+new Date;var ms=curr-(prevTime||curr);self.diff=ms;self.prev=prevTime;self.curr=curr;prevTime=curr;if(null==self.useColors)self.useColors=exports.useColors();if(null==self.color&&self.useColors)self.color=selectColor();var args=Array.prototype.slice.call(arguments);args[0]=exports.coerce(args[0]);if("string"!==typeof args[0]){args=["%o"].concat(args)}var index=0;args[0]=args[0].replace(/%([a-z%])/g,function(match,format){if(match==="%")return match;index++;var formatter=exports.formatters[format];if("function"===typeof formatter){var val=args[index];match=formatter.call(self,val);args.splice(index,1);index--}return match});if("function"===typeof exports.formatArgs){args=exports.formatArgs.apply(self,args)}var logFn=enabled.log||exports.log||console.log.bind(console);logFn.apply(self,args)}enabled.enabled=true;var fn=exports.enabled(namespace)?enabled:disabled;fn.namespace=namespace;return fn}function enable(namespaces){exports.save(namespaces);var split=(namespaces||"").split(/[\s,]+/);var len=split.length;for(var i=0;i<len;i++){if(!split[i])continue;namespaces=split[i].replace(/\*/g,".*?");if(namespaces[0]==="-"){exports.skips.push(new RegExp("^"+namespaces.substr(1)+"$"))}else{exports.names.push(new RegExp("^"+namespaces+"$"))}}}function disable(){exports.enable("")}function enabled(name){var i,len;for(i=0,len=exports.skips.length;i<len;i++){if(exports.skips[i].test(name)){return false}}for(i=0,len=exports.names.length;i<len;i++){if(exports.names[i].test(name)){return true}}return false}function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}},{ms:24}],24:[function(_dereq_,module,exports){var s=1e3;var m=s*60;var h=m*60;var d=h*24;var y=d*365.25;module.exports=function(val,options){options=options||{};if("string"==typeof val)return parse(val);return options.long?long(val):short(val)};function parse(str){var match=/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);if(!match)return;var n=parseFloat(match[1]);var type=(match[2]||"ms").toLowerCase();switch(type){case"years":case"year":case"y":return n*y;case"days":case"day":case"d":return n*d;case"hours":case"hour":case"h":return n*h;case"minutes":case"minute":case"m":return n*m;case"seconds":case"second":case"s":return n*s;case"ms":return n}}function short(ms){if(ms>=d)return Math.round(ms/d)+"d";if(ms>=h)return Math.round(ms/h)+"h";if(ms>=m)return Math.round(ms/m)+"m";if(ms>=s)return Math.round(ms/s)+"s";return ms+"ms"}function long(ms){return plural(ms,d,"day")||plural(ms,h,"hour")||plural(ms,m,"minute")||plural(ms,s,"second")||ms+" ms"}function plural(ms,n,name){if(ms<n)return;if(ms<n*1.5)return Math.floor(ms/n)+" "+name;return Math.ceil(ms/n)+" "+name+"s"}},{}],25:[function(_dereq_,module,exports){(function(global){var keys=_dereq_("./keys");var hasBinary=_dereq_("has-binary");var sliceBuffer=_dereq_("arraybuffer.slice");var base64encoder=_dereq_("base64-arraybuffer");var after=_dereq_("after");var utf8=_dereq_("utf8");var isAndroid=navigator.userAgent.match(/Android/i);var isPhantomJS=/PhantomJS/i.test(navigator.userAgent);var dontSendBlobs=isAndroid||isPhantomJS;exports.protocol=3;var packets=exports.packets={open:0,close:1,ping:2,pong:3,message:4,upgrade:5,noop:6};var packetslist=keys(packets);var err={type:"error",data:"parser error"};var Blob=_dereq_("blob");exports.encodePacket=function(packet,supportsBinary,utf8encode,callback){if("function"==typeof supportsBinary){callback=supportsBinary;supportsBinary=false}if("function"==typeof utf8encode){callback=utf8encode;utf8encode=null}var data=packet.data===undefined?undefined:packet.data.buffer||packet.data;if(global.ArrayBuffer&&data instanceof ArrayBuffer){return encodeArrayBuffer(packet,supportsBinary,callback)}else if(Blob&&data instanceof global.Blob){return encodeBlob(packet,supportsBinary,callback)}if(data&&data.base64){return encodeBase64Object(packet,callback)}var encoded=packets[packet.type];if(undefined!==packet.data){encoded+=utf8encode?utf8.encode(String(packet.data)):String(packet.data)}return callback(""+encoded)};function encodeBase64Object(packet,callback){var message="b"+exports.packets[packet.type]+packet.data.data;return callback(message)}function encodeArrayBuffer(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}var data=packet.data;var contentArray=new Uint8Array(data);var resultBuffer=new Uint8Array(1+data.byteLength);resultBuffer[0]=packets[packet.type];for(var i=0;i<contentArray.length;i++){resultBuffer[i+1]=contentArray[i]}return callback(resultBuffer.buffer)}function encodeBlobAsArrayBuffer(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}var fr=new FileReader;fr.onload=function(){packet.data=fr.result;exports.encodePacket(packet,supportsBinary,true,callback)};return fr.readAsArrayBuffer(packet.data)}function encodeBlob(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}if(dontSendBlobs){return encodeBlobAsArrayBuffer(packet,supportsBinary,callback)}var length=new Uint8Array(1);length[0]=packets[packet.type];var blob=new Blob([length.buffer,packet.data]);return callback(blob)}exports.encodeBase64Packet=function(packet,callback){var message="b"+exports.packets[packet.type];if(Blob&&packet.data instanceof Blob){var fr=new FileReader;fr.onload=function(){var b64=fr.result.split(",")[1];callback(message+b64)};return fr.readAsDataURL(packet.data)}var b64data;try{b64data=String.fromCharCode.apply(null,new Uint8Array(packet.data))}catch(e){var typed=new Uint8Array(packet.data);var basic=new Array(typed.length);for(var i=0;i<typed.length;i++){basic[i]=typed[i]}b64data=String.fromCharCode.apply(null,basic)}message+=global.btoa(b64data);return callback(message)};exports.decodePacket=function(data,binaryType,utf8decode){if(typeof data=="string"||data===undefined){if(data.charAt(0)=="b"){return exports.decodeBase64Packet(data.substr(1),binaryType)}if(utf8decode){try{data=utf8.decode(data)}catch(e){return err}}var type=data.charAt(0);if(Number(type)!=type||!packetslist[type]){return err}if(data.length>1){return{type:packetslist[type],data:data.substring(1)}}else{return{type:packetslist[type]}}}var asArray=new Uint8Array(data);var type=asArray[0];var rest=sliceBuffer(data,1);if(Blob&&binaryType==="blob"){rest=new Blob([rest])}return{type:packetslist[type],data:rest}};exports.decodeBase64Packet=function(msg,binaryType){var type=packetslist[msg.charAt(0)];if(!global.ArrayBuffer){return{type:type,data:{base64:true,data:msg.substr(1)}}}var data=base64encoder.decode(msg.substr(1));if(binaryType==="blob"&&Blob){data=new Blob([data])}return{type:type,data:data}};exports.encodePayload=function(packets,supportsBinary,callback){if(typeof supportsBinary=="function"){callback=supportsBinary;supportsBinary=null}var isBinary=hasBinary(packets);if(supportsBinary&&isBinary){if(Blob&&!dontSendBlobs){return exports.encodePayloadAsBlob(packets,callback)}return exports.encodePayloadAsArrayBuffer(packets,callback)}if(!packets.length){return callback("0:")}function setLengthHeader(message){return message.length+":"+message}function encodeOne(packet,doneCallback){exports.encodePacket(packet,!isBinary?false:supportsBinary,true,function(message){doneCallback(null,setLengthHeader(message))})}map(packets,encodeOne,function(err,results){return callback(results.join(""))})};function map(ary,each,done){var result=new Array(ary.length);var next=after(ary.length,done);var eachWithIndex=function(i,el,cb){each(el,function(error,msg){result[i]=msg;cb(error,result)})};for(var i=0;i<ary.length;i++){eachWithIndex(i,ary[i],next)}}exports.decodePayload=function(data,binaryType,callback){if(typeof data!="string"){return exports.decodePayloadAsBinary(data,binaryType,callback)}if(typeof binaryType==="function"){callback=binaryType;binaryType=null}var packet;if(data==""){return callback(err,0,1)}var length="",n,msg;for(var i=0,l=data.length;i<l;i++){var chr=data.charAt(i);if(":"!=chr){length+=chr}else{if(""==length||length!=(n=Number(length))){return callback(err,0,1)}msg=data.substr(i+1,n);if(length!=msg.length){return callback(err,0,1)}if(msg.length){packet=exports.decodePacket(msg,binaryType,true);if(err.type==packet.type&&err.data==packet.data){return callback(err,0,1)}var ret=callback(packet,i+n,l);if(false===ret)return}i+=n;length=""}}if(length!=""){return callback(err,0,1)}};exports.encodePayloadAsArrayBuffer=function(packets,callback){if(!packets.length){return callback(new ArrayBuffer(0))}function encodeOne(packet,doneCallback){exports.encodePacket(packet,true,true,function(data){return doneCallback(null,data)})}map(packets,encodeOne,function(err,encodedPackets){var totalLength=encodedPackets.reduce(function(acc,p){var len;if(typeof p==="string"){len=p.length}else{len=p.byteLength}return acc+len.toString().length+len+2},0);var resultArray=new Uint8Array(totalLength);var bufferIndex=0;encodedPackets.forEach(function(p){var isString=typeof p==="string";var ab=p;if(isString){var view=new Uint8Array(p.length);for(var i=0;i<p.length;i++){view[i]=p.charCodeAt(i)}ab=view.buffer}if(isString){resultArray[bufferIndex++]=0}else{resultArray[bufferIndex++]=1}var lenStr=ab.byteLength.toString();for(var i=0;i<lenStr.length;i++){resultArray[bufferIndex++]=parseInt(lenStr[i])}resultArray[bufferIndex++]=255;var view=new Uint8Array(ab);for(var i=0;i<view.length;i++){resultArray[bufferIndex++]=view[i]}});return callback(resultArray.buffer)})};exports.encodePayloadAsBlob=function(packets,callback){function encodeOne(packet,doneCallback){exports.encodePacket(packet,true,true,function(encoded){var binaryIdentifier=new Uint8Array(1);binaryIdentifier[0]=1;if(typeof encoded==="string"){var view=new Uint8Array(encoded.length);for(var i=0;i<encoded.length;i++){view[i]=encoded.charCodeAt(i)}encoded=view.buffer;binaryIdentifier[0]=0}var len=encoded instanceof ArrayBuffer?encoded.byteLength:encoded.size;var lenStr=len.toString();var lengthAry=new Uint8Array(lenStr.length+1);for(var i=0;i<lenStr.length;i++){lengthAry[i]=parseInt(lenStr[i])}lengthAry[lenStr.length]=255;if(Blob){var blob=new Blob([binaryIdentifier.buffer,lengthAry.buffer,encoded]);doneCallback(null,blob)}})}map(packets,encodeOne,function(err,results){return callback(new Blob(results))})};exports.decodePayloadAsBinary=function(data,binaryType,callback){if(typeof binaryType==="function"){callback=binaryType;binaryType=null}var bufferTail=data;var buffers=[];var numberTooLong=false;while(bufferTail.byteLength>0){var tailArray=new Uint8Array(bufferTail);var isString=tailArray[0]===0;var msgLength="";for(var i=1;;i++){if(tailArray[i]==255)break;if(msgLength.length>310){numberTooLong=true;break}msgLength+=tailArray[i]}if(numberTooLong)return callback(err,0,1);bufferTail=sliceBuffer(bufferTail,2+msgLength.length);msgLength=parseInt(msgLength);var msg=sliceBuffer(bufferTail,0,msgLength);if(isString){try{msg=String.fromCharCode.apply(null,new Uint8Array(msg))}catch(e){var typed=new Uint8Array(msg);msg="";for(var i=0;i<typed.length;i++){msg+=String.fromCharCode(typed[i])}}}buffers.push(msg);bufferTail=sliceBuffer(bufferTail,msgLength)}var total=buffers.length;buffers.forEach(function(buffer,i){callback(exports.decodePacket(buffer,binaryType,true),i,total)})}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./keys":26,after:27,"arraybuffer.slice":28,"base64-arraybuffer":29,blob:30,"has-binary":31,utf8:33}],26:[function(_dereq_,module,exports){module.exports=Object.keys||function keys(obj){var arr=[];var has=Object.prototype.hasOwnProperty;for(var i in obj){if(has.call(obj,i)){arr.push(i)}}return arr}},{}],27:[function(_dereq_,module,exports){module.exports=after;function after(count,callback,err_cb){var bail=false;err_cb=err_cb||noop;proxy.count=count;return count===0?callback():proxy;function proxy(err,result){if(proxy.count<=0){throw new Error("after called too many times")}--proxy.count;if(err){bail=true;callback(err);callback=err_cb}else if(proxy.count===0&&!bail){callback(null,result)}}}function noop(){}},{}],28:[function(_dereq_,module,exports){module.exports=function(arraybuffer,start,end){var bytes=arraybuffer.byteLength;start=start||0;end=end||bytes;if(arraybuffer.slice){return arraybuffer.slice(start,end)}if(start<0){start+=bytes}if(end<0){end+=bytes}if(end>bytes){end=bytes}if(start>=bytes||start>=end||bytes===0){return new ArrayBuffer(0)}var abv=new Uint8Array(arraybuffer);var result=new Uint8Array(end-start);for(var i=start,ii=0;i<end;i++,ii++){result[ii]=abv[i]}return result.buffer}},{}],29:[function(_dereq_,module,exports){(function(chars){"use strict";exports.encode=function(arraybuffer){var bytes=new Uint8Array(arraybuffer),i,len=bytes.length,base64="";for(i=0;i<len;i+=3){base64+=chars[bytes[i]>>2];base64+=chars[(bytes[i]&3)<<4|bytes[i+1]>>4];base64+=chars[(bytes[i+1]&15)<<2|bytes[i+2]>>6];base64+=chars[bytes[i+2]&63]}if(len%3===2){base64=base64.substring(0,base64.length-1)+"="}else if(len%3===1){base64=base64.substring(0,base64.length-2)+"=="}return base64};exports.decode=function(base64){var bufferLength=base64.length*.75,len=base64.length,i,p=0,encoded1,encoded2,encoded3,encoded4;if(base64[base64.length-1]==="="){bufferLength--;if(base64[base64.length-2]==="="){bufferLength--}}var arraybuffer=new ArrayBuffer(bufferLength),bytes=new Uint8Array(arraybuffer);for(i=0;i<len;i+=4){encoded1=chars.indexOf(base64[i]);encoded2=chars.indexOf(base64[i+1]);encoded3=chars.indexOf(base64[i+2]);encoded4=chars.indexOf(base64[i+3]);bytes[p++]=encoded1<<2|encoded2>>4;bytes[p++]=(encoded2&15)<<4|encoded3>>2;bytes[p++]=(encoded3&3)<<6|encoded4&63}return arraybuffer}})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")},{}],30:[function(_dereq_,module,exports){(function(global){var BlobBuilder=global.BlobBuilder||global.WebKitBlobBuilder||global.MSBlobBuilder||global.MozBlobBuilder;var blobSupported=function(){try{var b=new Blob(["hi"]);return b.size==2}catch(e){return false}}();var blobBuilderSupported=BlobBuilder&&BlobBuilder.prototype.append&&BlobBuilder.prototype.getBlob;function BlobBuilderConstructor(ary,options){options=options||{};var bb=new BlobBuilder;for(var i=0;i<ary.length;i++){bb.append(ary[i])}return options.type?bb.getBlob(options.type):bb.getBlob()}module.exports=function(){if(blobSupported){return global.Blob}else if(blobBuilderSupported){return BlobBuilderConstructor}else{return undefined}}()}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],31:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_("isarray");module.exports=hasBinary;function hasBinary(data){function _hasBinary(obj){if(!obj)return false;if(global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer||global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){return true}if(isArray(obj)){for(var i=0;i<obj.length;i++){if(_hasBinary(obj[i])){return true}}}else if(obj&&"object"==typeof obj){if(obj.toJSON){obj=obj.toJSON()}for(var key in obj){if(obj.hasOwnProperty(key)&&_hasBinary(obj[key])){return true}}}return false}return _hasBinary(data)}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{isarray:32}],32:[function(_dereq_,module,exports){module.exports=Array.isArray||function(arr){return Object.prototype.toString.call(arr)=="[object Array]"}},{}],33:[function(_dereq_,module,exports){(function(global){(function(root){var freeExports=typeof exports=="object"&&exports;var freeModule=typeof module=="object"&&module&&module.exports==freeExports&&module;var freeGlobal=typeof global=="object"&&global;if(freeGlobal.global===freeGlobal||freeGlobal.window===freeGlobal){root=freeGlobal}var stringFromCharCode=String.fromCharCode;function ucs2decode(string){var output=[];var counter=0;var length=string.length;var value;var extra;while(counter<length){value=string.charCodeAt(counter++);if(value>=55296&&value<=56319&&counter<length){extra=string.charCodeAt(counter++);if((extra&64512)==56320){output.push(((value&1023)<<10)+(extra&1023)+65536)}else{output.push(value);counter--}}else{output.push(value)}}return output}function ucs2encode(array){var length=array.length;var index=-1;var value;var output="";while(++index<length){value=array[index];if(value>65535){value-=65536;
    output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value)}return output}function createByte(codePoint,shift){return stringFromCharCode(codePoint>>shift&63|128)}function encodeCodePoint(codePoint){if((codePoint&4294967168)==0){return stringFromCharCode(codePoint)}var symbol="";if((codePoint&4294965248)==0){symbol=stringFromCharCode(codePoint>>6&31|192)}else if((codePoint&4294901760)==0){symbol=stringFromCharCode(codePoint>>12&15|224);symbol+=createByte(codePoint,6)}else if((codePoint&4292870144)==0){symbol=stringFromCharCode(codePoint>>18&7|240);symbol+=createByte(codePoint,12);symbol+=createByte(codePoint,6)}symbol+=stringFromCharCode(codePoint&63|128);return symbol}function utf8encode(string){var codePoints=ucs2decode(string);var length=codePoints.length;var index=-1;var codePoint;var byteString="";while(++index<length){codePoint=codePoints[index];byteString+=encodeCodePoint(codePoint)}return byteString}function readContinuationByte(){if(byteIndex>=byteCount){throw Error("Invalid byte index")}var continuationByte=byteArray[byteIndex]&255;byteIndex++;if((continuationByte&192)==128){return continuationByte&63}throw Error("Invalid continuation byte")}function decodeSymbol(){var byte1;var byte2;var byte3;var byte4;var codePoint;if(byteIndex>byteCount){throw Error("Invalid byte index")}if(byteIndex==byteCount){return false}byte1=byteArray[byteIndex]&255;byteIndex++;if((byte1&128)==0){return byte1}if((byte1&224)==192){var byte2=readContinuationByte();codePoint=(byte1&31)<<6|byte2;if(codePoint>=128){return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&240)==224){byte2=readContinuationByte();byte3=readContinuationByte();codePoint=(byte1&15)<<12|byte2<<6|byte3;if(codePoint>=2048){return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&248)==240){byte2=readContinuationByte();byte3=readContinuationByte();byte4=readContinuationByte();codePoint=(byte1&15)<<18|byte2<<12|byte3<<6|byte4;if(codePoint>=65536&&codePoint<=1114111){return codePoint}}throw Error("Invalid UTF-8 detected")}var byteArray;var byteCount;var byteIndex;function utf8decode(byteString){byteArray=ucs2decode(byteString);byteCount=byteArray.length;byteIndex=0;var codePoints=[];var tmp;while((tmp=decodeSymbol())!==false){codePoints.push(tmp)}return ucs2encode(codePoints)}var utf8={version:"2.0.0",encode:utf8encode,decode:utf8decode};if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){define(function(){return utf8})}else if(freeExports&&!freeExports.nodeType){if(freeModule){freeModule.exports=utf8}else{var object={};var hasOwnProperty=object.hasOwnProperty;for(var key in utf8){hasOwnProperty.call(utf8,key)&&(freeExports[key]=utf8[key])}}}else{root.utf8=utf8}})(this)}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],34:[function(_dereq_,module,exports){(function(global){var rvalidchars=/^[\],:{}\s]*$/;var rvalidescape=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;var rvalidtokens=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;var rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g;var rtrimLeft=/^\s+/;var rtrimRight=/\s+$/;module.exports=function parsejson(data){if("string"!=typeof data||!data){return null}data=data.replace(rtrimLeft,"").replace(rtrimRight,"");if(global.JSON&&JSON.parse){return JSON.parse(data)}if(rvalidchars.test(data.replace(rvalidescape,"@").replace(rvalidtokens,"]").replace(rvalidbraces,""))){return new Function("return "+data)()}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],35:[function(_dereq_,module,exports){exports.encode=function(obj){var str="";for(var i in obj){if(obj.hasOwnProperty(i)){if(str.length)str+="&";str+=encodeURIComponent(i)+"="+encodeURIComponent(obj[i])}}return str};exports.decode=function(qs){var qry={};var pairs=qs.split("&");for(var i=0,l=pairs.length;i<l;i++){var pair=pairs[i].split("=");qry[decodeURIComponent(pair[0])]=decodeURIComponent(pair[1])}return qry}},{}],36:[function(_dereq_,module,exports){var re=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;var parts=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];module.exports=function parseuri(str){var src=str,b=str.indexOf("["),e=str.indexOf("]");if(b!=-1&&e!=-1){str=str.substring(0,b)+str.substring(b,e).replace(/:/g,";")+str.substring(e,str.length)}var m=re.exec(str||""),uri={},i=14;while(i--){uri[parts[i]]=m[i]||""}if(b!=-1&&e!=-1){uri.source=src;uri.host=uri.host.substring(1,uri.host.length-1).replace(/;/g,":");uri.authority=uri.authority.replace("[","").replace("]","").replace(/;/g,":");uri.ipv6uri=true}return uri}},{}],37:[function(_dereq_,module,exports){var global=function(){return this}();var WebSocket=global.WebSocket||global.MozWebSocket;module.exports=WebSocket?ws:null;function ws(uri,protocols,opts){var instance;if(protocols){instance=new WebSocket(uri,protocols)}else{instance=new WebSocket(uri)}return instance}if(WebSocket)ws.prototype=WebSocket.prototype},{}],38:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_("isarray");module.exports=hasBinary;function hasBinary(data){function _hasBinary(obj){if(!obj)return false;if(global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer||global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){return true}if(isArray(obj)){for(var i=0;i<obj.length;i++){if(_hasBinary(obj[i])){return true}}}else if(obj&&"object"==typeof obj){if(obj.toJSON){obj=obj.toJSON()}for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key)&&_hasBinary(obj[key])){return true}}}return false}return _hasBinary(data)}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{isarray:39}],39:[function(_dereq_,module,exports){module.exports=_dereq_(32)},{}],40:[function(_dereq_,module,exports){var global=_dereq_("global");try{module.exports="XMLHttpRequest"in global&&"withCredentials"in new global.XMLHttpRequest}catch(err){module.exports=false}},{global:41}],41:[function(_dereq_,module,exports){module.exports=function(){return this}()},{}],42:[function(_dereq_,module,exports){var indexOf=[].indexOf;module.exports=function(arr,obj){if(indexOf)return arr.indexOf(obj);for(var i=0;i<arr.length;++i){if(arr[i]===obj)return i}return-1}},{}],43:[function(_dereq_,module,exports){var has=Object.prototype.hasOwnProperty;exports.keys=Object.keys||function(obj){var keys=[];for(var key in obj){if(has.call(obj,key)){keys.push(key)}}return keys};exports.values=function(obj){var vals=[];for(var key in obj){if(has.call(obj,key)){vals.push(obj[key])}}return vals};exports.merge=function(a,b){for(var key in b){if(has.call(b,key)){a[key]=b[key]}}return a};exports.length=function(obj){return exports.keys(obj).length};exports.isEmpty=function(obj){return 0==exports.length(obj)}},{}],44:[function(_dereq_,module,exports){var re=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;var parts=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];module.exports=function parseuri(str){var m=re.exec(str||""),uri={},i=14;while(i--){uri[parts[i]]=m[i]||""}return uri}},{}],45:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_("isarray");var isBuf=_dereq_("./is-buffer");exports.deconstructPacket=function(packet){var buffers=[];var packetData=packet.data;function _deconstructPacket(data){if(!data)return data;if(isBuf(data)){var placeholder={_placeholder:true,num:buffers.length};buffers.push(data);return placeholder}else if(isArray(data)){var newData=new Array(data.length);for(var i=0;i<data.length;i++){newData[i]=_deconstructPacket(data[i])}return newData}else if("object"==typeof data&&!(data instanceof Date)){var newData={};for(var key in data){newData[key]=_deconstructPacket(data[key])}return newData}return data}var pack=packet;pack.data=_deconstructPacket(packetData);pack.attachments=buffers.length;return{packet:pack,buffers:buffers}};exports.reconstructPacket=function(packet,buffers){var curPlaceHolder=0;function _reconstructPacket(data){if(data&&data._placeholder){var buf=buffers[data.num];return buf}else if(isArray(data)){for(var i=0;i<data.length;i++){data[i]=_reconstructPacket(data[i])}return data}else if(data&&"object"==typeof data){for(var key in data){data[key]=_reconstructPacket(data[key])}return data}return data}packet.data=_reconstructPacket(packet.data);packet.attachments=undefined;return packet};exports.removeBlobs=function(data,callback){function _removeBlobs(obj,curKey,containingObject){if(!obj)return obj;if(global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){pendingBlobs++;var fileReader=new FileReader;fileReader.onload=function(){if(containingObject){containingObject[curKey]=this.result}else{bloblessData=this.result}if(!--pendingBlobs){callback(bloblessData)}};fileReader.readAsArrayBuffer(obj)}else if(isArray(obj)){for(var i=0;i<obj.length;i++){_removeBlobs(obj[i],i,obj)}}else if(obj&&"object"==typeof obj&&!isBuf(obj)){for(var key in obj){_removeBlobs(obj[key],key,obj)}}}var pendingBlobs=0;var bloblessData=data;_removeBlobs(bloblessData);if(!pendingBlobs){callback(bloblessData)}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./is-buffer":47,isarray:48}],46:[function(_dereq_,module,exports){var debug=_dereq_("debug")("socket.io-parser");var json=_dereq_("json3");var isArray=_dereq_("isarray");var Emitter=_dereq_("component-emitter");var binary=_dereq_("./binary");var isBuf=_dereq_("./is-buffer");exports.protocol=4;exports.types=["CONNECT","DISCONNECT","EVENT","BINARY_EVENT","ACK","BINARY_ACK","ERROR"];exports.CONNECT=0;exports.DISCONNECT=1;exports.EVENT=2;exports.ACK=3;exports.ERROR=4;exports.BINARY_EVENT=5;exports.BINARY_ACK=6;exports.Encoder=Encoder;exports.Decoder=Decoder;function Encoder(){}Encoder.prototype.encode=function(obj,callback){debug("encoding packet %j",obj);if(exports.BINARY_EVENT==obj.type||exports.BINARY_ACK==obj.type){encodeAsBinary(obj,callback)}else{var encoding=encodeAsString(obj);callback([encoding])}};function encodeAsString(obj){var str="";var nsp=false;str+=obj.type;if(exports.BINARY_EVENT==obj.type||exports.BINARY_ACK==obj.type){str+=obj.attachments;str+="-"}if(obj.nsp&&"/"!=obj.nsp){nsp=true;str+=obj.nsp}if(null!=obj.id){if(nsp){str+=",";nsp=false}str+=obj.id}if(null!=obj.data){if(nsp)str+=",";str+=json.stringify(obj.data)}debug("encoded %j as %s",obj,str);return str}function encodeAsBinary(obj,callback){function writeEncoding(bloblessData){var deconstruction=binary.deconstructPacket(bloblessData);var pack=encodeAsString(deconstruction.packet);var buffers=deconstruction.buffers;buffers.unshift(pack);callback(buffers)}binary.removeBlobs(obj,writeEncoding)}function Decoder(){this.reconstructor=null}Emitter(Decoder.prototype);Decoder.prototype.add=function(obj){var packet;if("string"==typeof obj){packet=decodeString(obj);if(exports.BINARY_EVENT==packet.type||exports.BINARY_ACK==packet.type){this.reconstructor=new BinaryReconstructor(packet);if(this.reconstructor.reconPack.attachments===0){this.emit("decoded",packet)}}else{this.emit("decoded",packet)}}else if(isBuf(obj)||obj.base64){if(!this.reconstructor){throw new Error("got binary data when not reconstructing a packet")}else{packet=this.reconstructor.takeBinaryData(obj);if(packet){this.reconstructor=null;this.emit("decoded",packet)}}}else{throw new Error("Unknown type: "+obj)}};function decodeString(str){var p={};var i=0;p.type=Number(str.charAt(0));if(null==exports.types[p.type])return error();if(exports.BINARY_EVENT==p.type||exports.BINARY_ACK==p.type){var buf="";while(str.charAt(++i)!="-"){buf+=str.charAt(i);if(i==str.length)break}if(buf!=Number(buf)||str.charAt(i)!="-"){throw new Error("Illegal attachments")}p.attachments=Number(buf)}if("/"==str.charAt(i+1)){p.nsp="";while(++i){var c=str.charAt(i);if(","==c)break;p.nsp+=c;if(i==str.length)break}}else{p.nsp="/"}var next=str.charAt(i+1);if(""!==next&&Number(next)==next){p.id="";while(++i){var c=str.charAt(i);if(null==c||Number(c)!=c){--i;break}p.id+=str.charAt(i);if(i==str.length)break}p.id=Number(p.id)}if(str.charAt(++i)){try{p.data=json.parse(str.substr(i))}catch(e){return error()}}debug("decoded %s as %j",str,p);return p}Decoder.prototype.destroy=function(){if(this.reconstructor){this.reconstructor.finishedReconstruction()}};function BinaryReconstructor(packet){this.reconPack=packet;this.buffers=[]}BinaryReconstructor.prototype.takeBinaryData=function(binData){this.buffers.push(binData);if(this.buffers.length==this.reconPack.attachments){var packet=binary.reconstructPacket(this.reconPack,this.buffers);this.finishedReconstruction();return packet}return null};BinaryReconstructor.prototype.finishedReconstruction=function(){this.reconPack=null;this.buffers=[]};function error(data){return{type:exports.ERROR,data:"parser error"}}},{"./binary":45,"./is-buffer":47,"component-emitter":9,debug:10,isarray:48,json3:49}],47:[function(_dereq_,module,exports){(function(global){module.exports=isBuf;function isBuf(obj){return global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],48:[function(_dereq_,module,exports){module.exports=_dereq_(32)},{}],49:[function(_dereq_,module,exports){(function(window){var getClass={}.toString,isProperty,forEach,undef;var isLoader=typeof define==="function"&&define.amd;var nativeJSON=typeof JSON=="object"&&JSON;var JSON3=typeof exports=="object"&&exports&&!exports.nodeType&&exports;if(JSON3&&nativeJSON){JSON3.stringify=nativeJSON.stringify;JSON3.parse=nativeJSON.parse}else{JSON3=window.JSON=nativeJSON||{}}var isExtended=new Date(-0xc782b5b800cec);try{isExtended=isExtended.getUTCFullYear()==-109252&&isExtended.getUTCMonth()===0&&isExtended.getUTCDate()===1&&isExtended.getUTCHours()==10&&isExtended.getUTCMinutes()==37&&isExtended.getUTCSeconds()==6&&isExtended.getUTCMilliseconds()==708}catch(exception){}function has(name){if(has[name]!==undef){return has[name]}var isSupported;if(name=="bug-string-char-index"){isSupported="a"[0]!="a"}else if(name=="json"){isSupported=has("json-stringify")&&has("json-parse")}else{var value,serialized='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if(name=="json-stringify"){var stringify=JSON3.stringify,stringifySupported=typeof stringify=="function"&&isExtended;if(stringifySupported){(value=function(){return 1}).toJSON=value;try{stringifySupported=stringify(0)==="0"&&stringify(new Number)==="0"&&stringify(new String)=='""'&&stringify(getClass)===undef&&stringify(undef)===undef&&stringify()===undef&&stringify(value)==="1"&&stringify([value])=="[1]"&&stringify([undef])=="[null]"&&stringify(null)=="null"&&stringify([undef,getClass,null])=="[null,null,null]"&&stringify({a:[value,true,false,null,"\x00\b\n\f\r    "]})==serialized&&stringify(null,value)==="1"&&stringify([1,2],null,1)=="[\n 1,\n 2\n]"&&stringify(new Date(-864e13))=='"-271821-04-20T00:00:00.000Z"'&&stringify(new Date(864e13))=='"+275760-09-13T00:00:00.000Z"'&&stringify(new Date(-621987552e5))=='"-000001-01-01T00:00:00.000Z"'&&stringify(new Date(-1))=='"1969-12-31T23:59:59.999Z"'}catch(exception){stringifySupported=false}}isSupported=stringifySupported}if(name=="json-parse"){var parse=JSON3.parse;if(typeof parse=="function"){try{if(parse("0")===0&&!parse(false)){value=parse(serialized);var parseSupported=value["a"].length==5&&value["a"][0]===1;if(parseSupported){try{parseSupported=!parse('"    "')}catch(exception){}if(parseSupported){try{parseSupported=parse("01")!==1}catch(exception){}}if(parseSupported){try{parseSupported=parse("1.")!==1}catch(exception){}}}}}catch(exception){parseSupported=false}}isSupported=parseSupported}}return has[name]=!!isSupported}if(!has("json")){var functionClass="[object Function]";var dateClass="[object Date]";var numberClass="[object Number]";var stringClass="[object String]";var arrayClass="[object Array]";var booleanClass="[object Boolean]";var charIndexBuggy=has("bug-string-char-index");if(!isExtended){var floor=Math.floor;var Months=[0,31,59,90,120,151,181,212,243,273,304,334];var getDay=function(year,month){return Months[month]+365*(year-1970)+floor((year-1969+(month=+(month>1)))/4)-floor((year-1901+month)/100)+floor((year-1601+month)/400)}}if(!(isProperty={}.hasOwnProperty)){isProperty=function(property){var members={},constructor;if((members.__proto__=null,members.__proto__={toString:1},members).toString!=getClass){isProperty=function(property){var original=this.__proto__,result=property in(this.__proto__=null,this);this.__proto__=original;return result}}else{constructor=members.constructor;isProperty=function(property){var parent=(this.constructor||constructor).prototype;return property in this&&!(property in parent&&this[property]===parent[property])}}members=null;return isProperty.call(this,property)}}var PrimitiveTypes={"boolean":1,number:1,string:1,undefined:1};var isHostType=function(object,property){var type=typeof object[property];return type=="object"?!!object[property]:!PrimitiveTypes[type]};forEach=function(object,callback){var size=0,Properties,members,property;(Properties=function(){this.valueOf=0}).prototype.valueOf=0;members=new Properties;for(property in members){if(isProperty.call(members,property)){size++}}Properties=members=null;if(!size){members=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"];forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,length;var hasProperty=!isFunction&&typeof object.constructor!="function"&&isHostType(object,"hasOwnProperty")?object.hasOwnProperty:isProperty;for(property in object){if(!(isFunction&&property=="prototype")&&hasProperty.call(object,property)){callback(property)}}for(length=members.length;property=members[--length];hasProperty.call(object,property)&&callback(property));}}else if(size==2){forEach=function(object,callback){var members={},isFunction=getClass.call(object)==functionClass,property;for(property in object){if(!(isFunction&&property=="prototype")&&!isProperty.call(members,property)&&(members[property]=1)&&isProperty.call(object,property)){callback(property)}}}}else{forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,isConstructor;for(property in object){if(!(isFunction&&property=="prototype")&&isProperty.call(object,property)&&!(isConstructor=property==="constructor")){callback(property)}}if(isConstructor||isProperty.call(object,property="constructor")){callback(property)}}}return forEach(object,callback)};if(!has("json-stringify")){var Escapes={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"};var leadingZeroes="000000";var toPaddedString=function(width,value){return(leadingZeroes+(value||0)).slice(-width)};var unicodePrefix="\\u00";var quote=function(value){var result='"',index=0,length=value.length,isLarge=length>10&&charIndexBuggy,symbols;if(isLarge){symbols=value.split("")}for(;index<length;index++){var charCode=value.charCodeAt(index);switch(charCode){case 8:case 9:case 10:case 12:case 13:case 34:case 92:result+=Escapes[charCode];break;default:if(charCode<32){result+=unicodePrefix+toPaddedString(2,charCode.toString(16));break}result+=isLarge?symbols[index]:charIndexBuggy?value.charAt(index):value[index]}}return result+'"'};var serialize=function(property,object,callback,properties,whitespace,indentation,stack){var value,className,year,month,date,time,hours,minutes,seconds,milliseconds,results,element,index,length,prefix,result;try{value=object[property]}catch(exception){}if(typeof value=="object"&&value){className=getClass.call(value);if(className==dateClass&&!isProperty.call(value,"toJSON")){if(value>-1/0&&value<1/0){if(getDay){date=floor(value/864e5);for(year=floor(date/365.2425)+1970-1;getDay(year+1,0)<=date;year++);for(month=floor((date-getDay(year,0))/30.42);getDay(year,month+1)<=date;month++);date=1+date-getDay(year,month);time=(value%864e5+864e5)%864e5;hours=floor(time/36e5)%24;minutes=floor(time/6e4)%60;seconds=floor(time/1e3)%60;milliseconds=time%1e3}else{year=value.getUTCFullYear();month=value.getUTCMonth();date=value.getUTCDate();hours=value.getUTCHours();minutes=value.getUTCMinutes();seconds=value.getUTCSeconds();milliseconds=value.getUTCMilliseconds()}value=(year<=0||year>=1e4?(year<0?"-":"+")+toPaddedString(6,year<0?-year:year):toPaddedString(4,year))+"-"+toPaddedString(2,month+1)+"-"+toPaddedString(2,date)+"T"+toPaddedString(2,hours)+":"+toPaddedString(2,minutes)+":"+toPaddedString(2,seconds)+"."+toPaddedString(3,milliseconds)+"Z"}else{value=null}}else if(typeof value.toJSON=="function"&&(className!=numberClass&&className!=stringClass&&className!=arrayClass||isProperty.call(value,"toJSON"))){value=value.toJSON(property)}}if(callback){value=callback.call(object,property,value)}if(value===null){return"null"}className=getClass.call(value);if(className==booleanClass){return""+value}else if(className==numberClass){return value>-1/0&&value<1/0?""+value:"null"}else if(className==stringClass){return quote(""+value)}if(typeof value=="object"){for(length=stack.length;length--;){if(stack[length]===value){throw TypeError()}}stack.push(value);results=[];prefix=indentation;indentation+=whitespace;if(className==arrayClass){for(index=0,length=value.length;index<length;index++){element=serialize(index,value,callback,properties,whitespace,indentation,stack);results.push(element===undef?"null":element)}result=results.length?whitespace?"[\n"+indentation+results.join(",\n"+indentation)+"\n"+prefix+"]":"["+results.join(",")+"]":"[]"}else{forEach(properties||value,function(property){var element=serialize(property,value,callback,properties,whitespace,indentation,stack);if(element!==undef){results.push(quote(property)+":"+(whitespace?" ":"")+element)}});result=results.length?whitespace?"{\n"+indentation+results.join(",\n"+indentation)+"\n"+prefix+"}":"{"+results.join(",")+"}":"{}"}stack.pop();return result}};JSON3.stringify=function(source,filter,width){var whitespace,callback,properties,className;if(typeof filter=="function"||typeof filter=="object"&&filter){if((className=getClass.call(filter))==functionClass){callback=filter}else if(className==arrayClass){properties={};for(var index=0,length=filter.length,value;index<length;value=filter[index++],(className=getClass.call(value),className==stringClass||className==numberClass)&&(properties[value]=1));}}if(width){if((className=getClass.call(width))==numberClass){if((width-=width%1)>0){for(whitespace="",width>10&&(width=10);whitespace.length<width;whitespace+=" ");}}else if(className==stringClass){whitespace=width.length<=10?width:width.slice(0,10)}}return serialize("",(value={},value[""]=source,value),callback,properties,whitespace,"",[])}}if(!has("json-parse")){var fromCharCode=String.fromCharCode;var Unescapes={92:"\\",34:'"',47:"/",98:"\b",116:"    ",110:"\n",102:"\f",114:"\r"};var Index,Source;var abort=function(){Index=Source=null;throw SyntaxError()};var lex=function(){var source=Source,length=source.length,value,begin,position,isSigned,charCode;while(Index<length){charCode=source.charCodeAt(Index);switch(charCode){case 9:case 10:case 13:case 32:Index++;break;case 123:case 125:case 91:case 93:case 58:case 44:value=charIndexBuggy?source.charAt(Index):source[Index];Index++;return value;case 34:for(value="@",Index++;Index<length;){charCode=source.charCodeAt(Index);if(charCode<32){abort()}else if(charCode==92){charCode=source.charCodeAt(++Index);switch(charCode){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:value+=Unescapes[charCode];Index++;break;case 117:begin=++Index;for(position=Index+4;Index<position;Index++){charCode=source.charCodeAt(Index);if(!(charCode>=48&&charCode<=57||charCode>=97&&charCode<=102||charCode>=65&&charCode<=70)){abort()}}value+=fromCharCode("0x"+source.slice(begin,Index));break;default:abort()}}else{if(charCode==34){break}charCode=source.charCodeAt(Index);begin=Index;while(charCode>=32&&charCode!=92&&charCode!=34){charCode=source.charCodeAt(++Index)}value+=source.slice(begin,Index)}}if(source.charCodeAt(Index)==34){Index++;return value}abort();default:begin=Index;if(charCode==45){isSigned=true;charCode=source.charCodeAt(++Index)}if(charCode>=48&&charCode<=57){if(charCode==48&&(charCode=source.charCodeAt(Index+1),charCode>=48&&charCode<=57)){abort()}isSigned=false;for(;Index<length&&(charCode=source.charCodeAt(Index),charCode>=48&&charCode<=57);Index++);if(source.charCodeAt(Index)==46){position=++Index;for(;position<length&&(charCode=source.charCodeAt(position),charCode>=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}charCode=source.charCodeAt(Index);if(charCode==101||charCode==69){charCode=source.charCodeAt(++Index);if(charCode==43||charCode==45){Index++}for(position=Index;position<length&&(charCode=source.charCodeAt(position),charCode>=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}return+source.slice(begin,Index)}if(isSigned){abort()}if(source.slice(Index,Index+4)=="true"){Index+=4;return true}else if(source.slice(Index,Index+5)=="false"){Index+=5;return false}else if(source.slice(Index,Index+4)=="null"){Index+=4;return null}abort()}}return"$"};var get=function(value){var results,hasMembers;if(value=="$"){abort()}if(typeof value=="string"){if((charIndexBuggy?value.charAt(0):value[0])=="@"){return value.slice(1)}if(value=="["){results=[];for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="]"){break}if(hasMembers){if(value==","){value=lex();if(value=="]"){abort()}}else{abort()}}if(value==","){abort()}results.push(get(value))}return results}else if(value=="{"){results={};for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="}"){break}if(hasMembers){if(value==","){value=lex();if(value=="}"){abort()}}else{abort()}}if(value==","||typeof value!="string"||(charIndexBuggy?value.charAt(0):value[0])!="@"||lex()!=":"){abort()}results[value.slice(1)]=get(lex())}return results}abort()}return value};var update=function(source,property,callback){var element=walk(source,property,callback);if(element===undef){delete source[property]}else{source[property]=element}};var walk=function(source,property,callback){var value=source[property],length;if(typeof value=="object"&&value){if(getClass.call(value)==arrayClass){for(length=value.length;length--;){update(value,length,callback)}}else{forEach(value,function(property){update(value,property,callback)})}}return callback.call(source,property,value)};JSON3.parse=function(source,callback){var result,value;Index=0;Source=""+source;result=get(lex());if(lex()!="$"){abort()}Index=Source=null;return callback&&getClass.call(callback)==functionClass?walk((value={},value[""]=result,value),"",callback):result}}}if(isLoader){define(function(){return JSON3})}})(this)},{}],50:[function(_dereq_,module,exports){module.exports=toArray;function toArray(list,index){var array=[];index=index||0;for(var i=index||0;i<list.length;i++){array[i-index]=list[i]}return array}},{}]},{},[1])(1)});
var gaf = gaf || {};
gaf.COMPRESSION_NONE = 0x00474146;
gaf.COMPRESSION_ZIP = 0x00474143;
gaf.IDNONE = 0xffffffff;
gaf.FIRST_FRAME_INDEX = 0;
gaf.EFFECT_DROP_SHADOW = 0;
gaf.EFFECT_BLUR = 1;
gaf.EFFECT_GLOW = 2;
gaf.EFFECT_COLOR_MATRIX = 6;
gaf.ACTION_STOP = 0;
gaf.ACTION_PLAY = 1;
gaf.ACTION_GO_TO_AND_STOP = 2;
gaf.ACTION_GO_TO_AND_PLAY = 3;
gaf.ACTION_DISPATCH_EVENT = 4;
gaf.PI_FRAME = 0;
gaf.PI_EVENT_TYPE = 0;
gaf.TYPE_TEXTURE = 0;
gaf.TYPE_TEXT_FIELD = 1;
gaf.TYPE_TIME_LINE = 2;
gaf.UNIFORM_BLUR_TEXEL_OFFSET = "u_step";
gaf.UNIFORM_GLOW_TEXEL_OFFSET = "u_step";
gaf.UNIFORM_GLOW_COLOR = "u_glowColor";
gaf.UNIFORM_ALPHA_TINT_MULT = "colorTransformMult";
gaf.UNIFORM_ALPHA_TINT_OFFSET = "colorTransformOffsets";
gaf.UNIFORM_ALPHA_COLOR_MATRIX_BODY = "colorMatrix";
gaf.UNIFORM_ALPHA_COLOR_MATRIX_APPENDIX = "colorMatrix2";
var gaf = gaf || {};
gaf._tmp = gaf._tmp || {};
gaf._initialized = false;
gaf.CCGAFLoader = function()
{
    this.load = function(realUrl, url, item, cb)
    {
        if(!gaf._initialized)
        {
            gaf._setup();
        }
        var loader = new gaf.Loader();
        loader.LoadFile(realUrl, function(data){cb(null, data)});
    };
};
gaf._setup = function()
{
    gaf._setupShaders();
    gaf._initialized = true;
};
cc.loader.register('.gaf', new gaf.CCGAFLoader());
gaf.CGAffineTransformCocosFormatFromFlashFormat = function(transform)
{
    var t = {};
    t.a = transform.a;
    t.b = -transform.b;
    t.c = -transform.c;
    t.d = transform.d;
    t.tx = transform.tx;
    t.ty = -transform.ty;
    return t;
};
gaf._AssetPreload = function()
{
    this["0"] = this.End;
    this["1"] = this.Atlases;
    this["2"] = this.AnimationMasks;
    this["3"] = this.AnimationObjects;
    this["4"] = this.AnimationFrames;
    this["5"] = this.NamedParts;
    this["6"] = this.Sequences;
    this["7"] = this.TextFields;
    this["8"] = this.Atlases;
    this["9"] = this.Stage;
    this["10"] = this.AnimationObjects;
    this["11"] = this.AnimationMasks;
    this["12"] = this.AnimationFrames;
    this["13"] = this.TimeLine;
};
gaf._AssetPreload.prototype.End = function(asset, content, timeLine){
    if(timeLine)
    {
        timeLine.getFps = function()
        {
            return asset.getSceneFps();
        };
    }
};
gaf._AssetPreload.prototype.Tag = function(asset, tag, timeLine)
{
    (this[tag.tagId]).call(this, asset, tag.content, timeLine);
};
gaf._AssetPreload.prototype.Tags = function(asset, tags, timeLine)
{
    var self = this;
    tags.forEach(function(tag)
    {
        self.Tag(asset, tag, timeLine);
    });
};
gaf._AssetPreload.prototype.AtlasCreateFrames = function(elements, asset, spriteFrames)
{
    elements.forEach(function (item) {
        var texture = asset._atlases[item.atlasId];
        var rect = cc.rect(item.origin.x, item.origin.y, item.size.x, item.size.y);
        var frame = new cc.SpriteFrame(texture, rect);
        frame._gafAnchor =
        {
            x: (0 - (0 - (item.pivot.x / item.size.x))),
            y: (0 + (1 - (item.pivot.y / item.size.y)))
        };
        spriteFrames[item.elementAtlasId] = frame;
    });
};
gaf._AssetPreload.prototype.Atlases = function(asset, content, timeLine)
{
    var spriteFrames = asset._atlasScales[content.scale] = asset._atlasScales[content.scale] || [];
    var csf = cc.Director._getInstance().getContentScaleFactor();
    content.atlases.forEach(function(item)
    {
        var atlasId = item.id;
        var finalizeLoading = function()
        {
            gaf._AssetPreload.AtlasCreateFrames(content.elements, asset, spriteFrames);
        };
        var atlasPath = "";
        item.sources.forEach(function(atlasSource)
        {
            if(atlasSource.csf === csf)
            {
                atlasPath = atlasSource.source;
            }
        });
        cc.assert(atlasPath, "GAF Error. Texture for current CSF not found. Reconvert animation with correct parameters.");
        if(asset._textureLoadDelegate)
        {
            atlasPath = asset._textureLoadDelegate(atlasPath);
        }
        var loaded = false;
        var paths = asset._getSearchPaths(atlasPath);
        for(var i = 0, len = paths.length; i < len; ++i){
            var path = paths[i];
            var atlas = cc.textureCache.getTextureForKey(path);
            if(atlas && atlas.isLoaded())
            {
                atlas.handleLoadedTexture(true);
                loaded = true;
                asset._atlases[atlasId] = atlas;
                finalizeLoading();
                break;
            }
        }
        if(!loaded)
        {
            var success = function (atlas) {
                atlas.handleLoadedTexture(true);
                asset._onAtlasLoaded(atlasId, atlas);
            };
            var fail = function () {
                cc.log("GAF Error. Couldn't find `" + atlasPath + "` required by `" + asset.getGAFFileName() + "`");
            };
            if(!asset._atlasesToLoad.hasOwnProperty(atlasId))
            {
                gaf._AtlasLoader.loadArray(paths, success, fail);
                asset._atlasesToLoad[atlasId] = {};
            }
            asset._onLoadTasks.push(finalizeLoading);
        }
    });
};
gaf._AssetPreload.prototype.AnimationObjects = function(asset, content, timeLine)
{
    content.forEach(function(item)
    {
        item.type = (item.type === undefined) ? gaf.TYPE_TEXTURE : item.type;
        timeLine._objects.push(item.objectId);
        asset._objects[item.objectId] = item;
    });
};
gaf._AssetPreload.prototype.convertTint = function(mat, alpha)
{
    if(!mat)
        return null;
    return {
        mult:
        {
            r: mat.redMultiplier * 255,
            g: mat.greenMultiplier * 255,
            b: mat.blueMultiplier * 255,
            a: alpha * 255
        },
        offset:
        {
            r: mat.redOffset * 255,
            g: mat.greenOffset * 255,
            b: mat.blueOffset * 255,
            a: mat.alphaOffset * 255
        }
    };
};
gaf._AssetPreload.prototype.convertState = function(state)
{
    return {
        hasColorTransform: state.hasColorTransform,
        hasMask: state.hasMask,
        hasEffect: state.hasEffect,
        objectIdRef: state.objectIdRef,
        depth: state.depth,
        alpha: state.alpha * 255,
        matrix: gaf.CGAffineTransformCocosFormatFromFlashFormat(state.matrix),
        colorTransform: this.convertTint(state.colorTransform, state.alpha),
        effect: state.effect,
        maskObjectIdRef: state.maskObjectIdRef
    };
};
gaf._AssetPreload.prototype.AnimationFrames = function(asset, content, timeLine)
{
    var self = this;
    cc.assert(timeLine, "Error. Time Line should not be null.");
    var statesForId = {};
    var frames = [];
    var lastFrame = {};
    for(var i = 0, len = content.length; i < len; ++i)
    {
        var frame = content[i];
        if(frame.state)
        {
            frame.state.forEach(function (state)
            {
                if (state.alpha !== 0)
                {
                    statesForId[state.objectIdRef] = self.convertState(state);
                }
                else
                {
                    statesForId[state.objectIdRef] = null;
                }
            });
        }
        var stateArray = [];
        for(var obj in statesForId){ if(statesForId.hasOwnProperty(obj) && statesForId[obj])
        {
            stateArray.push(statesForId[obj]);
        }}
        lastFrame = frame;
        frames[frame.frame - 1] = {states: stateArray, actions: frame.actions || null};
    }
    timeLine.getFrames = function(){return frames};
};
gaf._AssetPreload.prototype.NamedParts = function(asset, content, timeLine)
{
    var parts = {};
    content.forEach(function(item)
    {
        parts[item.name] = item.objectId;
    });
    timeLine.getNamedParts = function(){return parts};
};
gaf._AssetPreload.prototype.Sequences = function(asset, content, timeLine)
{
    var sequences = {};
    content.forEach(function(item){
        sequences[item.id] = {start: item.start - 1, end: item.end};
    });
    timeLine.getSequences = function(){return sequences};
};
gaf._AssetPreload.prototype.TextFields = function(asset, content, timeLine)
{
    debugger;
};
gaf._AssetPreload.prototype.Stage = function(asset, content, timeLine)
{
    asset._sceneFps = content.fps;
    asset._sceneColor = content.color;
    asset._sceneWidth = content.width;
    asset._sceneHeight = content.height;
};
gaf._AssetPreload.prototype.AnimationMasks = function(asset, content, timeLine)
{
    content.forEach(function(item)
    {
        item.type = (item.type === undefined) ? gaf.TYPE_TEXTURE : item.type;
        timeLine._objects.push(item.objectId);
        asset._masks[item.objectId] = item;
    });
};
gaf._AssetPreload.prototype.TimeLine = function(asset, content, timeLine)
{
    var result = new gaf._TimeLineProto(asset, content.animationFrameCount, content.boundingBox, content.pivotPoint, content.id, content.linkageName);
    asset._pushTimeLine(result);
    this.Tags(asset, content.tags, result);
};
gaf._AssetPreload = new gaf._AssetPreload();
var gaf = gaf || {};
gaf.Asset = cc.Class.extend
({
    _className: "GAFAsset",
    _header: null,
    _timeLines: null,
    _textFields: null,
    _protos: null,
    _objects: null,
    _masks: null,
    _rootTimeLine: null,
    _textureLoadDelegate: null,
    _sceneFps: 60,
    _sceneWidth: 0,
    _sceneHeight: 0,
    _sceneColor: 0,
    _gafData: null,
    _desiredAtlasScale: 1,
    _usedAtlasScale: 0,
    _atlases: null,
    _onLoadTasks: null,
    _atlasScales: null,
    _textureLoaded: false,
    _atlasesToLoad: null,
    _gafName: null,
    initWithGAFFile: function (filePath, textureLoadDelegate) {
        var self = this;
        this._textureLoadDelegate = textureLoadDelegate;
        this._gafName = filePath;
        var gafData = cc.loader.getRes(filePath);
        if(!gafData)
        {
            cc.loader.load(filePath, function(err, data){
                if(!err)
                {
                    self._init(data[0]);
                }
            });
        }
        else {
            return this._init(gafData);
        }
        return false;
    },
    initWithGAFBundle: function (zipFilePath, entryFile, delegate)
    {
        cc.assert(false, "initWithGAFBundle is not yet implemented");
        return false;
    },
    setRootTimelineWithName: function (name)
    {
        for(var i = 0, end = this._timeLines.length; i < end; ++i)
        {
            var object = this._timeLines[i];
            if (object && object.getLinkageName() === name)
            {
                this._setRootTimeline(object);
                return;
            }
        }
    },
    isAssetVersionPlayable: function ()
    {
        return true;
    },
    desiredAtlasScale : function(){
        return this._desiredAtlasScale;
    },
    setDesiredAtlasScale : function(desiredAtlasScale){
        this._desiredAtlasScale = desiredAtlasScale;
        for(var currentScale in this._atlasScales)if(this._atlasScales.hasOwnProperty(currentScale))
        {
            if( (this._usedAtlasScale === 0) ||
                (Math.abs(this._usedAtlasScale - desiredAtlasScale) > Math.abs(currentScale - desiredAtlasScale) ))
            {
                this._usedAtlasScale = currentScale;
            }
        }
    },
    createObject: function ()
    {
        return this._instantiateGaf(this._gafData);
    },
    createObjectAndRun: function (looped)
    {
        cc.assert(arguments.length === 1, "GAFAsset::createObjectAndRun should have one param");
        var object = this._instantiateGaf(this._gafData);
        object.setLooped(looped, true);
        object.start();
        return object;
    },
    setTextureLoadDelegate: function (delegate)
    {
        debugger;
    },
    getSceneFps: function ()
    {
        return this._sceneFps;
    },
    getSceneWidth: function ()
    {
        debugger;
    },
    getSceneHeight: function ()
    {
        debugger;
    },
    getSceneColor: function ()
    {
        debugger;
    },
    setSceneFps: function (fps)
    {
        this._sceneFps = fps;
    },
    setSceneWidth: function (width)
    {
        debugger;
    },
    setSceneHeight: function (height)
    {
        debugger;
    },
    setSceneColor: function (color4B)
    {
        debugger;
    },
    getHeader: function ()
    {
        return this._header;
    },
    getGAFFileName: function()
    {
        return this._gafName;
    },
    ctor : function()
    {
        this._header = {};
        this._timeLines = [];
        this._textFields = [];
        this._objects = [];
        this._masks = [];
        this._protos = [];
        this._atlases = {};
        this._onLoadTasks = [];
        this._atlasScales = {};
        this._atlasesToLoad = {};
        if(arguments.length > 0)
            this.initWithGAFFile.apply(this, arguments);
    },
    _getProtos: function()
    {
        return this._protos;
    },
    _setRootTimeline : function(timeLine)
    {
        this._rootTimeLine = timeLine;
        this._header.pivot = timeLine.getPivot();
        this._header.frameSize = timeLine.getRect();
    },
    _setHeader : function (gafHeader)
    {
        for(var prop in gafHeader)
        {
            if(gafHeader.hasOwnProperty(prop))
            {
                this._header[prop] = gafHeader[prop];
            }
        }
    },
    _getMajorVerison : function()
    {
        return this._header.versionMajor;
    },
    _init : function(gafData)
    {
        var self = this;
        this._gafData = gafData;
        this._setHeader(gafData.header);
        this._timeLinesToLink = [];
        if(this._getMajorVerison() < 4)
        {
            this._pushTimeLine(new gaf._TimeLineProto(this, this._header.framesCount, this._header.frameSize, this._header.pivot));
        }
        gaf._AssetPreload.Tags(this, gafData.tags, this._rootTimeLine);
        this._objects.forEach(function(item)
        {
            switch(item.type)
            {
                case gaf.TYPE_TEXTURE:
                    if(!self._protos[item.objectId])
                    {
                        self._protos[item.objectId] = new gaf._SpriteProto(self, self._atlasScales, item.elementAtlasIdRef);
                    }
                    break;
                case gaf.TYPE_TIME_LINE:
                    self._protos[item.objectId] = self._timeLines[item.elementAtlasIdRef];
                    break;
                case gaf.TYPE_TEXT_FIELD:
                    self._protos[item.objectId] = self._textFields[item.elementAtlasIdRef];
                    break;
                default:
                    cc.log("Unknown object type: " + item.type);
                    break;
            }
        });
        this._masks.forEach(function(item)
        {
            if(self._protos[item.objectId])
            {
                return;
            }
            var proto = null;
            switch(item.type)
            {
                case gaf.TYPE_TEXTURE:
                    proto = new gaf._SpriteProto(self, self._atlasScales, item.elementAtlasIdRef);
                    break;
                case gaf.TYPE_TIME_LINE:
                    proto = self._timeLines[item.elementAtlasIdRef];
                    break;
                case gaf.TYPE_TEXT_FIELD:
                    proto = self._textFields[item.elementAtlasIdRef];
                    break;
            }
            self._protos[item.objectId] = new gaf._MaskProto(self, proto, item.elementAtlasIdRef);
        });
        this.setDesiredAtlasScale(this._desiredAtlasScale);
        if(Object.keys(this._atlasesToLoad).length === 0)
        {
            this._textureLoaded = true;
            this.dispatchEvent("load");
        }
    },
    _pushTimeLine : function(timeLine)
    {
        this._timeLines[timeLine.getId()] = timeLine;
        if(timeLine.getId() === 0)
        {
            this._setRootTimeline(timeLine);
        }
    },
    _instantiateGaf : function()
    {
        var root = null;
        root = this._rootTimeLine._gafConstruct();
        return root;
    },
    _onAtlasLoaded : function(id, atlas)
    {
        this._atlases[id] = atlas;
        delete this._atlasesToLoad[id];
        if(Object.keys(this._atlasesToLoad).length === 0)
        {
            this._onLoadTasks.forEach(function(fn){fn()});
            this._onLoadTasks.length = 0;
            this._textureLoaded = true;
            this.dispatchEvent("load");
        }
    },
    isLoaded : function()
    {
        return this._textureLoaded;
    },
    _getSearchPaths: function(imageUrl)
    {
        var extendedPath = this.getGAFFileName().split('/');
        extendedPath[extendedPath.length-1] = imageUrl;
        var alternativeUrl = extendedPath.join('/');
        return [imageUrl, alternativeUrl];
    }
});
gaf.Asset.create = function (gafFilePath, delegate)
{
    return new gaf.Asset(gafFilePath, delegate);
};
gaf.Asset.createWithBundle = function (zipFilePath, entryFile, delegate)
{
    var asset = new gaf.Asset();
    asset.initWithGAFBundle(zipFilePath, entryFile, delegate);
    return asset;
};
cc.EventHelper.prototype.apply(gaf.Asset.prototype);
var gaf = gaf || {};
gaf._stateHasCtx = function(state)
{
    if( state.hasColorTransform &&
       (state.colorTransform.offset.r > 0 ||
        state.colorTransform.offset.g > 0 ||
        state.colorTransform.offset.b > 0 ||
        state.colorTransform.offset.a > 0)
    )
    {
        return true;
    }
    if(state.hasEffect)
    {
        for(var i = 0, total = state.effect.length; i < total; ++i)
        {
            if(state.effect[i].type === gaf.EFFECT_COLOR_MATRIX)
                return true;
        }
    }
    return false;
};
gaf.Object = cc.Node.extend
({
    _asset : null,
    _className : "GAFObject",
    _id : gaf.IDNONE,
    _gafproto : null,
    _parentTimeLine : null,
    _lastVisibleInFrame : 0,
    _filterStack : null,
    _cascadeColorMult : null,
    _cascadeColorOffset : null,
    _needsCtx : false,
    _usedAtlasScale: 1,
    ctor: function(scale)
    {
        if(arguments.length == 1)
        {
            this._usedAtlasScale = scale;
        }
        this._super();
        this._cascadeColorMult = cc.color(255, 255, 255, 255);
        this._cascadeColorOffset = cc.color(0, 0, 0, 0);
        this._filterStack = [];
    },
    setAnimationStartedNextLoopDelegate : function (delegate) {},
    setAnimationFinishedPlayDelegate : function (delegate) {},
    setLooped : function (looped) {},
    getBoundingBoxForCurrentFrame : function () {return null;},
    setFps : function (fps) {},
    getObjectByName : function (name) {return null;},
    clearSequence : function () {},
    getIsAnimationRunning : function () {return false;},
    getSequences : function(){return [];},
    gotoAndStop : function (value) {},
    getStartFrame : function (frameLabel) {return gaf.IDNONE;},
    setFramePlayedDelegate : function (delegate) {},
    getCurrentFrameIndex : function () {
        return gaf.IDNONE;
    },
    getTotalFrameCount : function () {return 0;},
    start : function () {},
    stop : function () {},
    isVisibleInCurrentFrame : function ()
    {
        return !(this._parentTimeLine && ((this._parentTimeLine.getCurrentFrameIndex() + 1) != this._lastVisibleInFrame));
    },
    isDone : function () {return true;},
    playSequence : function (name, looped, resume) {return false;},
    isReversed : function () {return false;},
    setSequenceDelegate : function (delegate) {},
    setFrame : function (index) {return false;},
    setControlDelegate : function (func) {},
    getEndFrame : function (frameLabel) {return gaf.IDNONE;},
    pauseAnimation : function () {},
    gotoAndPlay : function (value) {},
    isLooped : function () {return false;},
    resumeAnimation : function () {},
    setReversed : function (reversed) {},
    hasSequences : function () {return false;},
    getFps : function () {return 60;},
    setLocator : function (locator){},
    setExternalTransform : function(affineTransform)
    {
        if(!cc.affineTransformEqualToTransform(this._additionalTransform, affineTransform))
        {
            this.setAdditionalTransform(affineTransform);
        }
    },
    getExternalTransform : function()
    {
        return this._additionalTransform;
    },
    setAnimationRunning: function () {},
    _enableTick: function(val){},
    _resetState : function()
    {},
    _updateVisibility : function(state, parent)
    {
        var alphaOffset = state.hasColorTransform ? state.colorTransform.offset.a : 0;
        this.setOpacity(state.alpha + alphaOffset);
    },
    isVisible : function()
    {
        return this.getOpacity() > 0;
    },
    visit: function(parentCmd)
    {
        if(this.isVisibleInCurrentFrame())
        {
            this._super(parentCmd);
        }
    },
    _getFilters : function(){return null},
    _processAnimation : function(){},
    _applyState : function(state, parent)
    {
        this._applyStateSuper(state, parent);
    },
    _applyStateSuper : function(state, parent)
    {
        this._needsCtx = parent._needsCtx;
        this._filterStack.length = 0;
        this._parentTimeLine = parent;
        if(this._usedAtlasScale != 1)
        {
            var newMat = cc.clone(state.matrix);
            newMat.tx *= this._usedAtlasScale;
            newMat.ty *= this._usedAtlasScale;
            this.setExternalTransform(newMat);
        }
        else
        {
            this.setExternalTransform(state.matrix);
        }
        if (state.hasEffect) {
            this._filterStack = this._filterStack.concat(state.effect);
            this._needsCtx = true;
        }
        if (parent._filterStack && parent._filterStack.length > 0) {
            this._filterStack = this._filterStack.concat(parent._filterStack);
        }
        if(this._filterStack.length > 0 && this._filterStack[0].type === gaf.EFFECT_COLOR_MATRIX)
        {
            this._needsCtx = true;
        }
        if (state.hasColorTransform)
        {
            this._cascadeColorMult.r = state.colorTransform.mult.r * parent._cascadeColorMult.r / 255;
            this._cascadeColorMult.g = state.colorTransform.mult.g * parent._cascadeColorMult.g / 255;
            this._cascadeColorMult.b = state.colorTransform.mult.b * parent._cascadeColorMult.b / 255;
            this._cascadeColorMult.a = state.colorTransform.mult.a * parent._cascadeColorMult.a / 255;
            this._cascadeColorOffset.r = state.colorTransform.offset.r + parent._cascadeColorOffset.r;
            this._cascadeColorOffset.g = state.colorTransform.offset.g + parent._cascadeColorOffset.g;
            this._cascadeColorOffset.b = state.colorTransform.offset.b + parent._cascadeColorOffset.b;
            this._cascadeColorOffset.a = state.colorTransform.offset.a + parent._cascadeColorOffset.a;
        }
        else
        {
            this._cascadeColorMult.r = parent._cascadeColorMult.r;
            this._cascadeColorMult.g = parent._cascadeColorMult.g;
            this._cascadeColorMult.b = parent._cascadeColorMult.b;
            this._cascadeColorMult.a = state.alpha * (parent._cascadeColorMult.a / 255);
            this._cascadeColorOffset.r = parent._cascadeColorOffset.r;
            this._cascadeColorOffset.g = parent._cascadeColorOffset.g;
            this._cascadeColorOffset.b = parent._cascadeColorOffset.b;
            this._cascadeColorOffset.a = parent._cascadeColorOffset.a;
        }
        if (this._cascadeColorOffset.r > 0 ||
            this._cascadeColorOffset.g > 0 ||
            this._cascadeColorOffset.b > 0 ||
            this._cascadeColorOffset.a > 0)
        {
            this._needsCtx = true;
        }
    },
    _initRendererCmd: function()
    {
        this._renderCmd = cc.renderer.getRenderCmd(this);
        this._renderCmd._visit = this._renderCmd.visit;
        var self = this;
        this._renderCmd.visit = function(parentCmd) {
            if(self.isVisibleInCurrentFrame()){
                this._visit(parentCmd);
            }
        }
    },
    _getNode : function()
    {
        return this;
    },
    setAnchorPoint : function(point, y)
    {
        if (y === undefined)
        {
            this._super(point.x, point.y - 1);
        }
        else
        {
            this._super(point, y - 1);
        }
    }
});
gaf.Object._createNullObject = function()
{
    var ret = new gaf.Object();
    ret.isVisible = function(){return true};
    return ret;
};
gaf.TimeLine = gaf.Object.extend
({
    _className: "GAFTimeLine",
    _objects: null,
    _container: null,
    _animationStartedNextLoopDelegate: null,
    _animationFinishedPlayDelegate: null,
    _framePlayedDelegate: null,
    _sequenceDelegate: null,
    _fps: 60,
    _frameTime: 1/60,
    _currentSequenceStart: gaf.FIRST_FRAME_INDEX,
    _currentSequenceEnd: gaf.FIRST_FRAME_INDEX,
    _totalFrameCount: 0,
    _isRunning: false,
    _isLooped: false,
    _isReversed: false,
    _timeDelta: 0,
    _animationsSelectorScheduled: false,
    _currentFrame: gaf.FIRST_FRAME_INDEX,
    setAnimationStartedNextLoopDelegate: function (delegate)
    {
        this._animationStartedNextLoopDelegate = delegate;
    },
    setAnimationFinishedPlayDelegate: function (delegate)
    {
        this._animationFinishedPlayDelegate = delegate;
    },
    setLooped: function (looped, recursively)
    {
        this._isLooped = looped;
        if (recursively)
        {
            this._objects.forEach(function (item)
            {
                item.setLooped(looped, recursively);
            });
        }
    },
    getBoundingBoxForCurrentFrame: function ()
    {
        var result = null;//cc.rect();
        var isFirstObj = true;
        this._objects.forEach(function (item) {
            if(item.isVisibleInCurrentFrame() && item.isVisible())
            {
                var bb = item.getBoundingBoxForCurrentFrame();
                if(!bb)
                {
                    bb = item.getBoundingBox();
                }
                if (isFirstObj)
                {
                    isFirstObj = false;
                    result = bb;
                }
                else
                {
                    result = cc.rectUnion(result, bb);
                }
            }
        });
        return cc._rectApplyAffineTransformIn(result, this._container.getNodeToParentTransform());
    },
    setFps: function (fps)
    {
        cc.assert(fps !== 0, 'Error! Fps is set to zero.');
        this._fps = fps;
        this._frameTime = 1/fps;
    },
    getObjectByName: function (name)
    {
        var elements = name.split('.');
        var result = null;
        var retId = -1;
        var timeLine = this;
        var BreakException = {};
        try
        {
            elements.forEach(function(element)
            {
                var parts = timeLine._gafproto.getNamedParts();
                if(parts.hasOwnProperty(element))
                {
                    retId = parts[element];
                }
                else
                {
                    BreakException.lastElement = element;
                    throw BreakException;
                }
                result = timeLine._objects[retId];
                timeLine = result;
            });
        }
        catch (e)
        {
            if (e!==BreakException)
            {
                throw e;
            }
            cc.log("Sequence incorrect: `" + name + "` At: `" + BreakException.lastElement + "`");
            return null;
        }
        return result;
    },
    clearSequence: function ()
    {
        this._currentSequenceStart = gaf.FIRST_FRAME_INDEX;
        this._currentSequenceEnd = this._gafproto.getTotalFrames();
    },
    getIsAnimationRunning: function ()
    {
        return this._isRunning;
    },
    gotoAndStop: function (value)
    {
        var frame = 0;
        if (typeof value === 'string')
        {
            frame = this.getStartFrame(value);
        }
        else
        {
            frame = value;
        }
        if (this.setFrame(frame))
        {
            this.setAnimationRunning(false, false);
            return true;
        }
        return false;
    },
    gotoAndPlay: function (value)
    {
        var frame = 0;
        if (typeof value === 'string')
        {
            frame = this.getStartFrame(value);
        }
        else
        {
            frame = value;
        }
        if (this.setFrame(frame))
        {
            this.setAnimationRunning(true, false);
            return true;
        }
        return false;
    },
    getStartFrame: function (frameLabel)
    {
        var seq = this._gafproto.getSequences()[frameLabel];
        if (seq)
        {
            return seq.start;
        }
        return gaf.IDNONE;
    },
    getEndFrame: function (frameLabel)
    {
        var seq = this._gafproto.getSequences()[frameLabel];
        if (seq)
        {
            return seq.end;
        }
        return gaf.IDNONE;
    },
    setFramePlayedDelegate: function (delegate)
    {
        this._framePlayedDelegate = delegate;
    },
    getCurrentFrameIndex: function ()
    {
        return this._showingFrame;
    },
    getTotalFrameCount: function ()
    {
        return this._gafproto.getTotalFrames();
    },
    start: function ()
    {
        this._enableTick(true);
        if (!this._isRunning)
        {
            this._currentFrame = gaf.FIRST_FRAME_INDEX;
            this.setAnimationRunning(true, true);
        }
    },
    stop: function ()
    {
        this._enableTick(false);
        if (this._isRunning)
        {
            this._currentFrame = gaf.FIRST_FRAME_INDEX;
            this.setAnimationRunning(false, true);
        }
    },
    isDone: function ()
    {
        if (this._isLooped)
        {
            return false;
        }
        else
        {
            if (!this._isReversed)
            {
                return this._currentFrame > this._totalFrameCount;
            }
            else
            {
                return this._currentFrame < gaf.FIRST_FRAME_INDEX - 1;
            }
        }
    },
    getSequences: function()
    {
        return this._gafproto.getSequences();
    },
    playSequence: function (name, looped)
    {
        var s = this.getStartFrame(name);
        var e = this.getEndFrame(name);
        if (gaf.IDNONE === s || gaf.IDNONE === e)
        {
            return false;
        }
        this._currentSequenceStart = s;
        this._currentSequenceEnd = e;
        if (this._currentFrame < this._currentSequenceStart || this._currentFrame > this._currentSequenceEnd)
        {
            this._currentFrame = this._currentSequenceStart;
        }
        else
        {
            this._currentFrame = this._currentSequenceStart;
        }
        this.setLooped(looped, false);
        this.resumeAnimation();
        return true;
    },
    isReversed: function ()
    {
        return this._isReversed;
    },
    setSequenceDelegate: function (delegate)
    {
        this._sequenceDelegate = delegate;
    },
    setFrame: function (index)
    {
        if (index >= gaf.FIRST_FRAME_INDEX && index < this._totalFrameCount)
        {
            this._showingFrame = index;
            this._currentFrame = index;
            this._processAnimation();
            return true;
        }
        return false;
    },
    pauseAnimation: function ()
    {
        if (this._isRunning)
        {
            this.setAnimationRunning(false, false);
        }
    },
    isLooped: function ()
    {
        return this._isLooped;
    },
    resumeAnimation: function ()
    {
        if (!this._isRunning)
        {
            this.setAnimationRunning(true, false);
        }
    },
    setReversed: function (reversed)
    {
        this._isReversed = reversed;
    },
    hasSequences: function ()
    {
        return this._gafproto.getSequences().length > 0;
    },
    getFps: function ()
    {
        return this._fps;
    },
    ctor: function(gafTimeLineProto, scale)
    {
        this._super(scale);
        this._objects = [];
        cc.assert(gafTimeLineProto,  "Error! Missing mandatory parameter.");
        this._gafproto = gafTimeLineProto;
    },
    setExternalTransform: function(affineTransform)
    {
        if(!cc.affineTransformEqualToTransform(this._container._additionalTransform, affineTransform))
        {
           this._container.setAdditionalTransform(affineTransform);
        }
    },
    _init: function()
    {
        this.setContentSize(this._gafproto.getBoundingBox());
        this._currentSequenceEnd = this._gafproto.getTotalFrames();
        this._totalFrameCount = this._currentSequenceEnd;
        this.setFps(this._gafproto.getFps());
        this._container = new cc.Node();
        this.addChild(this._container);
        var self = this;
        var asset = this._gafproto.getAsset();
        this._gafproto.getObjects().forEach(function(object)
        {
            var objectProto = asset._getProtos()[object];
            cc.assert(objectProto, "Error. GAF proto for type: " + object.type + " and reference id: " + object + " not found.");
            self._objects[object] = objectProto._gafConstruct();
        });
    },
    _enableTick: function(val)
    {
        if (!this._animationsSelectorScheduled && val)
        {
            this.schedule(this._processAnimations);
            this._animationsSelectorScheduled = true;
        }
        else if (this._animationsSelectorScheduled && !val)
        {
            this.unschedule(this._processAnimations);
            this._animationsSelectorScheduled = false;
        }
    },
    _processAnimations: function (dt)
    {
        this._timeDelta += dt;
        while (this._timeDelta >= this._frameTime)
        {
            this._timeDelta -= this._frameTime;
            this._step();
        }
    },
    _step: function ()
    {
        this._showingFrame = this._currentFrame;
        if(!this.getIsAnimationRunning())
        {
            this._processAnimation();
            return;
        }
        if(this._sequenceDelegate)
        {
            var seq;
            if(!this._isReversed)
            {
                seq = this._getSequenceByLastFrame(this._currentFrame);
            }
            else
            {
                seq = this._getSequenceByFirstFrame(this._currentFrame + 1);
            }
            if (seq)
            {
                this._sequenceDelegate(this, seq);
            }
        }
        if (this._isCurrentFrameLastInSequence())
        {
            if(this._isLooped)
            {
                if(this._animationStartedNextLoopDelegate)
                    this._animationStartedNextLoopDelegate(this);
            }
            else
            {
                this.setAnimationRunning(false, false);
                if(this._animationFinishedPlayDelegate)
                    this._animationFinishedPlayDelegate(this);
            }
        }
        this._processAnimation();
        this._currentFrame = this._nextFrame();
    },
    _isCurrentFrameLastInSequence: function()
    {
        if (this._isReversed)
            return this._currentFrame == this._currentSequenceStart;
        return this._currentFrame == this._currentSequenceEnd - 1;
    },
    _nextFrame: function()
    {
        if (this._isCurrentFrameLastInSequence())
        {
            if (!this._isLooped)
                return this._currentFrame;
            if (this._isReversed)
                return this._currentSequenceEnd - 1;
            else
                return this._currentSequenceStart;
        }
        return this._currentFrame + (this._isReversed ? -1 : 1);
    },
    _processAnimation: function ()
    {
        this._realizeFrame(this._container, this._currentFrame);
        if (this._framePlayedDelegate)
        {
            this._framePlayedDelegate(this, this._currentFrame);
        }
    },
    _realizeFrame: function(out, frameIndex)
    {
        var self = this;
        var objects = self._objects;
        var frames = self._gafproto.getFrames();
        if(frameIndex > frames.length)
        {
            return;
        }
        var currentFrame = frames[frameIndex];
        if(!currentFrame)
        {
            return;
        }
        var states = currentFrame.states;
        for(var stateIdx = 0, total = states.length; stateIdx < total; ++stateIdx)
        {
            var state = states[stateIdx];
            var object = objects[state.objectIdRef];
            if(!object)
            {
                return;
            }
            if(state.alpha < 0)
            {
                object._resetState();
            }
            object._updateVisibility(state, self);
            if(!object.isVisible())
            {
                continue;
            }
            object._applyState(state, self);
            var parent = out;
            if(state.hasMask)
            {
                parent = objects[state.maskObjectIdRef]._getNode();
                cc.assert(parent, "Error! Mask not found.");
            }
            object._lastVisibleInFrame = 1 + frameIndex;
            gaf.TimeLine.rearrangeSubobject(parent, object, state.depth);
            if(object._step)
            {
                object._step();
            }
        }
    },
    setAnimationRunning: function (value, recursively)
    {
        this._isRunning = value;
        if(recursively)
        {
            this._objects.forEach(function (obj)
            {
                if (obj && obj.setAnimationRunning)
                {
                    obj.setAnimationRunning(value, recursively);
                }
            });
        }
    },
    _getSequenceByLastFrame: function(){
        var sequences = this._gafproto.getSequences();
        for(var item in sequences){
            if(sequences.hasOwnProperty(item)){
                if(sequences[item].end === frame + 1)
                {
                    return item;
                }
            }
        }
        return "";
    },
    _resetState : function()
    {
        this._super();
        this._currentFrame = this._currentSequenceStart;
    },
    _getSequenceByFirstFrame: function(){
        var sequences = this._gafproto.getSequences();
        for(var item in sequences){
            if(sequences.hasOwnProperty(item)){
                if(sequences[item].start === frame)
                {
                    return item;
                }
            }
        }
        return "";
    }
});
gaf.TimeLine.rearrangeSubobject = function(out, object, depth)
{
    var parent = object.getParent();
    if (parent !== out)
    {
        object.removeFromParent(false);
        out.addChild(object, depth);
    }
    else
    {
        object.setLocalZOrder(depth);
    }
};
gaf.TextField = gaf.Object.extend
({
    _className: "GAFTextField"
});
gaf.Sprite = gaf.Object.extend
({
    _className: "GAFSprite",
    _hasCtx: false,
    _hasFilter: false,
    ctor : function(gafSpriteProto, usedScale)
    {
        this._super(usedScale);
        cc.assert(gafSpriteProto, "Error! Missing mandatory parameter.");
        this._gafproto = gafSpriteProto;
    },
    _init : function()
    {
        var frame = this._gafproto.getFrame();
        cc.assert(frame instanceof cc.SpriteFrame, "Error. Wrong object type.");
        this._sprite = new cc.Sprite();
        this._sprite._renderCmd = this._gafCreateRenderCmd(this._sprite);
        this._sprite.initWithSpriteFrame(frame);
        this._sprite.setAnchorPoint(this._gafproto.getAnchor());
        this.addChild(this._sprite);
        this._sprite.setOpacityModifyRGB(true);
        if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            this._sprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    },
    _applyState : function(state, parent)
    {
        this._applyStateSuper(state, parent);
        if(this._needsCtx)
        {
            if(!this._hasCtx)
            {
                this._enableCtx();
                this._hasCtx = true;
            }
            this._applyCtxState(state);
        }
        else
        {
            if(this._hasCtx)
            {
                this._disableCtx();
                this._hasCtx = false;
            }
            if(!cc.colorEqual(this._sprite._realColor, this._cascadeColorMult))
            {
                this._sprite.setColor(this._cascadeColorMult);
            }
            if(this._sprite.getOpacity() != this._cascadeColorMult.a)
            {
                this._sprite.setOpacity(this._cascadeColorMult.a);
            }
        }
    },
    _enableCtx: function()
    {
        this._sprite._renderCmd._enableCtx();
    },
    _disableCtx: function()
    {
        this._sprite._renderCmd._disableCtx();
    },
    _applyCtxState: function(state){
        this._sprite._renderCmd._applyCtxState(this);
    },
    getBoundingBoxForCurrentFrame: function ()
    {
        var result = this._sprite.getBoundingBox();
        return cc._rectApplyAffineTransformIn(result, this.getNodeToParentTransform());
    },
    _gafCreateRenderCmd: function(item){
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new gaf.Sprite.CanvasRenderCmd(item);
        else
            return new gaf.Sprite.WebGLRenderCmd(item);
    }
});
gaf.Mask = gaf.Object.extend
({
    _className: "GAFMask",
    _clippingNode: null,
    ctor : function(gafSpriteProto)
    {
        this._super();
        cc.assert(gafSpriteProto, "Error! Missing mandatory parameter.");
        this._gafproto = gafSpriteProto;
    },
    _init : function()
    {
        var maskNodeProto = this._gafproto.getMaskNodeProto();
        cc.assert(maskNodeProto, "Error. Mask node for id ref " + this._gafproto.getIdRef() + " not found.");
        this._maskNode = maskNodeProto._gafConstruct();
            this._clippingNode = cc.ClippingNode.create(this._maskNode);
        this._clippingNode.setAlphaThreshold(0.5);
        this.addChild(this._clippingNode);
    },
    setExternalTransform : function(affineTransform)
    {
        if(!cc.affineTransformEqualToTransform(this._maskNode._additionalTransform, affineTransform))
        {
            this._maskNode.setAdditionalTransform(affineTransform);
        }
    },
    _getNode : function()
    {
        return this._clippingNode;
    }
});
(function() {
    gaf.Sprite.CanvasRenderCmd = function (renderable) {
        cc.Sprite.CanvasRenderCmd.call(this, renderable);
        this._hasTintMult = false;
        this._hasTintOffset = false;
        this._hasCtx = false;
        this._tintMult = cc.color(255,255,255,255);
        this._tintOffset = cc.color(0,0,0,0);
        this._textureDirty = false;
    };
    var proto = gaf.Sprite.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
    proto.constructor = gaf.Sprite.CanvasRenderCmd;
    proto._disableCtx = function(){
        this._hasTintOffset = false;
        this._hasCtx = false;
        this._textureDirty = true;
        this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
        this._tintMult = cc.color(255,255,255,255);
        this._tintOffset = cc.color(0,0,0,0);
    };
    proto._enableCtx = function(){
    };
    proto._applyCtxState = function(gafObject){
        var tintMult = gafObject._cascadeColorMult;
        var tintOffset = gafObject._cascadeColorOffset;
        var opacity = tintMult.a;
        if(this._node.getOpacity() != opacity)
        {
            this._node.setOpacity(opacity);
        }
        var multDirty = !cc.colorEqual(this._tintMult, tintMult);
        if(multDirty)
        {
            this._node.setColor(tintMult);
            this._tintMult = tintMult;
            this._hasTintMult =
                (tintMult.r !== 255 ||
                 tintMult.g !== 255 ||
                 tintMult.b !== 255 );
        }
        var offfsetDirty =
            (this._tintOffset.r != tintOffset.r) ||
            (this._tintOffset.g != tintOffset.g) ||
            (this._tintOffset.b != tintOffset.b) ||
            (this._tintOffset.a != tintOffset.a);
        if(offfsetDirty)
        {
            this._tintOffset = tintOffset;
            this._hasTintOffset =
                (tintOffset.r !== 0 ||
                 tintOffset.g !== 0 ||
                 tintOffset.b !== 0 ||
                 tintOffset.a !== 0 );
        }
        this._textureDirty = multDirty || offfsetDirty;
        if(this._textureDirty)
        {
            this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
        }
        this._hasCtx = gafObject._filterStack.length > 0 && gafObject._filterStack[0].type === gaf.EFFECT_COLOR_MATRIX;
    };
    proto.rendering = function(ctx, scaleX, scaleY)
    {
        var node = this._node;
        var locTextureCoord = this._textureCoord,
            alpha = (this._displayedOpacity / 255);
        if ((node._texture && ((locTextureCoord.width === 0 || locTextureCoord.height === 0)
            || !node._texture._textureLoaded)) || alpha === 0)
            return;
        var wrapper = ctx || cc._renderContext,
            context = wrapper.getContext();
        var locX = node._offsetPosition.x,
            locHeight = node._rect.height,
            locWidth = node._rect.width,
            locY = -node._offsetPosition.y - locHeight,
            image;
        wrapper.setTransform(this._worldTransform, scaleX, scaleY);
        wrapper.setCompositeOperation(this._blendFuncStr);
        wrapper.setGlobalAlpha(alpha);
        if(node._flippedX || node._flippedY)
            wrapper.save();
        if (node._flippedX) {
            locX = -locX - locWidth;
            context.scale(-1, 1);
        }
        if (node._flippedY) {
            locY = node._offsetPosition.y;
            context.scale(1, -1);
        }
        image = node._texture._htmlElementObj;
        if (this._colorized) {
            context.drawImage(image,
                0, 0, locTextureCoord.width,locTextureCoord.height,
                locX * scaleX,locY * scaleY, locWidth * scaleX, locHeight * scaleY);
        } else {
            context.drawImage(image,
                locTextureCoord.renderX, locTextureCoord.renderY, locTextureCoord.width, locTextureCoord.height,
                locX * scaleX, locY * scaleY, locWidth * scaleX, locHeight * scaleY);
        }
        if(node._flippedX || node._flippedY)
            wrapper.restore();
        cc.g_NumberOfDraws++;
    };
    if(cc.sys._supportCanvasNewBlendModes){
        proto._updateColor = function () {
            var displayedColor = this._displayedColor, node = this._node;
            this._hasTintMult |= (displayedColor.r !== 255 || displayedColor.g !== 255 || displayedColor.b !== 255);
            if(this._textureDirty)
            {
                this._textureDirty = false;
                if (this._colorized) {
                    this._colorized = false;
                    node.texture = this._originalTexture;
                }
            }
            else
            {
                return;
            }
            var locElement, locTexture = node._texture, locRect = this._textureCoord;
            if(this._hasTintMult)
            {
                if (locTexture && locRect.validRect && this._originalTexture) {
                    locElement = locTexture.getHtmlElementObj();
                    if (!locElement)
                        return;
                    this._colorized = true;
                    if (this._hasTintOffset || this._hasCtx) displayedColor = this._tintMult;
                    locElement = cc.Sprite.CanvasRenderCmd._generateTintImageWithMultiply(this._originalTexture._htmlElementObj, displayedColor, locRect);
                    locTexture = new cc.Texture2D();
                    locTexture.initWithElement(locElement);
                    locTexture.handleLoadedTexture();
                    node.texture = locTexture;
                }
            }
            locTexture = node._texture;
            if(this._hasTintOffset)
            {
                var cacheTextureForColor = cc.textureCache.getTextureColors(this._originalTexture.getHtmlElementObj());
                if (locTexture && locRect.validRect && this._originalTexture) {
                    locElement = locTexture.getHtmlElementObj();
                    if (!locElement)
                        return;
                    if(this._colorized)
                        var texRect = cc.rect(0,0,locRect.width, locRect.height);
                    else
                        texRect = locRect;
                    locElement = this._gafGenerateTintImage(node.texture._htmlElementObj, texRect, cacheTextureForColor, this._tintOffset, locRect);
                    locTexture = new cc.Texture2D();
                    locTexture.initWithElement(locElement);
                    locTexture.handleLoadedTexture();
                    node.texture = locTexture;
                    this._colorized = true;
                }
            }
        };
        proto._gafGenerateTintImage = function(texture, texRect, tintedImgCache, color, rect, renderCanvas){
            if (!rect)
                rect = cc.rect(0, 0, texture.width, texture.height);
            var w = Math.min(rect.width, tintedImgCache[0].width);
            var h = Math.min(rect.height, tintedImgCache[0].height);
            var buff = renderCanvas, ctx;
            if (!buff) {
                buff = document.createElement("canvas");
                buff.width = w;
                buff.height = h;
                ctx = buff.getContext("2d");
            } else {
                ctx = buff.getContext("2d");
                ctx.clearRect(0, 0, w, h);
            }
            ctx.save();
            ctx.globalCompositeOperation = 'source-over';
            ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h);
            ctx.globalCompositeOperation = 'source-in';
            ctx.fillStyle = 'rgba(' + Math.round(color.r) + ',' + Math.round(color.g) + ',' + Math.round(color.b) + ',1)';
            ctx.fillRect(0, 0, w, h);
            ctx.globalCompositeOperation = 'lighter';
            ctx.drawImage(texture, texRect.x, texRect.y, w, h, 0, 0, w, h);
            ctx.restore();
            return buff;
        };
    }
})();
gaf._TimeLineProto = function(asset, animationFrameCount, boundingBox, pivotPoint, id, linkageName)
{
    id = typeof id != 'undefined' ? id : 0;
    linkageName = linkageName || "";
    this._objects = [];
    this.getTotalFrames = function(){return animationFrameCount};
    this.getBoundingBox = function() {return boundingBox};
    this.getId = function() {return id};
    this.getLinkageName = function() {return linkageName};
    this.getPivot = function(){return pivotPoint};
    this.getRect = function(){return boundingBox};
    this.getNamedParts = function() {return {}};
    this.getSequences = function() {return {}};
    this.getFrames = function(){return []};
    this.getFps = function(){return 60};
    this.getObjects = function(){return this._objects};
    this.getAsset = function(){return asset};
    this._gafConstruct = function()
    {
        var usedScale = this.getAsset()._usedAtlasScale;
        var ret = new gaf.TimeLine(this, usedScale);
        ret._init();
        return ret;
    };
};
gaf._SpriteProto = function(asset, atlasFrames, elementAtlasIdRef)
{
    this.getFrames = function(){return atlasFrames};
    this.getIdRef = function(){return elementAtlasIdRef};
    this.getAsset = function() {return asset};
    this._gafConstruct = function()
    {
        var usedScale = this.getAsset()._usedAtlasScale;
        var ret = new gaf.Sprite(this, usedScale);
        ret._init();
        return ret;
    };
};
gaf._SpriteProto.prototype.getFrame = function()
{
    var usedScale = this.getAsset()._usedAtlasScale;
    cc.assert(usedScale, "Error. Atlas scale zero.");
    var frames = this.getFrames()[usedScale];
    cc.assert(frames, "Error. No frames found for used scale `"+usedScale+"`");
    return frames[this.getIdRef()];
};
gaf._SpriteProto.prototype.getAnchor = function()
{
    return this.getFrame()._gafAnchor;
};
gaf._MaskProto = function(asset, mask, idRef)
{
    this.getIdRef = function(){return idRef};
    this.getMaskNodeProto = function() {return mask};
    this._gafConstruct = function()
    {
        var ret = new gaf.Mask(this);
        ret._init();
        return ret;
    };
};
gaf.ReadSingleTag = function(stream){
    var tagId = stream.Ushort();
    var tag = gaf.Tags[tagId];
    var result = {};
    if(typeof tag === "undefined"){
        console.log("GAF. Non implemented tag detected.");
        gaf.Tags.Default.parse(stream, tagId);
    }
    else{
        result = tag.parse(stream, tagId);
    }
    return result;
};
gaf.ReadTags = function(stream){
    var tags = [];
    try {
        do {
            var tag = gaf.ReadSingleTag(stream);
            tags.push(tag);
        } while (tag.tagId != 0);
    }
    catch (e){
        if (e instanceof Error && e.message == "GAF format error"){
            console.log("GAF format error:\n" + e.stack);
        }
        else{
            console.log(e.stack);
            throw e;
        }
    }
    return tags;
};
gaf.Tag = function(){
    this.Default = Object.create(gaf.Tag.base);
    this["0"] = Object.create(gaf.Tag.End);
    this["1"] = Object.create(gaf.Tag.DefineAtlas);
    this["2"] = Object.create(gaf.Tag.DefineAnimationMasks);
    this["3"] = Object.create(gaf.Tag.DefineAnimationObjects);
    this["4"] = Object.create(gaf.Tag.DefineAnimationFrames);
    this["5"] = Object.create(gaf.Tag.DefineNamedParts);
    this["6"] = Object.create(gaf.Tag.DefineSequences);
    this["7"] = Object.create(gaf.Tag.DefineTextFields);
    this["8"] = Object.create(gaf.Tag.DefineAtlas2);
    this["9"] = Object.create(gaf.Tag.DefineStage);
    this["10"] = Object.create(gaf.Tag.DefineAnimationObjects2);
    this["11"] = Object.create(gaf.Tag.DefineAnimationMasks2);
    this["12"] = Object.create(gaf.Tag.DefineAnimationFrames2);
    this["13"] = Object.create(gaf.Tag.DefineTimeline);
};
gaf.Tag.base = function() {};
gaf.Tag.base.parse = function(stream, tagId){
    var size = stream.Uint();
    stream.startNestedBuffer(size);
    var result = this.doParse(stream);
    stream.endNestedBuffer();
    result.tagName = this.tagName;
    result.tagId = tagId;
    return result;
};
gaf.Tag.base.doParse = function(stream){
        return {};
    };
gaf.Tag.End = Object.create(gaf.Tag.base);
gaf.Tag.End.tagName = "TagEnd";
gaf.Tag.DefineAtlas = Object.create(gaf.Tag.base);
gaf.Tag.DefineAtlas.tagName = "TagDefineAtlas";
gaf.Tag.DefineAtlas.doParse = function (s) {
    var exec = s.fields(
        'scale', 'Float',
        'atlases', s.array('Ubyte', s.fields(
            'id', 'Uint',
            'sources', s.array('Ubyte', s.fields(
                'source', 'String',
                'csf', 'Float'
            ))
        )),
        'elements', s.array('Uint', s.fields(
            'pivot', 'Point',
            'origin', 'Point',
            'scale', 'Float',
            'size', 'Point',
            'atlasId', 'Uint',
            'elementAtlasId', 'Uint'
        ))
    );
    return {'content': exec()};
};
gaf.Tag.DefineAnimationMasks = Object.create(gaf.Tag.base);
gaf.Tag.DefineAnimationMasks.tagName = "TagDefineAnimationMasks";
gaf.Tag.DefineAnimationMasks.doParse = function (s) {
    var exec = s.array('Uint', s.fields(
            'objectId', 'Uint',
            'elementAtlasIdRef', 'Uint'
        ));
    var result = {'content': exec()};
    debugger;
    return result;
};
gaf.Tag.DefineAnimationObjects = Object.create(gaf.Tag.base);
gaf.Tag.DefineAnimationObjects.tagName = "TagDefineAnimationObjects";
gaf.Tag.DefineAnimationObjects.doParse = function (s) {
    var exec = s.array('Uint', s.fields(
        'objectId', 'Uint',
        'elementAtlasIdRef', 'Uint'
    ));
    return {'content': exec()};
};
gaf.Tag.DefineAnimationFrames = Object.create(gaf.Tag.base);
gaf.Tag.DefineAnimationFrames.tagName = "TagDefineAnimationFrames";
gaf.Tag.DefineAnimationFrames.doParse = function(s){
    var exec = s.array('Uint', s.fields(
        'frame', 'Uint',
        'state', s.array('Uint', s.fields(
            'hasColorTransform', 'Ubyte',
            'hasMask', 'Ubyte',
            'hasEffect', 'Ubyte',
            'objectIdRef', 'Uint',
            'depth', 'Int',
            'alpha', 'Float',
            'matrix', 'Matrix',
            'colorTransform', s.condition('hasColorTransform', 1, s.fields(
                'alphaOffset', 'Float',
                'redMultiplier', 'Float',
                'redOffset', 'Float',
                'greenMultiplier', 'Float',
                'greenOffset', 'Float',
                'blueMultiplier', 'Float',
                'blueOffset', 'Float'
            )),
            'effect', s.condition('hasEffect', 1, s.array('Ubyte', gaf.Tag._readFilter(s))),
            'maskObjectIdRef', s.condition('hasMask', 1, s.fields(
                'maskObjectIdRef', 'Uint'
            ))
        ))
    ));
    return {'content': exec()};
};
gaf.Tag.DefineNamedParts = Object.create(gaf.Tag.base);
gaf.Tag.DefineNamedParts.tagName = "TagDefineNamedParts";
gaf.Tag.DefineNamedParts.doParse = function(s) {
    var exec = s.array('Uint', s.fields(
        'objectId', 'Uint',
        'name', 'String'
    ));
    return {'content': exec()};
};
gaf.Tag.DefineSequences = Object.create(gaf.Tag.base);
gaf.Tag.DefineSequences.tagName = "TagDefineSequences";
gaf.Tag.DefineSequences.doParse = function(s) {
    var exec = s.array('Uint', s.fields(
        'id', 'String',
        'start', 'Ushort',
        'end', 'Ushort'
    ));
    return {'content': exec()};
};
gaf.Tag.DefineTextFields = Object.create(gaf.Tag.base);
gaf.Tag.DefineTextFields.tagName = "TagDefineTextFields";
gaf.Tag.DefineTextFields.doParse = function(s) {
    var exec = s.array('Uint', s.fields(
        'id', 'Uint',
        'pivot', 'Point',
        'end', 'Ushort',
        'width', 'Float',
        'height', 'Float',
        'text', 'String',
        'embedFonts', 'Boolean',
        'multiline', 'Boolean',
        'wordWrap', 'Boolean',
        'hasRestrict', 'Boolean',
        'restrict', s.condition('hasRestrict', 1, function (){return s['String'];}),
        'editable', 'Boolean',
        'selectable', 'Boolean',
        'displayAsPassword', 'Boolean',
        'maxChars', 'Uint',
        'align', 'Uint',
        'blockIndent', 'Uint',
        'bold', 'Boolean',
        'bullet', 'Boolean',
        'color', 'color',
        'font', 'String',
        'indent', 'Uint',
        'italic', 'Boolean',
        'kerning', 'Boolean',
        'leading', 'Uint',
        'leftMargin', 'Uint',
        'letterSpacing', 'Float',
        'rightMargin', 'Uint',
        'size', 'Uint',
        'tabStops', s.array('Uint', s.fields(
            'value', 'Uint'
        )),
        'target', 'string',
        'underline', 'Boolean',
        'url', 'String'
    ));
    return {'content': exec()};
};
gaf.Tag.DefineAtlas2 = Object.create(gaf.Tag.base);
gaf.Tag.DefineAtlas2.tagName = "TagDefineAtlas2";
gaf.Tag.DefineAtlas2.doParse = function(s) {
    var exec = s.fields(
        'scale', 'Float',
        'atlases', s.array('Ubyte', s.fields(
            'id', 'Uint',
            'sources', s.array('Ubyte', s.fields(
                'source', 'String',
                'csf', 'Float'
            ))
        )),
        'elements', s.array('Uint', s.fields(
            'pivot', 'Point',
            'origin', 'Point',
            'scale', 'Float',
            'size', 'Point',
            'atlasId', 'Uint',
            'elementAtlasId', 'Uint',
            'hasScale9Grid', 'Boolean',
            'scale9GridRect', s.condition('hasScale9Grid', 1, function(){return s.Rect();})
        ))
    );
    return {'content': exec()};
};
gaf.Tag.DefineStage = Object.create(gaf.Tag.base);
gaf.Tag.DefineStage.tagName = "TagDefineStage";
gaf.Tag.DefineStage.doParse = function(s) {
    var exec = s.fields(
        'fps', 'Ubyte',
        'color', 'color',
        'width', 'Ushort',
        'height', 'Ushort'
    );
    return {'content': exec()};
};
gaf.Tag.DefineAnimationObjects2 = Object.create(gaf.Tag.base);
gaf.Tag.DefineAnimationObjects2.tagName = "TagDefineAnimationObjects2";
gaf.Tag.DefineAnimationObjects2.doParse = function(s) {
    var exec = s.array('Uint', s.fields(
        'objectId', 'Uint',
        'elementAtlasIdRef', 'Uint',
        'type', 'Ushort'
    ));
    return {'content': exec()};
};
gaf.Tag.DefineAnimationMasks2 = Object.create(gaf.Tag.base);
gaf.Tag.DefineAnimationMasks2.tagName = "TagDefineAnimationMasks2";
gaf.Tag.DefineAnimationMasks2.doParse  = function(s) {
    var exec = s.array('Uint', s.fields(
        'objectId', 'Uint',
        'elementAtlasIdRef', 'Uint',
        'type', 'Ushort'
    ));
    return {'content': exec()};
};
gaf.Tag.DefineAnimationFrames2 = Object.create(gaf.Tag.base);
gaf.Tag.DefineAnimationFrames2.tagName = "TagDefineAnimationFrames2";
gaf.Tag.DefineAnimationFrames2.doParse = function(s) {
    var exec = s.array('Uint', s.fields(
        'frame', 'Uint',
        'hasChangesInDisplayList', 'Boolean',
        'hasActions', 'Boolean',
        'state', s.condition('hasChangesInDisplayList', 1, s.array('Uint', s.fields(
            'hasColorTransform', 'Boolean',
            'hasMask', 'Boolean',
            'hasEffect', 'Boolean',
            'objectIdRef', 'Uint',
            'depth', 'Int',
            'alpha', 'Float',
            'matrix', 'Matrix',
            'colorTransform', s.condition('hasColorTransform', 1, s.fields(
                'alphaOffset', 'Float',
                'redMultiplier', 'Float',
                'redOffset', 'Float',
                'greenMultiplier', 'Float',
                'greenOffset', 'Float',
                'blueMultiplier', 'Float',
                'blueOffset', 'Float'
            )),
            'effect', s.condition('hasEffect', 1, s.array('Ubyte', gaf.Tag._readFilter(s))),
            'maskObjectIdRef', s.condition('hasMask', 1, function(){return s.Uint()})
        ))),
        'actions',  s.condition('hasActions', 1, s.array('Uint', s.fields(
            'type', 'Uint',
            'scope', 'String',
            'params', gaf.Tag._readActionArguments(s)
        )))
    ));
    return {'content': exec()};
};
gaf.Tag.DefineTimeline = Object.create(gaf.Tag.base);
gaf.Tag.DefineTimeline.tagName = "TagDefineTimeline";
gaf.Tag.DefineTimeline.doParse = function(s) {
    var exec = s.fields(
        'id', 'Uint',
        'animationFrameCount', 'Uint',
        'boundingBox', 'Rect',
        'pivotPoint', 'Point',
        'hasLinkage', 'Boolean',
        'linkageName', s.condition('hasLinkage', 1, function () {
            return s.String();
        })
    );
    var result = {'content': exec()};
    result.content.tags = gaf.ReadTags(s);
    return result;
};
gaf.Tag._readActionArguments = function(s){
    return function(){
        var size = s.Uint();
        var ret = [];
        s.startNestedBuffer(size);
        while(s.maxOffset() < s.tell()){
            ret.push(s.String());
        }
        s.endNestedBuffer();
        return ret;
    };
};
gaf.Tag._readFilter = function(s){
    return s.fields(
        'type', 'Uint',
        'dropShadow', s.condition('type', gaf.EFFECT_DROP_SHADOW, s.fields(
            'color', 'color',
            'blurX', 'Float',
            'blurY', 'Float',
            'angle', 'Float',
            'distance', 'Float',
            'strength', 'Float',
            'inner', 'Boolean',
            'knockout', 'Boolean'
        )),
        'blur', s.condition('type', gaf.EFFECT_BLUR, s.fields(
            'blurX', 'Float',
            'blurY', 'Float'
        )),
        'glow', s.condition('type', gaf.EFFECT_GLOW, s.fields(
            'color', 'color',
            'blurX', 'Float',
            'blurY', 'Float',
            'strength', 'Float',
            'inner', 'Boolean',
            'knockout', 'Boolean'
        )),
        'colorMatrix', s.condition('type', gaf.EFFECT_COLOR_MATRIX, s.fields(
            'rr', 'Float', 'gr', 'Float', 'br', 'Float', 'ar', 'Float', 'r', 'Float',
            'rg', 'Float', 'gg', 'Float', 'bg', 'Float', 'ag', 'Float', 'g', 'Float',
            'rb', 'Float', 'gb', 'Float', 'bb', 'Float', 'ab', 'Float', 'b', 'Float',
            'ra', 'Float', 'ga', 'Float', 'ba', 'Float', 'aa', 'Float', 'a', 'Float'
        ))
    )
};
gaf.Tags = new gaf.Tag();
var gaf = gaf || {};
gaf.Loader = function(){
    var readHeaderBegin = function(stream, header){
        header.compression = stream.Uint();
        header.versionMajor = stream.Ubyte();
        header.versionMinor = stream.Ubyte();
        header.fileLength = stream.Uint();
    };
    var readHeaderEndV3 = function(stream, header) {
        header.framesCount = stream.Ushort();
        header.frameSize = stream.Rect();
        header.pivot = stream.Point();
    };
    var readHeaderEndV4 = function(stream, header){
        var scaleCount = stream.Uint();
        header.scaleValues = [];
        for(var i = 0; i < scaleCount; ++i){
            header.scaleValues.push(stream.Float());
        }
        var csfCount = stream.Uint();
        header.csfValues = [];
        for(var i = 0; i < csfCount; ++i){
            header.csfValues.push(stream.Float());
        }
    };
    this.LoadFile = function(filePath, onLoaded){
        var oReq = new XMLHttpRequest();
        oReq.open("GET", filePath, true);
        var self = this;
        oReq.responseType = "arraybuffer";
        oReq.onload = function(oEvent) {
            var gaf_data = new gaf.DataReader(oReq.response);
            var gafFile = self.LoadStream(gaf_data);
            if(onLoaded)
                onLoaded(gafFile);
        };
        oReq.send();
    };
    this.LoadStream = function(stream){
        var header = {};
        readHeaderBegin(stream, header);
        if(header.compression == gaf.COMPRESSION_NONE) {
        }
        else if(header.compression == gaf.COMPRESSION_ZIP){
            var compressed = stream.dataRaw.slice(stream.tell());
            var inflate = new window.Zlib.Inflate(new Uint8Array(compressed));
            var decompressed = inflate.decompress();
            stream = new gaf.DataReader(decompressed.buffer);
        }
        else{
            throw new Error("GAF syntax error.");
        }
        if(header.versionMajor < 4){
            readHeaderEndV3(stream, header);
        }
        else{
            readHeaderEndV4(stream, header);
        }
        var tags = gaf.ReadTags(stream);
        return {
            header: header,
            tags: tags
        };
    };
};
gaf.DataReader = function(data) {
    this.dataRaw = data;
    this.buf = new DataView(data);
    this.offset = [0];
};
gaf.DataReader.prototype.constructor = gaf.DataReader;
gaf.DataReader.prototype.newOffset = function(size){
    this.offset[this.offset.length - 1] += size;
    if(this.getOffset() > this.maxOffset()){
        throw new Error("GAF format error");
    }
    return this.offset[this.offset.length - 1] - size;
};
gaf.DataReader.prototype.maxOffset = function(){
    if(this.offset.length == 1){
        return this.buf.byteLength;
    }
    else{
        return this.offset[this.offset.length - 2];
    }
};
gaf.DataReader.prototype.getOffset = function(size){
    return this.offset[this.offset.length - 1];
};
gaf.DataReader.prototype.Ubyte = function() {
    return this.buf.getUint8(this.newOffset(1));
};
gaf.DataReader.prototype.Boolean = function() {
    var result = this.buf.getUint8(this.newOffset(1));
    if(result > 1){
        throw new Error("GAF format error");
    }
    return result;
};
gaf.DataReader.prototype.Uint = function() {
    return this.buf.getUint32(this.newOffset(4), true);
};
gaf.DataReader.prototype.Int = function() {
    return this.buf.getInt32(this.newOffset(4), true);
};
gaf.DataReader.prototype.color = function() {
    return {
        b: this.Ubyte(),
        g: this.Ubyte(),
        r: this.Ubyte(),
        a: this.Ubyte()
    };
};
gaf.DataReader.prototype.Ushort = function() {
    return this.buf.getUint16(this.newOffset(2), true);
};
gaf.DataReader.prototype.Float = function() {
    return this.buf.getFloat32(this.newOffset(4), true);
};
gaf.DataReader.prototype.String = function() {
    var strLen = this.Ushort();
    var from = this.newOffset(strLen);
    var to = this.getOffset();
    try
    {
        var str = this.dataRaw.slice(from, to);
    }
    catch(e)
    {
        if(e.message == "Object doesn't support property or method 'slice'")
        {
            str = [];
            for(var i = from; i < to; ++i)
                str.push(this.buf.getUint8(i));
        }
        else
        {
            throw(e);
        }
    }
    return decodeURIComponent(escape(String.fromCharCode.apply(null, new Uint8Array(str))));
};
gaf.DataReader.prototype.startNestedBuffer = function(length) {
    this.offset.push(this.offset[this.offset.length-1]);
    this.offset[this.offset.length-2] += length;
};
gaf.DataReader.prototype.endNestedBuffer = function() {
    if (this.offset.length == 1) throw new Error('No nested buffer available');
    this.offset.pop();
};
gaf.DataReader.prototype.Point = function(){
    return {
        x: this.Float(),
        y: this.Float()
    };
};
gaf.DataReader.prototype.Rect = function(){
    return {
        x: this.Float(),
        y: this.Float(),
        width: this.Float(),
        height: this.Float()
    };
};
gaf.DataReader.prototype.Matrix = function(){
    return {
        a: this.Float(),
        b: this.Float(),
        c: this.Float(),
        d: this.Float(),
        tx: this.Float(),
        ty: this.Float()
    };
};
gaf.DataReader.prototype.seek = function(pos){
    this.offset[this.offset.length-1] = pos;
};
gaf.DataReader.prototype.tell = function(){
    return this.offset[this.offset.length-1];
};
gaf.DataReader.prototype.fields = function(){
    var self = this;
    var arguments_ = arguments;
    return function(){
        arguments.callee.result = {};
        var i = 0;
        if(arguments_.length % 2){
            throw new Error('Number of arguments is not even');
        }
        while(i < arguments_.length){
            var field = arguments_[i++];
            var func = arguments_[i++];
            if(typeof func === 'function'){
                arguments.callee.result[field] = func();
            }
            else if (func in self && typeof self[func] === 'function'){
                arguments.callee.result[field] = self[func].call(self);
            }
            else{
                throw new Error('Object DataReader has no function `' + func + '`');
            }
        }
        return arguments.callee.result;
    }
};
gaf.DataReader.prototype.condition = function(key, value, func){
    var arguments_ = arguments;
    return function() {
        if(arguments_.length != 3){
            throw new Error('Condition function');
        }
        var parent = arguments.callee.caller;
        if(!('result' in parent)){
            throw new Error('Condition function caller has no key `result`');
        }
        var container = parent.result;
        var field = arguments_[0];
        var value = arguments_[1];
        var exec = arguments_[2];
        var evaluate = null;
        if(typeof value === 'function'){
            evaluate = function(){return value(container[field]);};
        }
        else{
            evaluate = function(){return value == container[field];};
        }
        if(evaluate()){
            return exec();
        }
        else{
            return null;
        }
    }
};
gaf.DataReader.prototype.array = function(){
    var self = this;
    var arguments_ = arguments;
    return function() {
        arguments.callee.result = [];
        var length = self[arguments_[0]].call(self);
        for (var i = 0; i < length; ++i) {
            var r = arguments_[1].call();
            arguments.callee.result.push(r);
        }
        return arguments.callee.result;
    }
};
gaf.SHADER_GAUSSIAN_BLUR_FRAG =
    "varying mediump vec2 v_texCoord;\n"
    + "uniform mediump vec2 u_step;\n"
    + "void main()\n"
    + "{ \n"
    + "    mediump vec4 sum = vec4(0.0);                                      \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 4.0) * 0.05;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 3.0) * 0.09;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 2.0) * 0.12;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 1.0) * 0.15;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 0.0) * 0.18;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 1.0) * 0.15;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 2.0) * 0.12;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 3.0) * 0.09;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 4.0) * 0.05;   \n"
    + "    gl_FragColor = sum;                                                \n"
    + "} \n";
gaf.SHADER_GLOW_FRAG =
    "varying mediump vec2 v_texCoord;\n"
    + "uniform mediump vec2 u_step;\n"
    + "uniform mediump vec4 u_glowColor;\n"
    + "void main()\n"
    + "{ \n"
    + "    mediump vec4 sum = vec4(0.0);                                      \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 4.0) * 0.05;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 3.0) * 0.09;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 2.0) * 0.12;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord - u_step * 1.0) * 0.15;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 0.0) * 0.18;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 1.0) * 0.15;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 2.0) * 0.12;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 3.0) * 0.09;   \n"
    + "    sum += texture2D(CC_Texture0, v_texCoord + u_step * 4.0) * 0.05;   \n"
    + "    gl_FragColor = sum * u_glowColor;                                  \n"
    + "} \n";
gaf.SHADER_COLOR_MATRIX_FRAG =
    "varying mediump vec2 v_texCoord;\n"
    + "varying mediump vec4 v_fragmentColor;\n"
    + "uniform mediump vec4 colorTransformMult;\n"
    + "uniform mediump vec4 colorTransformOffsets;\n"
    + "uniform mediump mat4 colorMatrix;\n"
    + "uniform mediump vec4 colorMatrix2;\n"
    + "void main()\n"
    + "{ \n"
    + "    vec4 texColor = texture2D(CC_Texture0, v_texCoord);                          \n"
    + "    const float kMinimalAlphaAllowed = 1.0e-8;                                   \n"
    + "    if (texColor.a > kMinimalAlphaAllowed)                                       \n"
    + "    {                                                                            \n"
    + "        texColor = vec4(texColor.rgb / texColor.a, texColor.a);                  \n"
    + "        vec4 ctxColor = texColor * colorTransformMult + colorTransformOffsets;   \n"
    + "        vec4 adjustColor = colorMatrix * ctxColor + colorMatrix2;                \n"
    + "        adjustColor *= v_fragmentColor;                                          \n"
    + "        texColor = vec4(adjustColor.rgb * adjustColor.a, adjustColor.a);         \n"
    + "    }                                                                            \n"
    + "    gl_FragColor = texColor;                                                     \n"
    + "}\n";
gaf._glShaderInit = function() {
    gaf._Uniforms = {
        ColorTransformMult: -1,
        ColorTransformOffset: -1,
        ColorMatrixBody: -1,
        ColorMatrixAppendix: -1,
        BlurTexelOffset: -1,
        GlowTexelOffset: -1,
        GlowColor: -1
    };
    gaf._shaderCreate = function (fs, vs) {
        var program = new cc.GLProgram();
        var result = program.initWithVertexShaderByteArray(vs, fs);
        cc.assert(result, "Shader init error");
        program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
        program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
        program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
        result = program.link();
        cc.assert(result, "Shader linking error");
        program.updateUniforms();
        return program;
    };
    gaf._shaderCreateAlpha = function () {
        var program = gaf._shaderCreate(gaf.SHADER_COLOR_MATRIX_FRAG, cc.SHADER_POSITION_TEXTURE_COLOR_VERT);
        gaf._Uniforms.ColorTransformMult = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_TINT_MULT);
        gaf._Uniforms.ColorTransformOffset = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_TINT_OFFSET);
        gaf._Uniforms.ColorMatrixBody = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_COLOR_MATRIX_BODY);
        gaf._Uniforms.ColorMatrixAppendix = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_COLOR_MATRIX_APPENDIX);
        return program;
    };
    gaf._shaderCreateBlur = function () {
        var program = gaf._shaderCreate(gaf.SHADER_GAUSSIAN_BLUR_FRAG, cc.SHADER_POSITION_TEXTURE_COLOR_VERT);
        gaf._Uniforms.BlurTexelOffset = program._glContext.getUniformLocation(program._programObj, gaf.UNIFORM_BLUR_TEXEL_OFFSET);
        return program;
    };
    gaf._shaderCreateGlow = function () {
        var program = gaf._shaderCreate(gaf.SHADER_GLOW_FRAG, cc.SHADER_POSITION_TEXTURE_COLOR_VERT);
        gaf._Uniforms.GlowTexelOffset = program._glContext.getUniformLocation(program._programObj, gaf.UNIFORM_GLOW_TEXEL_OFFSET);
        gaf._Uniforms.GlowColor = program._glContext.getUniformLocation(program._programObj, gaf.UNIFORM_GLOW_COLOR);
        return program;
    };
    gaf._Shaders = {
        Alpha: gaf._shaderCreateAlpha(),
        Blur: gaf._shaderCreateBlur(),
        Glow: gaf._shaderCreateGlow()
    };
};
gaf._setupShaders = function() {
    if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
        gaf._glShaderInit();
    }
    else {
        delete gaf._glShaderInit;
    }
};
gaf._AtlasLoader = {};
gaf._AtlasLoader.execute = function(condition, success, fail)
{
    condition() ? success() : fail();
};
gaf._AtlasLoader.checkAtlas = function(atlas)
{
    return function(){return atlas && typeof atlas !== "string" && atlas.isLoaded()};
};
gaf._AtlasLoader.load = function(path, success, fail)
{
    cc.textureCache.addImage(path, function(atlas){
        gaf._AtlasLoader.execute(
            gaf._AtlasLoader.checkAtlas(atlas),
            function(){success(atlas)},
            fail
        );
    });
};
gaf._AtlasLoader.loadFront = function(arr, success, fail)
{
    return function()
    {
        if (arr.length > 0){
            gaf._AtlasLoader.load(
                arr[0],
                success,
                gaf._AtlasLoader.loadFront(
                    arr.slice(1),
                    success,
                    fail
        ));}
        else
            fail();
    }
};
gaf._AtlasLoader.loadArray = function(array, success, fail)
{
    gaf._AtlasLoader.loadFront(array, success, fail)();
};
var Box2D = {};
(function (a2j, undefined) {
    if(!(Object.defineProperty instanceof Function)
        && Object.prototype.__defineGetter__ instanceof Function
        && Object.prototype.__defineSetter__ instanceof Function)
    {
        Object.defineProperty = function(obj, p, cfg) {
            if(cfg.get instanceof Function)
                obj.__defineGetter__(p, cfg.get);
            if(cfg.set instanceof Function)
                obj.__defineSetter__(p, cfg.set);
        }
    }
    function emptyFn() {};
    a2j.inherit = function(cls, base) {
        var tmpCtr = cls;
        emptyFn.prototype = base.prototype;
        cls.prototype = new emptyFn;
        cls.prototype.constructor = tmpCtr;
    };
    a2j.generateCallback = function generateCallback(context, cb) {
        return function () {
            cb.apply(context, arguments);
        };
    };
    a2j.NVector = function NVector(length) {
        if (length === undefined) length = 0;
        var tmp = new Array(length || 0);
        for (var i = 0; i < length; ++i)
            tmp[i] = 0;
        return tmp;
    };
    a2j.is = function is(o1, o2) {
        if (o1 === null) return false;
        if ((o2 instanceof Function) && (o1 instanceof o2)) return true;
        if ((o1.constructor.__implements != undefined) && (o1.constructor.__implements[o2])) return true;
        return false;
    };
    a2j.parseUInt = function(v) {
        return Math.abs(parseInt(v));
    }
})(Box2D);
var Vector = Array;
var Vector_a2j_Number = Box2D.NVector;
if (typeof(Box2D) === "undefined") Box2D = {};
if (typeof(Box2D.Collision) === "undefined") Box2D.Collision = {};
if (typeof(Box2D.Collision.Shapes) === "undefined") Box2D.Collision.Shapes = {};
if (typeof(Box2D.Common) === "undefined") Box2D.Common = {};
if (typeof(Box2D.Common.Math) === "undefined") Box2D.Common.Math = {};
if (typeof(Box2D.Dynamics) === "undefined") Box2D.Dynamics = {};
if (typeof(Box2D.Dynamics.Contacts) === "undefined") Box2D.Dynamics.Contacts = {};
if (typeof(Box2D.Dynamics.Controllers) === "undefined") Box2D.Dynamics.Controllers = {};
if (typeof(Box2D.Dynamics.Joints) === "undefined") Box2D.Dynamics.Joints = {};
(function () {
    Box2D.Collision.IBroadPhase = 'Box2D.Collision.IBroadPhase';
    function b2AABB() {
        b2AABB.b2AABB.apply(this, arguments);
    };
    Box2D.Collision.b2AABB = b2AABB;
    function b2Bound() {
        b2Bound.b2Bound.apply(this, arguments);
    };
    Box2D.Collision.b2Bound = b2Bound;
    function b2BoundValues() {
        b2BoundValues.b2BoundValues.apply(this, arguments);
        if (this.constructor === b2BoundValues) this.b2BoundValues.apply(this, arguments);
    };
    Box2D.Collision.b2BoundValues = b2BoundValues;
    function b2Collision() {
        b2Collision.b2Collision.apply(this, arguments);
    };
    Box2D.Collision.b2Collision = b2Collision;
    function b2ContactID() {
        b2ContactID.b2ContactID.apply(this, arguments);
        if (this.constructor === b2ContactID) this.b2ContactID.apply(this, arguments);
    };
    Box2D.Collision.b2ContactID = b2ContactID;
    function b2ContactPoint() {
        b2ContactPoint.b2ContactPoint.apply(this, arguments);
    };
    Box2D.Collision.b2ContactPoint = b2ContactPoint;
    function b2Distance() {
        b2Distance.b2Distance.apply(this, arguments);
    };
    Box2D.Collision.b2Distance = b2Distance;
    function b2DistanceInput() {
        b2DistanceInput.b2DistanceInput.apply(this, arguments);
    };
    Box2D.Collision.b2DistanceInput = b2DistanceInput;
    function b2DistanceOutput() {
        b2DistanceOutput.b2DistanceOutput.apply(this, arguments);
    };
    Box2D.Collision.b2DistanceOutput = b2DistanceOutput;
    function b2DistanceProxy() {
        b2DistanceProxy.b2DistanceProxy.apply(this, arguments);
    };
    Box2D.Collision.b2DistanceProxy = b2DistanceProxy;
    function b2DynamicTree() {
        b2DynamicTree.b2DynamicTree.apply(this, arguments);
        if (this.constructor === b2DynamicTree) this.b2DynamicTree.apply(this, arguments);
    };
    Box2D.Collision.b2DynamicTree = b2DynamicTree;
    function b2DynamicTreeBroadPhase() {
        b2DynamicTreeBroadPhase.b2DynamicTreeBroadPhase.apply(this, arguments);
    };
    Box2D.Collision.b2DynamicTreeBroadPhase = b2DynamicTreeBroadPhase;
    function b2DynamicTreeNode() {
        b2DynamicTreeNode.b2DynamicTreeNode.apply(this, arguments);
    };
    Box2D.Collision.b2DynamicTreeNode = b2DynamicTreeNode;
    function b2DynamicTreePair() {
        b2DynamicTreePair.b2DynamicTreePair.apply(this, arguments);
    };
    Box2D.Collision.b2DynamicTreePair = b2DynamicTreePair;
    function b2Manifold() {
        b2Manifold.b2Manifold.apply(this, arguments);
        if (this.constructor === b2Manifold) this.b2Manifold.apply(this, arguments);
    };
    Box2D.Collision.b2Manifold = b2Manifold;
    function b2ManifoldPoint() {
        b2ManifoldPoint.b2ManifoldPoint.apply(this, arguments);
        if (this.constructor === b2ManifoldPoint) this.b2ManifoldPoint.apply(this, arguments);
    };
    Box2D.Collision.b2ManifoldPoint = b2ManifoldPoint;
    function b2Point() {
        b2Point.b2Point.apply(this, arguments);
    };
    Box2D.Collision.b2Point = b2Point;
    function b2RayCastInput() {
        b2RayCastInput.b2RayCastInput.apply(this, arguments);
        if (this.constructor === b2RayCastInput) this.b2RayCastInput.apply(this, arguments);
    };
    Box2D.Collision.b2RayCastInput = b2RayCastInput;
    function b2RayCastOutput() {
        b2RayCastOutput.b2RayCastOutput.apply(this, arguments);
    };
    Box2D.Collision.b2RayCastOutput = b2RayCastOutput;
    function b2Segment() {
        b2Segment.b2Segment.apply(this, arguments);
    };
    Box2D.Collision.b2Segment = b2Segment;
    function b2SeparationFunction() {
        b2SeparationFunction.b2SeparationFunction.apply(this, arguments);
    };
    Box2D.Collision.b2SeparationFunction = b2SeparationFunction;
    function b2Simplex() {
        b2Simplex.b2Simplex.apply(this, arguments);
        if (this.constructor === b2Simplex) this.b2Simplex.apply(this, arguments);
    };
    Box2D.Collision.b2Simplex = b2Simplex;
    function b2SimplexCache() {
        b2SimplexCache.b2SimplexCache.apply(this, arguments);
    };
    Box2D.Collision.b2SimplexCache = b2SimplexCache;
    function b2SimplexVertex() {
        b2SimplexVertex.b2SimplexVertex.apply(this, arguments);
    };
    Box2D.Collision.b2SimplexVertex = b2SimplexVertex;
    function b2TimeOfImpact() {
        b2TimeOfImpact.b2TimeOfImpact.apply(this, arguments);
    };
    Box2D.Collision.b2TimeOfImpact = b2TimeOfImpact;
    function b2TOIInput() {
        b2TOIInput.b2TOIInput.apply(this, arguments);
    };
    Box2D.Collision.b2TOIInput = b2TOIInput;
    function b2WorldManifold() {
        b2WorldManifold.b2WorldManifold.apply(this, arguments);
        if (this.constructor === b2WorldManifold) this.b2WorldManifold.apply(this, arguments);
    };
    Box2D.Collision.b2WorldManifold = b2WorldManifold;
    function ClipVertex() {
        ClipVertex.ClipVertex.apply(this, arguments);
    };
    Box2D.Collision.ClipVertex = ClipVertex;
    function Features() {
        Features.Features.apply(this, arguments);
    };
    Box2D.Collision.Features = Features;
    function b2CircleShape() {
        b2CircleShape.b2CircleShape.apply(this, arguments);
        if (this.constructor === b2CircleShape) this.b2CircleShape.apply(this, arguments);
    };
    Box2D.Collision.Shapes.b2CircleShape = b2CircleShape;
    function b2EdgeChainDef() {
        b2EdgeChainDef.b2EdgeChainDef.apply(this, arguments);
        if (this.constructor === b2EdgeChainDef) this.b2EdgeChainDef.apply(this, arguments);
    };
    Box2D.Collision.Shapes.b2EdgeChainDef = b2EdgeChainDef;
    function b2EdgeShape() {
        b2EdgeShape.b2EdgeShape.apply(this, arguments);
        if (this.constructor === b2EdgeShape) this.b2EdgeShape.apply(this, arguments);
    };
    Box2D.Collision.Shapes.b2EdgeShape = b2EdgeShape;
    function b2MassData() {
        b2MassData.b2MassData.apply(this, arguments);
    };
    Box2D.Collision.Shapes.b2MassData = b2MassData;
    function b2PolygonShape() {
        b2PolygonShape.b2PolygonShape.apply(this, arguments);
        if (this.constructor === b2PolygonShape) this.b2PolygonShape.apply(this, arguments);
    };
    Box2D.Collision.Shapes.b2PolygonShape = b2PolygonShape;
    function b2Shape() {
        b2Shape.b2Shape.apply(this, arguments);
        if (this.constructor === b2Shape) this.b2Shape.apply(this, arguments);
    };
    Box2D.Collision.Shapes.b2Shape = b2Shape;
    Box2D.Common.b2internal = 'Box2D.Common.b2internal';
    function b2Color() {
        b2Color.b2Color.apply(this, arguments);
        if (this.constructor === b2Color) this.b2Color.apply(this, arguments);
    };
    Box2D.Common.b2Color = b2Color;
    function b2Settings() {
        b2Settings.b2Settings.apply(this, arguments);
    };
    Box2D.Common.b2Settings = b2Settings;
    function b2Mat22() {
        b2Mat22.b2Mat22.apply(this, arguments);
        if (this.constructor === b2Mat22) this.b2Mat22.apply(this, arguments);
    };
    Box2D.Common.Math.b2Mat22 = b2Mat22;
    function b2Mat33() {
        b2Mat33.b2Mat33.apply(this, arguments);
        if (this.constructor === b2Mat33) this.b2Mat33.apply(this, arguments);
    };
    Box2D.Common.Math.b2Mat33 = b2Mat33;
    function b2Math() {
        b2Math.b2Math.apply(this, arguments);
    };
    Box2D.Common.Math.b2Math = b2Math;
    function b2Sweep() {
        b2Sweep.b2Sweep.apply(this, arguments);
    };
    Box2D.Common.Math.b2Sweep = b2Sweep;
    function b2Transform() {
        b2Transform.b2Transform.apply(this, arguments);
        if (this.constructor === b2Transform) this.b2Transform.apply(this, arguments);
    };
    Box2D.Common.Math.b2Transform = b2Transform;
    function b2Vec2() {
        b2Vec2.b2Vec2.apply(this, arguments);
        if (this.constructor === b2Vec2) this.b2Vec2.apply(this, arguments);
    };
    Box2D.Common.Math.b2Vec2 = b2Vec2;
    function b2Vec3() {
        b2Vec3.b2Vec3.apply(this, arguments);
        if (this.constructor === b2Vec3) this.b2Vec3.apply(this, arguments);
    };
    Box2D.Common.Math.b2Vec3 = b2Vec3;
    function b2Body() {
        b2Body.b2Body.apply(this, arguments);
        if (this.constructor === b2Body) this.b2Body.apply(this, arguments);
    };
    Box2D.Dynamics.b2Body = b2Body;
    function b2BodyDef() {
        b2BodyDef.b2BodyDef.apply(this, arguments);
        if (this.constructor === b2BodyDef) this.b2BodyDef.apply(this, arguments);
    };
    Box2D.Dynamics.b2BodyDef = b2BodyDef;
    function b2ContactFilter() {
        b2ContactFilter.b2ContactFilter.apply(this, arguments);
    };
    Box2D.Dynamics.b2ContactFilter = b2ContactFilter;
    function b2ContactImpulse() {
        b2ContactImpulse.b2ContactImpulse.apply(this, arguments);
    };
    Box2D.Dynamics.b2ContactImpulse = b2ContactImpulse;
    function b2ContactListener() {
        b2ContactListener.b2ContactListener.apply(this, arguments);
    };
    Box2D.Dynamics.b2ContactListener = b2ContactListener;
    function b2ContactManager() {
        b2ContactManager.b2ContactManager.apply(this, arguments);
        if (this.constructor === b2ContactManager) this.b2ContactManager.apply(this, arguments);
    };
    Box2D.Dynamics.b2ContactManager = b2ContactManager;
    function b2DebugDraw() {
        b2DebugDraw.b2DebugDraw.apply(this, arguments);
        if (this.constructor === b2DebugDraw) this.b2DebugDraw.apply(this, arguments);
    };
    Box2D.Dynamics.b2DebugDraw = b2DebugDraw;
    function b2DestructionListener() {
        b2DestructionListener.b2DestructionListener.apply(this, arguments);
    };
    Box2D.Dynamics.b2DestructionListener = b2DestructionListener;
    function b2FilterData() {
        b2FilterData.b2FilterData.apply(this, arguments);
    };
    Box2D.Dynamics.b2FilterData = b2FilterData;
    function b2Fixture() {
        b2Fixture.b2Fixture.apply(this, arguments);
        if (this.constructor === b2Fixture) this.b2Fixture.apply(this, arguments);
    };
    Box2D.Dynamics.b2Fixture = b2Fixture;
    function b2FixtureDef() {
        b2FixtureDef.b2FixtureDef.apply(this, arguments);
        if (this.constructor === b2FixtureDef) this.b2FixtureDef.apply(this, arguments);
    };
    Box2D.Dynamics.b2FixtureDef = b2FixtureDef;
    function b2Island() {
        b2Island.b2Island.apply(this, arguments);
        if (this.constructor === b2Island) this.b2Island.apply(this, arguments);
    };
    Box2D.Dynamics.b2Island = b2Island;
    function b2TimeStep() {
        b2TimeStep.b2TimeStep.apply(this, arguments);
    };
    Box2D.Dynamics.b2TimeStep = b2TimeStep;
    function b2World() {
        b2World.b2World.apply(this, arguments);
        if (this.constructor === b2World) this.b2World.apply(this, arguments);
    };
    Box2D.Dynamics.b2World = b2World;
    function b2CircleContact() {
        b2CircleContact.b2CircleContact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2CircleContact = b2CircleContact;
    function b2Contact() {
        b2Contact.b2Contact.apply(this, arguments);
        if (this.constructor === b2Contact) this.b2Contact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2Contact = b2Contact;
    function b2ContactConstraint() {
        b2ContactConstraint.b2ContactConstraint.apply(this, arguments);
        if (this.constructor === b2ContactConstraint) this.b2ContactConstraint.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactConstraint = b2ContactConstraint;
    function b2ContactConstraintPoint() {
        b2ContactConstraintPoint.b2ContactConstraintPoint.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactConstraintPoint = b2ContactConstraintPoint;
    function b2ContactEdge() {
        b2ContactEdge.b2ContactEdge.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactEdge = b2ContactEdge;
    function b2ContactFactory() {
        b2ContactFactory.b2ContactFactory.apply(this, arguments);
        if (this.constructor === b2ContactFactory) this.b2ContactFactory.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactFactory = b2ContactFactory;
    function b2ContactRegister() {
        b2ContactRegister.b2ContactRegister.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactRegister = b2ContactRegister;
    function b2ContactResult() {
        b2ContactResult.b2ContactResult.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactResult = b2ContactResult;
    function b2ContactSolver() {
        b2ContactSolver.b2ContactSolver.apply(this, arguments);
        if (this.constructor === b2ContactSolver) this.b2ContactSolver.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2ContactSolver = b2ContactSolver;
    function b2EdgeAndCircleContact() {
        b2EdgeAndCircleContact.b2EdgeAndCircleContact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2EdgeAndCircleContact = b2EdgeAndCircleContact;
    function b2NullContact() {
        b2NullContact.b2NullContact.apply(this, arguments);
        if (this.constructor === b2NullContact) this.b2NullContact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2NullContact = b2NullContact;
    function b2PolyAndCircleContact() {
        b2PolyAndCircleContact.b2PolyAndCircleContact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2PolyAndCircleContact = b2PolyAndCircleContact;
    function b2PolyAndEdgeContact() {
        b2PolyAndEdgeContact.b2PolyAndEdgeContact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2PolyAndEdgeContact = b2PolyAndEdgeContact;
    function b2PolygonContact() {
        b2PolygonContact.b2PolygonContact.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2PolygonContact = b2PolygonContact;
    function b2PositionSolverManifold() {
        b2PositionSolverManifold.b2PositionSolverManifold.apply(this, arguments);
        if (this.constructor === b2PositionSolverManifold) this.b2PositionSolverManifold.apply(this, arguments);
    };
    Box2D.Dynamics.Contacts.b2PositionSolverManifold = b2PositionSolverManifold;
    function b2BuoyancyController() {
        b2BuoyancyController.b2BuoyancyController.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2BuoyancyController = b2BuoyancyController;
    function b2ConstantAccelController() {
        b2ConstantAccelController.b2ConstantAccelController.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2ConstantAccelController = b2ConstantAccelController;
    function b2ConstantForceController() {
        b2ConstantForceController.b2ConstantForceController.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2ConstantForceController = b2ConstantForceController;
    function b2Controller() {
        b2Controller.b2Controller.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2Controller = b2Controller;
    function b2ControllerEdge() {
        b2ControllerEdge.b2ControllerEdge.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2ControllerEdge = b2ControllerEdge;
    function b2GravityController() {
        b2GravityController.b2GravityController.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2GravityController = b2GravityController;
    function b2TensorDampingController() {
        b2TensorDampingController.b2TensorDampingController.apply(this, arguments);
    };
    Box2D.Dynamics.Controllers.b2TensorDampingController = b2TensorDampingController;
    function b2DistanceJoint() {
        b2DistanceJoint.b2DistanceJoint.apply(this, arguments);
        if (this.constructor === b2DistanceJoint) this.b2DistanceJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2DistanceJoint = b2DistanceJoint;
    function b2DistanceJointDef() {
        b2DistanceJointDef.b2DistanceJointDef.apply(this, arguments);
        if (this.constructor === b2DistanceJointDef) this.b2DistanceJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2DistanceJointDef = b2DistanceJointDef;
    function b2FrictionJoint() {
        b2FrictionJoint.b2FrictionJoint.apply(this, arguments);
        if (this.constructor === b2FrictionJoint) this.b2FrictionJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2FrictionJoint = b2FrictionJoint;
    function b2FrictionJointDef() {
        b2FrictionJointDef.b2FrictionJointDef.apply(this, arguments);
        if (this.constructor === b2FrictionJointDef) this.b2FrictionJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2FrictionJointDef = b2FrictionJointDef;
    function b2GearJoint() {
        b2GearJoint.b2GearJoint.apply(this, arguments);
        if (this.constructor === b2GearJoint) this.b2GearJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2GearJoint = b2GearJoint;
    function b2GearJointDef() {
        b2GearJointDef.b2GearJointDef.apply(this, arguments);
        if (this.constructor === b2GearJointDef) this.b2GearJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2GearJointDef = b2GearJointDef;
    function b2Jacobian() {
        b2Jacobian.b2Jacobian.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2Jacobian = b2Jacobian;
    function b2Joint() {
        b2Joint.b2Joint.apply(this, arguments);
        if (this.constructor === b2Joint) this.b2Joint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2Joint = b2Joint;
    function b2JointDef() {
        b2JointDef.b2JointDef.apply(this, arguments);
        if (this.constructor === b2JointDef) this.b2JointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2JointDef = b2JointDef;
    function b2JointEdge() {
        b2JointEdge.b2JointEdge.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2JointEdge = b2JointEdge;
    function b2LineJoint() {
        b2LineJoint.b2LineJoint.apply(this, arguments);
        if (this.constructor === b2LineJoint) this.b2LineJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2LineJoint = b2LineJoint;
    function b2LineJointDef() {
        b2LineJointDef.b2LineJointDef.apply(this, arguments);
        if (this.constructor === b2LineJointDef) this.b2LineJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2LineJointDef = b2LineJointDef;
    function b2MouseJoint() {
        b2MouseJoint.b2MouseJoint.apply(this, arguments);
        if (this.constructor === b2MouseJoint) this.b2MouseJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2MouseJoint = b2MouseJoint;
    function b2MouseJointDef() {
        b2MouseJointDef.b2MouseJointDef.apply(this, arguments);
        if (this.constructor === b2MouseJointDef) this.b2MouseJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2MouseJointDef = b2MouseJointDef;
    function b2PrismaticJoint() {
        b2PrismaticJoint.b2PrismaticJoint.apply(this, arguments);
        if (this.constructor === b2PrismaticJoint) this.b2PrismaticJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2PrismaticJoint = b2PrismaticJoint;
    function b2PrismaticJointDef() {
        b2PrismaticJointDef.b2PrismaticJointDef.apply(this, arguments);
        if (this.constructor === b2PrismaticJointDef) this.b2PrismaticJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2PrismaticJointDef = b2PrismaticJointDef;
    function b2PulleyJoint() {
        b2PulleyJoint.b2PulleyJoint.apply(this, arguments);
        if (this.constructor === b2PulleyJoint) this.b2PulleyJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2PulleyJoint = b2PulleyJoint;
    function b2PulleyJointDef() {
        b2PulleyJointDef.b2PulleyJointDef.apply(this, arguments);
        if (this.constructor === b2PulleyJointDef) this.b2PulleyJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2PulleyJointDef = b2PulleyJointDef;
    function b2RevoluteJoint() {
        b2RevoluteJoint.b2RevoluteJoint.apply(this, arguments);
        if (this.constructor === b2RevoluteJoint) this.b2RevoluteJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2RevoluteJoint = b2RevoluteJoint;
    function b2RevoluteJointDef() {
        b2RevoluteJointDef.b2RevoluteJointDef.apply(this, arguments);
        if (this.constructor === b2RevoluteJointDef) this.b2RevoluteJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2RevoluteJointDef = b2RevoluteJointDef;
    function b2WeldJoint() {
        b2WeldJoint.b2WeldJoint.apply(this, arguments);
        if (this.constructor === b2WeldJoint) this.b2WeldJoint.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2WeldJoint = b2WeldJoint;
    function b2WeldJointDef() {
        b2WeldJointDef.b2WeldJointDef.apply(this, arguments);
        if (this.constructor === b2WeldJointDef) this.b2WeldJointDef.apply(this, arguments);
    };
    Box2D.Dynamics.Joints.b2WeldJointDef = b2WeldJointDef;
})();
Box2D.postDefs = [];
(function () {
    var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
        b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
        b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
        b2MassData = Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
        b2Shape = Box2D.Collision.Shapes.b2Shape,
        b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3,
        b2AABB = Box2D.Collision.b2AABB,
        b2Bound = Box2D.Collision.b2Bound,
        b2BoundValues = Box2D.Collision.b2BoundValues,
        b2Collision = Box2D.Collision.b2Collision,
        b2ContactID = Box2D.Collision.b2ContactID,
        b2ContactPoint = Box2D.Collision.b2ContactPoint,
        b2Distance = Box2D.Collision.b2Distance,
        b2DistanceInput = Box2D.Collision.b2DistanceInput,
        b2DistanceOutput = Box2D.Collision.b2DistanceOutput,
        b2DistanceProxy = Box2D.Collision.b2DistanceProxy,
        b2DynamicTree = Box2D.Collision.b2DynamicTree,
        b2DynamicTreeBroadPhase = Box2D.Collision.b2DynamicTreeBroadPhase,
        b2DynamicTreeNode = Box2D.Collision.b2DynamicTreeNode,
        b2DynamicTreePair = Box2D.Collision.b2DynamicTreePair,
        b2Manifold = Box2D.Collision.b2Manifold,
        b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint,
        b2Point = Box2D.Collision.b2Point,
        b2RayCastInput = Box2D.Collision.b2RayCastInput,
        b2RayCastOutput = Box2D.Collision.b2RayCastOutput,
        b2Segment = Box2D.Collision.b2Segment,
        b2SeparationFunction = Box2D.Collision.b2SeparationFunction,
        b2Simplex = Box2D.Collision.b2Simplex,
        b2SimplexCache = Box2D.Collision.b2SimplexCache,
        b2SimplexVertex = Box2D.Collision.b2SimplexVertex,
        b2TimeOfImpact = Box2D.Collision.b2TimeOfImpact,
        b2TOIInput = Box2D.Collision.b2TOIInput,
        b2WorldManifold = Box2D.Collision.b2WorldManifold,
        ClipVertex = Box2D.Collision.ClipVertex,
        Features = Box2D.Collision.Features,
        IBroadPhase = Box2D.Collision.IBroadPhase;
    b2AABB.b2AABB = function () {
        this.lowerBound = new b2Vec2();
        this.upperBound = new b2Vec2();
    };
    b2AABB.prototype.IsValid = function () {
        var dX = this.upperBound.x - this.lowerBound.x;
        var dY = this.upperBound.y - this.lowerBound.y;
        var valid = dX >= 0.0 && dY >= 0.0;
        valid = valid && this.lowerBound.IsValid() && this.upperBound.IsValid();
        return valid;
    }
    b2AABB.prototype.GetCenter = function () {
        return new b2Vec2((this.lowerBound.x + this.upperBound.x) / 2, (this.lowerBound.y + this.upperBound.y) / 2);
    }
    b2AABB.prototype.GetExtents = function () {
        return new b2Vec2((this.upperBound.x - this.lowerBound.x) / 2, (this.upperBound.y - this.lowerBound.y) / 2);
    }
    b2AABB.prototype.Contains = function (aabb) {
        var result = true;
        result = result && this.lowerBound.x <= aabb.lowerBound.x;
        result = result && this.lowerBound.y <= aabb.lowerBound.y;
        result = result && aabb.upperBound.x <= this.upperBound.x;
        result = result && aabb.upperBound.y <= this.upperBound.y;
        return result;
    }
    b2AABB.prototype.RayCast = function (output, input) {
        var tmin = (-Number.MAX_VALUE);
        var tmax = Number.MAX_VALUE;
        var pX = input.p1.x;
        var pY = input.p1.y;
        var dX = input.p2.x - input.p1.x;
        var dY = input.p2.y - input.p1.y;
        var absDX = Math.abs(dX);
        var absDY = Math.abs(dY);
        var normal = output.normal;
        var inv_d = 0;
        var t1 = 0;
        var t2 = 0;
        var t3 = 0;
        var s = 0; {
            if (absDX < Number.MIN_VALUE) {
                if (pX < this.lowerBound.x || this.upperBound.x < pX) return false;
            }
            else {
                inv_d = 1.0 / dX;
                t1 = (this.lowerBound.x - pX) * inv_d;
                t2 = (this.upperBound.x - pX) * inv_d;
                s = (-1.0);
                if (t1 > t2) {
                    t3 = t1;
                    t1 = t2;
                    t2 = t3;
                    s = 1.0;
                }
                if (t1 > tmin) {
                    normal.x = s;
                    normal.y = 0;
                    tmin = t1;
                }
                tmax = Math.min(tmax, t2);
                if (tmin > tmax) return false;
            }
        } {
            if (absDY < Number.MIN_VALUE) {
                if (pY < this.lowerBound.y || this.upperBound.y < pY) return false;
            }
            else {
                inv_d = 1.0 / dY;
                t1 = (this.lowerBound.y - pY) * inv_d;
                t2 = (this.upperBound.y - pY) * inv_d;
                s = (-1.0);
                if (t1 > t2) {
                    t3 = t1;
                    t1 = t2;
                    t2 = t3;
                    s = 1.0;
                }
                if (t1 > tmin) {
                    normal.y = s;
                    normal.x = 0;
                    tmin = t1;
                }
                tmax = Math.min(tmax, t2);
                if (tmin > tmax) return false;
            }
        }
        output.fraction = tmin;
        return true;
    }
    b2AABB.prototype.TestOverlap = function (other) {
        var d1X = other.lowerBound.x - this.upperBound.x;
        var d1Y = other.lowerBound.y - this.upperBound.y;
        var d2X = this.lowerBound.x - other.upperBound.x;
        var d2Y = this.lowerBound.y - other.upperBound.y;
        if (d1X > 0.0 || d1Y > 0.0) return false;
        if (d2X > 0.0 || d2Y > 0.0) return false;
        return true;
    }
    b2AABB.Combine = function (aabb1, aabb2) {
        var aabb = new b2AABB();
        aabb.Combine(aabb1, aabb2);
        return aabb;
    }
    b2AABB.prototype.Combine = function (aabb1, aabb2) {
        this.lowerBound.x = Math.min(aabb1.lowerBound.x, aabb2.lowerBound.x);
        this.lowerBound.y = Math.min(aabb1.lowerBound.y, aabb2.lowerBound.y);
        this.upperBound.x = Math.max(aabb1.upperBound.x, aabb2.upperBound.x);
        this.upperBound.y = Math.max(aabb1.upperBound.y, aabb2.upperBound.y);
    }
    b2Bound.b2Bound = function () {};
    b2Bound.prototype.IsLower = function () {
        return (this.value & 1) == 0;
    }
    b2Bound.prototype.IsUpper = function () {
        return (this.value & 1) == 1;
    }
    b2Bound.prototype.Swap = function (b) {
        var tempValue = this.value;
        var tempProxy = this.proxy;
        var tempStabbingCount = this.stabbingCount;
        this.value = b.value;
        this.proxy = b.proxy;
        this.stabbingCount = b.stabbingCount;
        b.value = tempValue;
        b.proxy = tempProxy;
        b.stabbingCount = tempStabbingCount;
    }
    b2BoundValues.b2BoundValues = function () {};
    b2BoundValues.prototype.b2BoundValues = function () {
        this.lowerValues = new Vector_a2j_Number();
        this.lowerValues[0] = 0.0;
        this.lowerValues[1] = 0.0;
        this.upperValues = new Vector_a2j_Number();
        this.upperValues[0] = 0.0;
        this.upperValues[1] = 0.0;
    }
    b2Collision.b2Collision = function () {};
    b2Collision.ClipSegmentToLine = function (vOut, vIn, normal, offset) {
        if (offset === undefined) offset = 0;
        var cv;
        var numOut = 0;
        cv = vIn[0];
        var vIn0 = cv.v;
        cv = vIn[1];
        var vIn1 = cv.v;
        var distance0 = normal.x * vIn0.x + normal.y * vIn0.y - offset;
        var distance1 = normal.x * vIn1.x + normal.y * vIn1.y - offset;
        if (distance0 <= 0.0) vOut[numOut++].Set(vIn[0]);
        if (distance1 <= 0.0) vOut[numOut++].Set(vIn[1]);
        if (distance0 * distance1 < 0.0) {
            var interp = distance0 / (distance0 - distance1);
            cv = vOut[numOut];
            var tVec = cv.v;
            tVec.x = vIn0.x + interp * (vIn1.x - vIn0.x);
            tVec.y = vIn0.y + interp * (vIn1.y - vIn0.y);
            cv = vOut[numOut];
            var cv2;
            if (distance0 > 0.0) {
                cv2 = vIn[0];
                cv.id = cv2.id;
            }
            else {
                cv2 = vIn[1];
                cv.id = cv2.id;
            }++numOut;
        }
        return numOut;
    }
    b2Collision.EdgeSeparation = function (poly1, xf1, edge1, poly2, xf2) {
        if (edge1 === undefined) edge1 = 0;
        var count1 = parseInt(poly1.m_vertexCount);
        var vertices1 = poly1.m_vertices;
        var normals1 = poly1.m_normals;
        var count2 = parseInt(poly2.m_vertexCount);
        var vertices2 = poly2.m_vertices;
        var tMat;
        var tVec;
        tMat = xf1.R;
        tVec = normals1[edge1];
        var normal1WorldX = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var normal1WorldY = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tMat = xf2.R;
        var normal1X = (tMat.col1.x * normal1WorldX + tMat.col1.y * normal1WorldY);
        var normal1Y = (tMat.col2.x * normal1WorldX + tMat.col2.y * normal1WorldY);
        var index = 0;
        var minDot = Number.MAX_VALUE;
        for (var i = 0; i < count2; ++i) {
            tVec = vertices2[i];
            var dot = tVec.x * normal1X + tVec.y * normal1Y;
            if (dot < minDot) {
                minDot = dot;
                index = i;
            }
        }
        tVec = vertices1[edge1];
        tMat = xf1.R;
        var v1X = xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var v1Y = xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tVec = vertices2[index];
        tMat = xf2.R;
        var v2X = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var v2Y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        v2X -= v1X;
        v2Y -= v1Y;
        var separation = v2X * normal1WorldX + v2Y * normal1WorldY;
        return separation;
    }
    b2Collision.FindMaxSeparation = function (edgeIndex, poly1, xf1, poly2, xf2) {
        var count1 = parseInt(poly1.m_vertexCount);
        var normals1 = poly1.m_normals;
        var tVec;
        var tMat;
        tMat = xf2.R;
        tVec = poly2.m_centroid;
        var dX = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var dY = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tMat = xf1.R;
        tVec = poly1.m_centroid;
        dX -= xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        dY -= xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        var dLocal1X = (dX * xf1.R.col1.x + dY * xf1.R.col1.y);
        var dLocal1Y = (dX * xf1.R.col2.x + dY * xf1.R.col2.y);
        var edge = 0;
        var maxDot = (-Number.MAX_VALUE);
        for (var i = 0; i < count1; ++i) {
            tVec = normals1[i];
            var dot = (tVec.x * dLocal1X + tVec.y * dLocal1Y);
            if (dot > maxDot) {
                maxDot = dot;
                edge = i;
            }
        }
        var s = b2Collision.EdgeSeparation(poly1, xf1, edge, poly2, xf2);
        var prevEdge = parseInt(edge - 1 >= 0 ? edge - 1 : count1 - 1);
        var sPrev = b2Collision.EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
        var nextEdge = parseInt(edge + 1 < count1 ? edge + 1 : 0);
        var sNext = b2Collision.EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
        var bestEdge = 0;
        var bestSeparation = 0;
        var increment = 0;
        if (sPrev > s && sPrev > sNext) {
            increment = (-1);
            bestEdge = prevEdge;
            bestSeparation = sPrev;
        }
        else if (sNext > s) {
            increment = 1;
            bestEdge = nextEdge;
            bestSeparation = sNext;
        }
        else {
            edgeIndex[0] = edge;
            return s;
        }
        while (true) {
            if (increment == (-1)) edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
            else edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;s = b2Collision.EdgeSeparation(poly1, xf1, edge, poly2, xf2);
            if (s > bestSeparation) {
                bestEdge = edge;
                bestSeparation = s;
            }
            else {
                break;
            }
        }
        edgeIndex[0] = bestEdge;
        return bestSeparation;
    }
    b2Collision.FindIncidentEdge = function (c, poly1, xf1, edge1, poly2, xf2) {
        if (edge1 === undefined) edge1 = 0;
        var count1 = parseInt(poly1.m_vertexCount);
        var normals1 = poly1.m_normals;
        var count2 = parseInt(poly2.m_vertexCount);
        var vertices2 = poly2.m_vertices;
        var normals2 = poly2.m_normals;
        var tMat;
        var tVec;
        tMat = xf1.R;
        tVec = normals1[edge1];
        var normal1X = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var normal1Y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tMat = xf2.R;
        var tX = (tMat.col1.x * normal1X + tMat.col1.y * normal1Y);
        normal1Y = (tMat.col2.x * normal1X + tMat.col2.y * normal1Y);
        normal1X = tX;
        var index = 0;
        var minDot = Number.MAX_VALUE;
        for (var i = 0; i < count2; ++i) {
            tVec = normals2[i];
            var dot = (normal1X * tVec.x + normal1Y * tVec.y);
            if (dot < minDot) {
                minDot = dot;
                index = i;
            }
        }
        var tClip;
        var i1 = parseInt(index);
        var i2 = parseInt(i1 + 1 < count2 ? i1 + 1 : 0);
        tClip = c[0];
        tVec = vertices2[i1];
        tMat = xf2.R;
        tClip.v.x = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        tClip.v.y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tClip.id.features.referenceEdge = edge1;
        tClip.id.features.incidentEdge = i1;
        tClip.id.features.incidentVertex = 0;
        tClip = c[1];
        tVec = vertices2[i2];
        tMat = xf2.R;
        tClip.v.x = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        tClip.v.y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tClip.id.features.referenceEdge = edge1;
        tClip.id.features.incidentEdge = i2;
        tClip.id.features.incidentVertex = 1;
    }
    b2Collision.MakeClipPointVector = function () {
        var r = new Vector(2);
        r[0] = new ClipVertex();
        r[1] = new ClipVertex();
        return r;
    }
    b2Collision.CollidePolygons = function (manifold, polyA, xfA, polyB, xfB) {
        var cv;
        manifold.m_pointCount = 0;
        var totalRadius = polyA.m_radius + polyB.m_radius;
        var edgeA = 0;
        b2Collision.s_edgeAO[0] = edgeA;
        var separationA = b2Collision.FindMaxSeparation(b2Collision.s_edgeAO, polyA, xfA, polyB, xfB);
        edgeA = b2Collision.s_edgeAO[0];
        if (separationA > totalRadius) return;
        var edgeB = 0;
        b2Collision.s_edgeBO[0] = edgeB;
        var separationB = b2Collision.FindMaxSeparation(b2Collision.s_edgeBO, polyB, xfB, polyA, xfA);
        edgeB = b2Collision.s_edgeBO[0];
        if (separationB > totalRadius) return;
        var poly1;
        var poly2;
        var xf1;
        var xf2;
        var edge1 = 0;
        var flip = 0;
        var k_relativeTol = 0.98;
        var k_absoluteTol = 0.001;
        var tMat;
        if (separationB > k_relativeTol * separationA + k_absoluteTol) {
            poly1 = polyB;
            poly2 = polyA;
            xf1 = xfB;
            xf2 = xfA;
            edge1 = edgeB;
            manifold.m_type = b2Manifold.e_faceB;
            flip = 1;
        }
        else {
            poly1 = polyA;
            poly2 = polyB;
            xf1 = xfA;
            xf2 = xfB;
            edge1 = edgeA;
            manifold.m_type = b2Manifold.e_faceA;
            flip = 0;
        }
        var incidentEdge = b2Collision.s_incidentEdge;
        b2Collision.FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
        var count1 = parseInt(poly1.m_vertexCount);
        var vertices1 = poly1.m_vertices;
        var local_v11 = vertices1[edge1];
        var local_v12;
        if (edge1 + 1 < count1) {
            local_v12 = vertices1[parseInt(edge1 + 1)];
        }
        else {
            local_v12 = vertices1[0];
        }
        var localTangent = b2Collision.s_localTangent;
        localTangent.Set(local_v12.x - local_v11.x, local_v12.y - local_v11.y);
        localTangent.Normalize();
        var localNormal = b2Collision.s_localNormal;
        localNormal.x = localTangent.y;
        localNormal.y = (-localTangent.x);
        var planePoint = b2Collision.s_planePoint;
        planePoint.Set(0.5 * (local_v11.x + local_v12.x), 0.5 * (local_v11.y + local_v12.y));
        var tangent = b2Collision.s_tangent;
        tMat = xf1.R;
        tangent.x = (tMat.col1.x * localTangent.x + tMat.col2.x * localTangent.y);
        tangent.y = (tMat.col1.y * localTangent.x + tMat.col2.y * localTangent.y);
        var tangent2 = b2Collision.s_tangent2;
        tangent2.x = (-tangent.x);
        tangent2.y = (-tangent.y);
        var normal = b2Collision.s_normal;
        normal.x = tangent.y;
        normal.y = (-tangent.x);
        var v11 = b2Collision.s_v11;
        var v12 = b2Collision.s_v12;
        v11.x = xf1.position.x + (tMat.col1.x * local_v11.x + tMat.col2.x * local_v11.y);
        v11.y = xf1.position.y + (tMat.col1.y * local_v11.x + tMat.col2.y * local_v11.y);
        v12.x = xf1.position.x + (tMat.col1.x * local_v12.x + tMat.col2.x * local_v12.y);
        v12.y = xf1.position.y + (tMat.col1.y * local_v12.x + tMat.col2.y * local_v12.y);
        var frontOffset = normal.x * v11.x + normal.y * v11.y;
        var sideOffset1 = (-tangent.x * v11.x) - tangent.y * v11.y + totalRadius;
        var sideOffset2 = tangent.x * v12.x + tangent.y * v12.y + totalRadius;
        var clipPoints1 = b2Collision.s_clipPoints1;
        var clipPoints2 = b2Collision.s_clipPoints2;
        var np = 0;
        np = b2Collision.ClipSegmentToLine(clipPoints1, incidentEdge, tangent2, sideOffset1);
        if (np < 2) return;
        np = b2Collision.ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2);
        if (np < 2) return;
        manifold.m_localPlaneNormal.SetV(localNormal);
        manifold.m_localPoint.SetV(planePoint);
        var pointCount = 0;
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; ++i) {
            cv = clipPoints2[i];
            var separation = normal.x * cv.v.x + normal.y * cv.v.y - frontOffset;
            if (separation <= totalRadius) {
                var cp = manifold.m_points[pointCount];
                tMat = xf2.R;
                var tX = cv.v.x - xf2.position.x;
                var tY = cv.v.y - xf2.position.y;
                cp.m_localPoint.x = (tX * tMat.col1.x + tY * tMat.col1.y);
                cp.m_localPoint.y = (tX * tMat.col2.x + tY * tMat.col2.y);
                cp.m_id.Set(cv.id);
                cp.m_id.features.flip = flip;
                ++pointCount;
            }
        }
        manifold.m_pointCount = pointCount;
    }
    b2Collision.CollideCircles = function (manifold, circle1, xf1, circle2, xf2) {
        manifold.m_pointCount = 0;
        var tMat;
        var tVec;
        tMat = xf1.R;
        tVec = circle1.m_p;
        var p1X = xf1.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var p1Y = xf1.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        tMat = xf2.R;
        tVec = circle2.m_p;
        var p2X = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var p2Y = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        var dX = p2X - p1X;
        var dY = p2Y - p1Y;
        var distSqr = dX * dX + dY * dY;
        var radius = circle1.m_radius + circle2.m_radius;
        if (distSqr > radius * radius) {
            return;
        }
        manifold.m_type = b2Manifold.e_circles;
        manifold.m_localPoint.SetV(circle1.m_p);
        manifold.m_localPlaneNormal.SetZero();
        manifold.m_pointCount = 1;
        manifold.m_points[0].m_localPoint.SetV(circle2.m_p);
        manifold.m_points[0].m_id.key = 0;
    }
    b2Collision.CollidePolygonAndCircle = function (manifold, polygon, xf1, circle, xf2) {
        manifold.m_pointCount = 0;
        var tPoint;
        var dX = 0;
        var dY = 0;
        var positionX = 0;
        var positionY = 0;
        var tVec;
        var tMat;
        tMat = xf2.R;
        tVec = circle.m_p;
        var cX = xf2.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var cY = xf2.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        dX = cX - xf1.position.x;
        dY = cY - xf1.position.y;
        tMat = xf1.R;
        var cLocalX = (dX * tMat.col1.x + dY * tMat.col1.y);
        var cLocalY = (dX * tMat.col2.x + dY * tMat.col2.y);
        var dist = 0;
        var normalIndex = 0;
        var separation = (-Number.MAX_VALUE);
        var radius = polygon.m_radius + circle.m_radius;
        var vertexCount = parseInt(polygon.m_vertexCount);
        var vertices = polygon.m_vertices;
        var normals = polygon.m_normals;
        for (var i = 0; i < vertexCount; ++i) {
            tVec = vertices[i];
            dX = cLocalX - tVec.x;
            dY = cLocalY - tVec.y;
            tVec = normals[i];
            var s = tVec.x * dX + tVec.y * dY;
            if (s > radius) {
                return;
            }
            if (s > separation) {
                separation = s;
                normalIndex = i;
            }
        }
        var vertIndex1 = parseInt(normalIndex);
        var vertIndex2 = parseInt(vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0);
        var v1 = vertices[vertIndex1];
        var v2 = vertices[vertIndex2];
        if (separation < Number.MIN_VALUE) {
            manifold.m_pointCount = 1;
            manifold.m_type = b2Manifold.e_faceA;
            manifold.m_localPlaneNormal.SetV(normals[normalIndex]);
            manifold.m_localPoint.x = 0.5 * (v1.x + v2.x);
            manifold.m_localPoint.y = 0.5 * (v1.y + v2.y);
            manifold.m_points[0].m_localPoint.SetV(circle.m_p);
            manifold.m_points[0].m_id.key = 0;
            return;
        }
        var u1 = (cLocalX - v1.x) * (v2.x - v1.x) + (cLocalY - v1.y) * (v2.y - v1.y);
        var u2 = (cLocalX - v2.x) * (v1.x - v2.x) + (cLocalY - v2.y) * (v1.y - v2.y);
        if (u1 <= 0.0) {
            if ((cLocalX - v1.x) * (cLocalX - v1.x) + (cLocalY - v1.y) * (cLocalY - v1.y) > radius * radius) return;
            manifold.m_pointCount = 1;
            manifold.m_type = b2Manifold.e_faceA;
            manifold.m_localPlaneNormal.x = cLocalX - v1.x;
            manifold.m_localPlaneNormal.y = cLocalY - v1.y;
            manifold.m_localPlaneNormal.Normalize();
            manifold.m_localPoint.SetV(v1);
            manifold.m_points[0].m_localPoint.SetV(circle.m_p);
            manifold.m_points[0].m_id.key = 0;
        }
        else if (u2 <= 0) {
            if ((cLocalX - v2.x) * (cLocalX - v2.x) + (cLocalY - v2.y) * (cLocalY - v2.y) > radius * radius) return;
            manifold.m_pointCount = 1;
            manifold.m_type = b2Manifold.e_faceA;
            manifold.m_localPlaneNormal.x = cLocalX - v2.x;
            manifold.m_localPlaneNormal.y = cLocalY - v2.y;
            manifold.m_localPlaneNormal.Normalize();
            manifold.m_localPoint.SetV(v2);
            manifold.m_points[0].m_localPoint.SetV(circle.m_p);
            manifold.m_points[0].m_id.key = 0;
        }
        else {
            var faceCenterX = 0.5 * (v1.x + v2.x);
            var faceCenterY = 0.5 * (v1.y + v2.y);
            separation = (cLocalX - faceCenterX) * normals[vertIndex1].x + (cLocalY - faceCenterY) * normals[vertIndex1].y;
            if (separation > radius) return;
            manifold.m_pointCount = 1;
            manifold.m_type = b2Manifold.e_faceA;
            manifold.m_localPlaneNormal.x = normals[vertIndex1].x;
            manifold.m_localPlaneNormal.y = normals[vertIndex1].y;
            manifold.m_localPlaneNormal.Normalize();
            manifold.m_localPoint.Set(faceCenterX, faceCenterY);
            manifold.m_points[0].m_localPoint.SetV(circle.m_p);
            manifold.m_points[0].m_id.key = 0;
        }
    }
    b2Collision.TestOverlap = function (a, b) {
        var t1 = b.lowerBound;
        var t2 = a.upperBound;
        var d1X = t1.x - t2.x;
        var d1Y = t1.y - t2.y;
        t1 = a.lowerBound;
        t2 = b.upperBound;
        var d2X = t1.x - t2.x;
        var d2Y = t1.y - t2.y;
        if (d1X > 0.0 || d1Y > 0.0) return false;
        if (d2X > 0.0 || d2Y > 0.0) return false;
        return true;
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.b2Collision.s_incidentEdge = b2Collision.MakeClipPointVector();
        Box2D.Collision.b2Collision.s_clipPoints1 = b2Collision.MakeClipPointVector();
        Box2D.Collision.b2Collision.s_clipPoints2 = b2Collision.MakeClipPointVector();
        Box2D.Collision.b2Collision.s_edgeAO = new Vector_a2j_Number(1);
        Box2D.Collision.b2Collision.s_edgeBO = new Vector_a2j_Number(1);
        Box2D.Collision.b2Collision.s_localTangent = new b2Vec2();
        Box2D.Collision.b2Collision.s_localNormal = new b2Vec2();
        Box2D.Collision.b2Collision.s_planePoint = new b2Vec2();
        Box2D.Collision.b2Collision.s_normal = new b2Vec2();
        Box2D.Collision.b2Collision.s_tangent = new b2Vec2();
        Box2D.Collision.b2Collision.s_tangent2 = new b2Vec2();
        Box2D.Collision.b2Collision.s_v11 = new b2Vec2();
        Box2D.Collision.b2Collision.s_v12 = new b2Vec2();
        Box2D.Collision.b2Collision.b2CollidePolyTempVec = new b2Vec2();
        Box2D.Collision.b2Collision.b2_nullFeature = 0x000000ff;
    });
    b2ContactID.b2ContactID = function () {
        this.features = new Features();
    };
    b2ContactID.prototype.b2ContactID = function () {
        this.features._m_id = this;
    }
    b2ContactID.prototype.Set = function (id) {
        this.key = id._key;
    }
    b2ContactID.prototype.Copy = function () {
        var id = new b2ContactID();
        id.key = this.key;
        return id;
    }
    Object.defineProperty(b2ContactID.prototype, 'key', {
        enumerable: false,
        configurable: true,
        get: function () {
            return this._key;
        }
    });
    Object.defineProperty(b2ContactID.prototype, 'key', {
        enumerable: false,
        configurable: true,
        set: function (value) {
            if (value === undefined) value = 0;
            this._key = value;
            this.features._referenceEdge = this._key & 0x000000ff;
            this.features._incidentEdge = ((this._key & 0x0000ff00) >> 8) & 0x000000ff;
            this.features._incidentVertex = ((this._key & 0x00ff0000) >> 16) & 0x000000ff;
            this.features._flip = ((this._key & 0xff000000) >> 24) & 0x000000ff;
        }
    });
    b2ContactPoint.b2ContactPoint = function () {
        this.position = new b2Vec2();
        this.velocity = new b2Vec2();
        this.normal = new b2Vec2();
        this.id = new b2ContactID();
    };
    b2Distance.b2Distance = function () {};
    b2Distance.Distance = function (output, cache, input) {
        ++b2Distance.b2_gjkCalls;
        var proxyA = input.proxyA;
        var proxyB = input.proxyB;
        var transformA = input.transformA;
        var transformB = input.transformB;
        var simplex = b2Distance.s_simplex;
        simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB);
        var vertices = simplex.m_vertices;
        var k_maxIters = 20;
        var saveA = b2Distance.s_saveA;
        var saveB = b2Distance.s_saveB;
        var saveCount = 0;
        var closestPoint = simplex.GetClosestPoint();
        var distanceSqr1 = closestPoint.LengthSquared();
        var distanceSqr2 = distanceSqr1;
        var i = 0;
        var p;
        var iter = 0;
        while (iter < k_maxIters) {
            saveCount = simplex.m_count;
            for (i = 0;
                 i < saveCount; i++) {
                saveA[i] = vertices[i].indexA;
                saveB[i] = vertices[i].indexB;
            }
            switch (simplex.m_count) {
                case 1:
                    break;
                case 2:
                    simplex.Solve2();
                    break;
                case 3:
                    simplex.Solve3();
                    break;
                default:
                    b2Settings.b2Assert(false);
            }
            if (simplex.m_count == 3) {
                break;
            }
            p = simplex.GetClosestPoint();
            distanceSqr2 = p.LengthSquared();
            if (distanceSqr2 > distanceSqr1) {}
            distanceSqr1 = distanceSqr2;
            var d = simplex.GetSearchDirection();
            if (d.LengthSquared() < Number.MIN_VALUE * Number.MIN_VALUE) {
                break;
            }
            var vertex = vertices[simplex.m_count];
            vertex.indexA = proxyA.GetSupport(b2Math.MulTMV(transformA.R, d.GetNegative()));
            vertex.wA = b2Math.MulX(transformA, proxyA.GetVertex(vertex.indexA));
            vertex.indexB = proxyB.GetSupport(b2Math.MulTMV(transformB.R, d));
            vertex.wB = b2Math.MulX(transformB, proxyB.GetVertex(vertex.indexB));
            vertex.w = b2Math.SubtractVV(vertex.wB, vertex.wA);
            ++iter;
            ++b2Distance.b2_gjkIters;
            var duplicate = false;
            for (i = 0;
                 i < saveCount; i++) {
                if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) {
                    duplicate = true;
                    break;
                }
            }
            if (duplicate) {
                break;
            }++simplex.m_count;
        }
        b2Distance.b2_gjkMaxIters = b2Math.Max(b2Distance.b2_gjkMaxIters, iter);
        simplex.GetWitnessPoints(output.pointA, output.pointB);
        output.distance = b2Math.SubtractVV(output.pointA, output.pointB).Length();
        output.iterations = iter;
        simplex.WriteCache(cache);
        if (input.useRadii) {
            var rA = proxyA.m_radius;
            var rB = proxyB.m_radius;
            if (output.distance > rA + rB && output.distance > Number.MIN_VALUE) {
                output.distance -= rA + rB;
                var normal = b2Math.SubtractVV(output.pointB, output.pointA);
                normal.Normalize();
                output.pointA.x += rA * normal.x;
                output.pointA.y += rA * normal.y;
                output.pointB.x -= rB * normal.x;
                output.pointB.y -= rB * normal.y;
            }
            else {
                p = new b2Vec2();
                p.x = .5 * (output.pointA.x + output.pointB.x);
                p.y = .5 * (output.pointA.y + output.pointB.y);
                output.pointA.x = output.pointB.x = p.x;
                output.pointA.y = output.pointB.y = p.y;
                output.distance = 0.0;
            }
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.b2Distance.s_simplex = new b2Simplex();
        Box2D.Collision.b2Distance.s_saveA = new Vector_a2j_Number(3);
        Box2D.Collision.b2Distance.s_saveB = new Vector_a2j_Number(3);
    });
    b2DistanceInput.b2DistanceInput = function () {};
    b2DistanceOutput.b2DistanceOutput = function () {
        this.pointA = new b2Vec2();
        this.pointB = new b2Vec2();
    };
    b2DistanceProxy.b2DistanceProxy = function () {};
    b2DistanceProxy.prototype.Set = function (shape) {
        switch (shape.GetType()) {
            case b2Shape.e_circleShape:
            {
                var circle = (shape instanceof b2CircleShape ? shape : null);
                this.m_vertices = new Vector(1, true);
                this.m_vertices[0] = circle.m_p;
                this.m_count = 1;
                this.m_radius = circle.m_radius;
            }
                break;
            case b2Shape.e_polygonShape:
            {
                var polygon = (shape instanceof b2PolygonShape ? shape : null);
                this.m_vertices = polygon.m_vertices;
                this.m_count = polygon.m_vertexCount;
                this.m_radius = polygon.m_radius;
            }
                break;
            default:
                b2Settings.b2Assert(false);
        }
    }
    b2DistanceProxy.prototype.GetSupport = function (d) {
        var bestIndex = 0;
        var bestValue = this.m_vertices[0].x * d.x + this.m_vertices[0].y * d.y;
        for (var i = 1; i < this.m_count; ++i) {
            var value = this.m_vertices[i].x * d.x + this.m_vertices[i].y * d.y;
            if (value > bestValue) {
                bestIndex = i;
                bestValue = value;
            }
        }
        return bestIndex;
    }
    b2DistanceProxy.prototype.GetSupportVertex = function (d) {
        var bestIndex = 0;
        var bestValue = this.m_vertices[0].x * d.x + this.m_vertices[0].y * d.y;
        for (var i = 1; i < this.m_count; ++i) {
            var value = this.m_vertices[i].x * d.x + this.m_vertices[i].y * d.y;
            if (value > bestValue) {
                bestIndex = i;
                bestValue = value;
            }
        }
        return this.m_vertices[bestIndex];
    }
    b2DistanceProxy.prototype.GetVertexCount = function () {
        return this.m_count;
    }
    b2DistanceProxy.prototype.GetVertex = function (index) {
        if (index === undefined) index = 0;
        b2Settings.b2Assert(0 <= index && index < this.m_count);
        return this.m_vertices[index];
    }
    b2DynamicTree.b2DynamicTree = function () {};
    b2DynamicTree.prototype.b2DynamicTree = function () {
        this.m_root = null;
        this.m_freeList = null;
        this.m_path = 0;
        this.m_insertionCount = 0;
    }
    b2DynamicTree.prototype.CreateProxy = function (aabb, userData) {
        var node = this.AllocateNode();
        var extendX = b2Settings.b2_aabbExtension;
        var extendY = b2Settings.b2_aabbExtension;
        node.aabb.lowerBound.x = aabb.lowerBound.x - extendX;
        node.aabb.lowerBound.y = aabb.lowerBound.y - extendY;
        node.aabb.upperBound.x = aabb.upperBound.x + extendX;
        node.aabb.upperBound.y = aabb.upperBound.y + extendY;
        node.userData = userData;
        this.InsertLeaf(node);
        return node;
    }
    b2DynamicTree.prototype.DestroyProxy = function (proxy) {
        this.RemoveLeaf(proxy);
        this.FreeNode(proxy);
    }
    b2DynamicTree.prototype.MoveProxy = function (proxy, aabb, displacement) {
        b2Settings.b2Assert(proxy.IsLeaf());
        if (proxy.aabb.Contains(aabb)) {
            return false;
        }
        this.RemoveLeaf(proxy);
        var extendX = b2Settings.b2_aabbExtension + b2Settings.b2_aabbMultiplier * (displacement.x > 0 ? displacement.x : (-displacement.x));
        var extendY = b2Settings.b2_aabbExtension + b2Settings.b2_aabbMultiplier * (displacement.y > 0 ? displacement.y : (-displacement.y));
        proxy.aabb.lowerBound.x = aabb.lowerBound.x - extendX;
        proxy.aabb.lowerBound.y = aabb.lowerBound.y - extendY;
        proxy.aabb.upperBound.x = aabb.upperBound.x + extendX;
        proxy.aabb.upperBound.y = aabb.upperBound.y + extendY;
        this.InsertLeaf(proxy);
        return true;
    }
    b2DynamicTree.prototype.Rebalance = function (iterations) {
        if (iterations === undefined) iterations = 0;
        if (this.m_root == null) return;
        for (var i = 0; i < iterations; i++) {
            var node = this.m_root;
            var bit = 0;
            while (node.IsLeaf() == false) {
                node = (this.m_path >> bit) & 1 ? node.child2 : node.child1;
                bit = (bit + 1) & 31;
            }++this.m_path;
            this.RemoveLeaf(node);
            this.InsertLeaf(node);
        }
    }
    b2DynamicTree.prototype.GetFatAABB = function (proxy) {
        return proxy.aabb;
    }
    b2DynamicTree.prototype.GetUserData = function (proxy) {
        return proxy.userData;
    }
    b2DynamicTree.prototype.Query = function (callback, aabb) {
        if (this.m_root == null) return;
        var stack = new Vector();
        var count = 0;
        stack[count++] = this.m_root;
        while (count > 0) {
            var node = stack[--count];
            if (node.aabb.TestOverlap(aabb)) {
                if (node.IsLeaf()) {
                    var proceed = callback(node);
                    if (!proceed) return;
                }
                else {
                    stack[count++] = node.child1;
                    stack[count++] = node.child2;
                }
            }
        }
    }
    b2DynamicTree.prototype.RayCast = function (callback, input) {
        if (this.m_root == null) return;
        var p1 = input.p1;
        var p2 = input.p2;
        var r = b2Math.SubtractVV(p1, p2);
        r.Normalize();
        var v = b2Math.CrossFV(1.0, r);
        var abs_v = b2Math.AbsV(v);
        var maxFraction = input.maxFraction;
        var segmentAABB = new b2AABB();
        var tX = 0;
        var tY = 0; {
            tX = p1.x + maxFraction * (p2.x - p1.x);
            tY = p1.y + maxFraction * (p2.y - p1.y);
            segmentAABB.lowerBound.x = Math.min(p1.x, tX);
            segmentAABB.lowerBound.y = Math.min(p1.y, tY);
            segmentAABB.upperBound.x = Math.max(p1.x, tX);
            segmentAABB.upperBound.y = Math.max(p1.y, tY);
        }
        var stack = new Vector();
        var count = 0;
        stack[count++] = this.m_root;
        while (count > 0) {
            var node = stack[--count];
            if (node.aabb.TestOverlap(segmentAABB) == false) {
                continue;
            }
            var c = node.aabb.GetCenter();
            var h = node.aabb.GetExtents();
            var separation = Math.abs(v.x * (p1.x - c.x) + v.y * (p1.y - c.y)) - abs_v.x * h.x - abs_v.y * h.y;
            if (separation > 0.0) continue;
            if (node.IsLeaf()) {
                var subInput = new b2RayCastInput();
                subInput.p1 = input.p1;
                subInput.p2 = input.p2;
                subInput.maxFraction = input.maxFraction;
                maxFraction = callback(subInput, node);
                if (maxFraction == 0.0) return;
                if (maxFraction > 0.0) {
                    tX = p1.x + maxFraction * (p2.x - p1.x);
                    tY = p1.y + maxFraction * (p2.y - p1.y);
                    segmentAABB.lowerBound.x = Math.min(p1.x, tX);
                    segmentAABB.lowerBound.y = Math.min(p1.y, tY);
                    segmentAABB.upperBound.x = Math.max(p1.x, tX);
                    segmentAABB.upperBound.y = Math.max(p1.y, tY);
                }
            }
            else {
                stack[count++] = node.child1;
                stack[count++] = node.child2;
            }
        }
    }
    b2DynamicTree.prototype.AllocateNode = function () {
        if (this.m_freeList) {
            var node = this.m_freeList;
            this.m_freeList = node.parent;
            node.parent = null;
            node.child1 = null;
            node.child2 = null;
            return node;
        }
        return new b2DynamicTreeNode();
    }
    b2DynamicTree.prototype.FreeNode = function (node) {
        node.parent = this.m_freeList;
        this.m_freeList = node;
    }
    b2DynamicTree.prototype.InsertLeaf = function (leaf) {
        ++this.m_insertionCount;
        if (this.m_root == null) {
            this.m_root = leaf;
            this.m_root.parent = null;
            return;
        }
        var center = leaf.aabb.GetCenter();
        var sibling = this.m_root;
        if (sibling.IsLeaf() == false) {
            do {
                var child1 = sibling.child1;
                var child2 = sibling.child2;
                var norm1 = Math.abs((child1.aabb.lowerBound.x + child1.aabb.upperBound.x) / 2 - center.x) + Math.abs((child1.aabb.lowerBound.y + child1.aabb.upperBound.y) / 2 - center.y);
                var norm2 = Math.abs((child2.aabb.lowerBound.x + child2.aabb.upperBound.x) / 2 - center.x) + Math.abs((child2.aabb.lowerBound.y + child2.aabb.upperBound.y) / 2 - center.y);
                if (norm1 < norm2) {
                    sibling = child1;
                }
                else {
                    sibling = child2;
                }
            }
            while (sibling.IsLeaf() == false)
        }
        var node1 = sibling.parent;
        var node2 = this.AllocateNode();
        node2.parent = node1;
        node2.userData = null;
        node2.aabb.Combine(leaf.aabb, sibling.aabb);
        if (node1) {
            if (sibling.parent.child1 == sibling) {
                node1.child1 = node2;
            }
            else {
                node1.child2 = node2;
            }
            node2.child1 = sibling;
            node2.child2 = leaf;
            sibling.parent = node2;
            leaf.parent = node2;
            do {
                if (node1.aabb.Contains(node2.aabb)) break;
                node1.aabb.Combine(node1.child1.aabb, node1.child2.aabb);
                node2 = node1;
                node1 = node1.parent;
            }
            while (node1)
        }
        else {
            node2.child1 = sibling;
            node2.child2 = leaf;
            sibling.parent = node2;
            leaf.parent = node2;
            this.m_root = node2;
        }
    }
    b2DynamicTree.prototype.RemoveLeaf = function (leaf) {
        if (leaf == this.m_root) {
            this.m_root = null;
            return;
        }
        var node2 = leaf.parent;
        var node1 = node2.parent;
        var sibling;
        if (node2.child1 == leaf) {
            sibling = node2.child2;
        }
        else {
            sibling = node2.child1;
        }
        if (node1) {
            if (node1.child1 == node2) {
                node1.child1 = sibling;
            }
            else {
                node1.child2 = sibling;
            }
            sibling.parent = node1;
            this.FreeNode(node2);
            while (node1) {
                var oldAABB = node1.aabb;
                node1.aabb = b2AABB.Combine(node1.child1.aabb, node1.child2.aabb);
                if (oldAABB.Contains(node1.aabb)) break;
                node1 = node1.parent;
            }
        }
        else {
            this.m_root = sibling;
            sibling.parent = null;
            this.FreeNode(node2);
        }
    }
    b2DynamicTreeBroadPhase.b2DynamicTreeBroadPhase = function () {
        this.m_tree = new b2DynamicTree();
        this.m_moveBuffer = new Vector();
        this.m_pairBuffer = new Vector();
        this.m_pairCount = 0;
    };
    b2DynamicTreeBroadPhase.prototype.CreateProxy = function (aabb, userData) {
        var proxy = this.m_tree.CreateProxy(aabb, userData);
        ++this.m_proxyCount;
        this.BufferMove(proxy);
        return proxy;
    }
    b2DynamicTreeBroadPhase.prototype.DestroyProxy = function (proxy) {
        this.UnBufferMove(proxy);
        --this.m_proxyCount;
        this.m_tree.DestroyProxy(proxy);
    }
    b2DynamicTreeBroadPhase.prototype.MoveProxy = function (proxy, aabb, displacement) {
        var buffer = this.m_tree.MoveProxy(proxy, aabb, displacement);
        if (buffer) {
            this.BufferMove(proxy);
        }
    }
    b2DynamicTreeBroadPhase.prototype.TestOverlap = function (proxyA, proxyB) {
        var aabbA = this.m_tree.GetFatAABB(proxyA);
        var aabbB = this.m_tree.GetFatAABB(proxyB);
        return aabbA.TestOverlap(aabbB);
    }
    b2DynamicTreeBroadPhase.prototype.GetUserData = function (proxy) {
        return this.m_tree.GetUserData(proxy);
    }
    b2DynamicTreeBroadPhase.prototype.GetFatAABB = function (proxy) {
        return this.m_tree.GetFatAABB(proxy);
    }
    b2DynamicTreeBroadPhase.prototype.GetProxyCount = function () {
        return this.m_proxyCount;
    }
    b2DynamicTreeBroadPhase.prototype.UpdatePairs = function (callback) {
        var __this = this;
        __this.m_pairCount = 0;
        var i = 0,
            queryProxy;
        for (i = 0;
             i < __this.m_moveBuffer.length; ++i) {
            queryProxy = __this.m_moveBuffer[i];
            function QueryCallback(proxy) {
                if (proxy == queryProxy) return true;
                if (__this.m_pairCount == __this.m_pairBuffer.length) {
                    __this.m_pairBuffer[__this.m_pairCount] = new b2DynamicTreePair();
                }
                var pair = __this.m_pairBuffer[__this.m_pairCount];
                pair.proxyA = proxy < queryProxy ? proxy : queryProxy;
                pair.proxyB = proxy >= queryProxy ? proxy : queryProxy;++__this.m_pairCount;
                return true;
            };
            var fatAABB = __this.m_tree.GetFatAABB(queryProxy);
            __this.m_tree.Query(QueryCallback, fatAABB);
        }
        __this.m_moveBuffer.length = 0;
        for (var i = 0; i < __this.m_pairCount;) {
            var primaryPair = __this.m_pairBuffer[i];
            var userDataA = __this.m_tree.GetUserData(primaryPair.proxyA);
            var userDataB = __this.m_tree.GetUserData(primaryPair.proxyB);
            callback(userDataA, userDataB);
            ++i;
            while (i < __this.m_pairCount) {
                var pair = __this.m_pairBuffer[i];
                if (pair.proxyA != primaryPair.proxyA || pair.proxyB != primaryPair.proxyB) {
                    break;
                }++i;
            }
        }
    }
    b2DynamicTreeBroadPhase.prototype.Query = function (callback, aabb) {
        this.m_tree.Query(callback, aabb);
    }
    b2DynamicTreeBroadPhase.prototype.RayCast = function (callback, input) {
        this.m_tree.RayCast(callback, input);
    }
    b2DynamicTreeBroadPhase.prototype.Validate = function () {}
    b2DynamicTreeBroadPhase.prototype.Rebalance = function (iterations) {
        if (iterations === undefined) iterations = 0;
        this.m_tree.Rebalance(iterations);
    }
    b2DynamicTreeBroadPhase.prototype.BufferMove = function (proxy) {
        this.m_moveBuffer[this.m_moveBuffer.length] = proxy;
    }
    b2DynamicTreeBroadPhase.prototype.UnBufferMove = function (proxy) {
        var i = parseInt(this.m_moveBuffer.indexOf(proxy));
        this.m_moveBuffer.splice(i, 1);
    }
    b2DynamicTreeBroadPhase.prototype.ComparePairs = function (pair1, pair2) {
        return 0;
    }
    b2DynamicTreeBroadPhase.__implements = {};
    b2DynamicTreeBroadPhase.__implements[IBroadPhase] = true;
    b2DynamicTreeNode.b2DynamicTreeNode = function () {
        this.aabb = new b2AABB();
    };
    b2DynamicTreeNode.prototype.IsLeaf = function () {
        return this.child1 == null;
    }
    b2DynamicTreePair.b2DynamicTreePair = function () {};
    b2Manifold.b2Manifold = function () {
        this.m_pointCount = 0;
    };
    b2Manifold.prototype.b2Manifold = function () {
        this.m_points = new Vector(b2Settings.b2_maxManifoldPoints);
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++) {
            this.m_points[i] = new b2ManifoldPoint();
        }
        this.m_localPlaneNormal = new b2Vec2();
        this.m_localPoint = new b2Vec2();
    }
    b2Manifold.prototype.Reset = function () {
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++) {
            ((this.m_points[i] instanceof b2ManifoldPoint ? this.m_points[i] : null)).Reset();
        }
        this.m_localPlaneNormal.SetZero();
        this.m_localPoint.SetZero();
        this.m_type = 0;
        this.m_pointCount = 0;
    }
    b2Manifold.prototype.Set = function (m) {
        this.m_pointCount = m.m_pointCount;
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++) {
            ((this.m_points[i] instanceof b2ManifoldPoint ? this.m_points[i] : null)).Set(m.m_points[i]);
        }
        this.m_localPlaneNormal.SetV(m.m_localPlaneNormal);
        this.m_localPoint.SetV(m.m_localPoint);
        this.m_type = m.m_type;
    }
    b2Manifold.prototype.Copy = function () {
        var copy = new b2Manifold();
        copy.Set(this);
        return copy;
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.b2Manifold.e_circles = 0x0001;
        Box2D.Collision.b2Manifold.e_faceA = 0x0002;
        Box2D.Collision.b2Manifold.e_faceB = 0x0004;
    });
    b2ManifoldPoint.b2ManifoldPoint = function () {
        this.m_localPoint = new b2Vec2();
        this.m_id = new b2ContactID();
    };
    b2ManifoldPoint.prototype.b2ManifoldPoint = function () {
        this.Reset();
    }
    b2ManifoldPoint.prototype.Reset = function () {
        this.m_localPoint.SetZero();
        this.m_normalImpulse = 0.0;
        this.m_tangentImpulse = 0.0;
        this.m_id.key = 0;
    }
    b2ManifoldPoint.prototype.Set = function (m) {
        this.m_localPoint.SetV(m.m_localPoint);
        this.m_normalImpulse = m.m_normalImpulse;
        this.m_tangentImpulse = m.m_tangentImpulse;
        this.m_id.Set(m.m_id);
    }
    b2Point.b2Point = function () {
        this.p = new b2Vec2();
    };
    b2Point.prototype.Support = function (xf, vX, vY) {
        if (vX === undefined) vX = 0;
        if (vY === undefined) vY = 0;
        return this.p;
    }
    b2Point.prototype.GetFirstVertex = function (xf) {
        return this.p;
    }
    b2RayCastInput.b2RayCastInput = function () {
        this.p1 = new b2Vec2();
        this.p2 = new b2Vec2();
    };
    b2RayCastInput.prototype.b2RayCastInput = function (p1, p2, maxFraction) {
        if (p1 === undefined) p1 = null;
        if (p2 === undefined) p2 = null;
        if (maxFraction === undefined) maxFraction = 1;
        if (p1) this.p1.SetV(p1);
        if (p2) this.p2.SetV(p2);
        this.maxFraction = maxFraction;
    }
    b2RayCastOutput.b2RayCastOutput = function () {
        this.normal = new b2Vec2();
    };
    b2Segment.b2Segment = function () {
        this.p1 = new b2Vec2();
        this.p2 = new b2Vec2();
    };
    b2Segment.prototype.TestSegment = function (lambda, normal, segment, maxLambda) {
        if (maxLambda === undefined) maxLambda = 0;
        var s = segment.p1;
        var rX = segment.p2.x - s.x;
        var rY = segment.p2.y - s.y;
        var dX = this.p2.x - this.p1.x;
        var dY = this.p2.y - this.p1.y;
        var nX = dY;
        var nY = (-dX);
        var k_slop = 100.0 * Number.MIN_VALUE;
        var denom = (-(rX * nX + rY * nY));
        if (denom > k_slop) {
            var bX = s.x - this.p1.x;
            var bY = s.y - this.p1.y;
            var a = (bX * nX + bY * nY);
            if (0.0 <= a && a <= maxLambda * denom) {
                var mu2 = (-rX * bY) + rY * bX;
                if ((-k_slop * denom) <= mu2 && mu2 <= denom * (1.0 + k_slop)) {
                    a /= denom;
                    var nLen = Math.sqrt(nX * nX + nY * nY);
                    nX /= nLen;
                    nY /= nLen;
                    lambda[0] = a;
                    normal.Set(nX, nY);
                    return true;
                }
            }
        }
        return false;
    }
    b2Segment.prototype.Extend = function (aabb) {
        this.ExtendForward(aabb);
        this.ExtendBackward(aabb);
    }
    b2Segment.prototype.ExtendForward = function (aabb) {
        var dX = this.p2.x - this.p1.x;
        var dY = this.p2.y - this.p1.y;
        var lambda = Math.min(dX > 0 ? (aabb.upperBound.x - this.p1.x) / dX : dX < 0 ? (aabb.lowerBound.x - this.p1.x) / dX : Number.POSITIVE_INFINITY,
            dY > 0 ? (aabb.upperBound.y - this.p1.y) / dY : dY < 0 ? (aabb.lowerBound.y - this.p1.y) / dY : Number.POSITIVE_INFINITY);
        this.p2.x = this.p1.x + dX * lambda;
        this.p2.y = this.p1.y + dY * lambda;
    }
    b2Segment.prototype.ExtendBackward = function (aabb) {
        var dX = (-this.p2.x) + this.p1.x;
        var dY = (-this.p2.y) + this.p1.y;
        var lambda = Math.min(dX > 0 ? (aabb.upperBound.x - this.p2.x) / dX : dX < 0 ? (aabb.lowerBound.x - this.p2.x) / dX : Number.POSITIVE_INFINITY,
            dY > 0 ? (aabb.upperBound.y - this.p2.y) / dY : dY < 0 ? (aabb.lowerBound.y - this.p2.y) / dY : Number.POSITIVE_INFINITY);
        this.p1.x = this.p2.x + dX * lambda;
        this.p1.y = this.p2.y + dY * lambda;
    }
    b2SeparationFunction.b2SeparationFunction = function () {
        this.m_localPoint = new b2Vec2();
        this.m_axis = new b2Vec2();
    };
    b2SeparationFunction.prototype.Initialize = function (cache, proxyA, transformA, proxyB, transformB) {
        this.m_proxyA = proxyA;
        this.m_proxyB = proxyB;
        var count = parseInt(cache.count);
        b2Settings.b2Assert(0 < count && count < 3);
        var localPointA;
        var localPointA1;
        var localPointA2;
        var localPointB;
        var localPointB1;
        var localPointB2;
        var pointAX = 0;
        var pointAY = 0;
        var pointBX = 0;
        var pointBY = 0;
        var normalX = 0;
        var normalY = 0;
        var tMat;
        var tVec;
        var s = 0;
        var sgn = 0;
        if (count == 1) {
            this.m_type = b2SeparationFunction.e_points;
            localPointA = this.m_proxyA.GetVertex(cache.indexA[0]);
            localPointB = this.m_proxyB.GetVertex(cache.indexB[0]);
            tVec = localPointA;
            tMat = transformA.R;
            pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            tVec = localPointB;
            tMat = transformB.R;
            pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            this.m_axis.x = pointBX - pointAX;
            this.m_axis.y = pointBY - pointAY;
            this.m_axis.Normalize();
        }
        else if (cache.indexB[0] == cache.indexB[1]) {
            this.m_type = b2SeparationFunction.e_faceA;
            localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]);
            localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]);
            localPointB = this.m_proxyB.GetVertex(cache.indexB[0]);
            this.m_localPoint.x = 0.5 * (localPointA1.x + localPointA2.x);
            this.m_localPoint.y = 0.5 * (localPointA1.y + localPointA2.y);
            this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointA2, localPointA1), 1.0);
            this.m_axis.Normalize();
            tVec = this.m_axis;
            tMat = transformA.R;
            normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
            normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
            tVec = this.m_localPoint;
            tMat = transformA.R;
            pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            tVec = localPointB;
            tMat = transformB.R;
            pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            s = (pointBX - pointAX) * normalX + (pointBY - pointAY) * normalY;
            if (s < 0.0) {
                this.m_axis.NegativeSelf();
            }
        }
        else if (cache.indexA[0] == cache.indexA[0]) {
            this.m_type = b2SeparationFunction.e_faceB;
            localPointB1 = this.m_proxyB.GetVertex(cache.indexB[0]);
            localPointB2 = this.m_proxyB.GetVertex(cache.indexB[1]);
            localPointA = this.m_proxyA.GetVertex(cache.indexA[0]);
            this.m_localPoint.x = 0.5 * (localPointB1.x + localPointB2.x);
            this.m_localPoint.y = 0.5 * (localPointB1.y + localPointB2.y);
            this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointB2, localPointB1), 1.0);
            this.m_axis.Normalize();
            tVec = this.m_axis;
            tMat = transformB.R;
            normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
            normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
            tVec = this.m_localPoint;
            tMat = transformB.R;
            pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            tVec = localPointA;
            tMat = transformA.R;
            pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            s = (pointAX - pointBX) * normalX + (pointAY - pointBY) * normalY;
            if (s < 0.0) {
                this.m_axis.NegativeSelf();
            }
        }
        else {
            localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]);
            localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]);
            localPointB1 = this.m_proxyB.GetVertex(cache.indexB[0]);
            localPointB2 = this.m_proxyB.GetVertex(cache.indexB[1]);
            var pA = b2Math.MulX(transformA, localPointA);
            var dA = b2Math.MulMV(transformA.R, b2Math.SubtractVV(localPointA2, localPointA1));
            var pB = b2Math.MulX(transformB, localPointB);
            var dB = b2Math.MulMV(transformB.R, b2Math.SubtractVV(localPointB2, localPointB1));
            var a = dA.x * dA.x + dA.y * dA.y;
            var e = dB.x * dB.x + dB.y * dB.y;
            var r = b2Math.SubtractVV(dB, dA);
            var c = dA.x * r.x + dA.y * r.y;
            var f = dB.x * r.x + dB.y * r.y;
            var b = dA.x * dB.x + dA.y * dB.y;
            var denom = a * e - b * b;
            s = 0.0;
            if (denom != 0.0) {
                s = b2Math.Clamp((b * f - c * e) / denom, 0.0, 1.0);
            }
            var t = (b * s + f) / e;
            if (t < 0.0) {
                t = 0.0;
                s = b2Math.Clamp((b - c) / a, 0.0, 1.0);
            }
            localPointA = new b2Vec2();
            localPointA.x = localPointA1.x + s * (localPointA2.x - localPointA1.x);
            localPointA.y = localPointA1.y + s * (localPointA2.y - localPointA1.y);
            localPointB = new b2Vec2();
            localPointB.x = localPointB1.x + s * (localPointB2.x - localPointB1.x);
            localPointB.y = localPointB1.y + s * (localPointB2.y - localPointB1.y);
            if (s == 0.0 || s == 1.0) {
                this.m_type = b2SeparationFunction.e_faceB;
                this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointB2, localPointB1), 1.0);
                this.m_axis.Normalize();
                this.m_localPoint = localPointB;
                tVec = this.m_axis;
                tMat = transformB.R;
                normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tVec = this.m_localPoint;
                tMat = transformB.R;
                pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                tVec = localPointA;
                tMat = transformA.R;
                pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                sgn = (pointAX - pointBX) * normalX + (pointAY - pointBY) * normalY;
                if (s < 0.0) {
                    this.m_axis.NegativeSelf();
                }
            }
            else {
                this.m_type = b2SeparationFunction.e_faceA;
                this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointA2, localPointA1), 1.0);
                this.m_localPoint = localPointA;
                tVec = this.m_axis;
                tMat = transformA.R;
                normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tVec = this.m_localPoint;
                tMat = transformA.R;
                pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                tVec = localPointB;
                tMat = transformB.R;
                pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                sgn = (pointBX - pointAX) * normalX + (pointBY - pointAY) * normalY;
                if (s < 0.0) {
                    this.m_axis.NegativeSelf();
                }
            }
        }
    }
    b2SeparationFunction.prototype.Evaluate = function (transformA, transformB) {
        var axisA;
        var axisB;
        var localPointA;
        var localPointB;
        var pointA;
        var pointB;
        var separation = 0;
        var normal;
        switch (this.m_type) {
            case b2SeparationFunction.e_points:
            {
                axisA = b2Math.MulTMV(transformA.R, this.m_axis);
                axisB = b2Math.MulTMV(transformB.R, this.m_axis.GetNegative());
                localPointA = this.m_proxyA.GetSupportVertex(axisA);
                localPointB = this.m_proxyB.GetSupportVertex(axisB);
                pointA = b2Math.MulX(transformA, localPointA);
                pointB = b2Math.MulX(transformB, localPointB);
                separation = (pointB.x - pointA.x) * this.m_axis.x + (pointB.y - pointA.y) * this.m_axis.y;
                return separation;
            }
            case b2SeparationFunction.e_faceA:
            {
                normal = b2Math.MulMV(transformA.R, this.m_axis);
                pointA = b2Math.MulX(transformA, this.m_localPoint);
                axisB = b2Math.MulTMV(transformB.R, normal.GetNegative());
                localPointB = this.m_proxyB.GetSupportVertex(axisB);
                pointB = b2Math.MulX(transformB, localPointB);
                separation = (pointB.x - pointA.x) * normal.x + (pointB.y - pointA.y) * normal.y;
                return separation;
            }
            case b2SeparationFunction.e_faceB:
            {
                normal = b2Math.MulMV(transformB.R, this.m_axis);
                pointB = b2Math.MulX(transformB, this.m_localPoint);
                axisA = b2Math.MulTMV(transformA.R, normal.GetNegative());
                localPointA = this.m_proxyA.GetSupportVertex(axisA);
                pointA = b2Math.MulX(transformA, localPointA);
                separation = (pointA.x - pointB.x) * normal.x + (pointA.y - pointB.y) * normal.y;
                return separation;
            }
            default:
                b2Settings.b2Assert(false);
                return 0.0;
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.b2SeparationFunction.e_points = 0x01;
        Box2D.Collision.b2SeparationFunction.e_faceA = 0x02;
        Box2D.Collision.b2SeparationFunction.e_faceB = 0x04;
    });
    b2Simplex.b2Simplex = function () {
        this.m_v1 = new b2SimplexVertex();
        this.m_v2 = new b2SimplexVertex();
        this.m_v3 = new b2SimplexVertex();
        this.m_vertices = new Vector(3);
    };
    b2Simplex.prototype.b2Simplex = function () {
        this.m_vertices[0] = this.m_v1;
        this.m_vertices[1] = this.m_v2;
        this.m_vertices[2] = this.m_v3;
    }
    b2Simplex.prototype.ReadCache = function (cache, proxyA, transformA, proxyB, transformB) {
        b2Settings.b2Assert(0 <= cache.count && cache.count <= 3);
        var wALocal;
        var wBLocal;
        this.m_count = cache.count;
        var vertices = this.m_vertices;
        for (var i = 0; i < this.m_count; i++) {
            var v = vertices[i];
            v.indexA = cache.indexA[i];
            v.indexB = cache.indexB[i];
            wALocal = proxyA.GetVertex(v.indexA);
            wBLocal = proxyB.GetVertex(v.indexB);
            v.wA = b2Math.MulX(transformA, wALocal);
            v.wB = b2Math.MulX(transformB, wBLocal);
            v.w = b2Math.SubtractVV(v.wB, v.wA);
            v.a = 0;
        }
        if (this.m_count > 1) {
            var metric1 = cache.metric;
            var metric2 = this.GetMetric();
            if (metric2 < .5 * metric1 || 2.0 * metric1 < metric2 || metric2 < Number.MIN_VALUE) {
                this.m_count = 0;
            }
        }
        if (this.m_count == 0) {
            v = vertices[0];
            v.indexA = 0;
            v.indexB = 0;
            wALocal = proxyA.GetVertex(0);
            wBLocal = proxyB.GetVertex(0);
            v.wA = b2Math.MulX(transformA, wALocal);
            v.wB = b2Math.MulX(transformB, wBLocal);
            v.w = b2Math.SubtractVV(v.wB, v.wA);
            this.m_count = 1;
        }
    }
    b2Simplex.prototype.WriteCache = function (cache) {
        cache.metric = this.GetMetric();
        cache.count = Box2D.parseUInt(this.m_count);
        var vertices = this.m_vertices;
        for (var i = 0; i < this.m_count; i++) {
            cache.indexA[i] = Box2D.parseUInt(vertices[i].indexA);
            cache.indexB[i] = Box2D.parseUInt(vertices[i].indexB);
        }
    }
    b2Simplex.prototype.GetSearchDirection = function () {
        switch (this.m_count) {
            case 1:
                return this.m_v1.w.GetNegative();
            case 2:
            {
                var e12 = b2Math.SubtractVV(this.m_v2.w, this.m_v1.w);
                var sgn = b2Math.CrossVV(e12, this.m_v1.w.GetNegative());
                if (sgn > 0.0) {
                    return b2Math.CrossFV(1.0, e12);
                }
                else {
                    return b2Math.CrossVF(e12, 1.0);
                }
            }
            default:
                b2Settings.b2Assert(false);
                return new b2Vec2();
        }
    }
    b2Simplex.prototype.GetClosestPoint = function () {
        switch (this.m_count) {
            case 0:
                b2Settings.b2Assert(false);
                return new b2Vec2();
            case 1:
                return this.m_v1.w;
            case 2:
                return new b2Vec2(this.m_v1.a * this.m_v1.w.x + this.m_v2.a * this.m_v2.w.x, this.m_v1.a * this.m_v1.w.y + this.m_v2.a * this.m_v2.w.y);
            default:
                b2Settings.b2Assert(false);
                return new b2Vec2();
        }
    }
    b2Simplex.prototype.GetWitnessPoints = function (pA, pB) {
        switch (this.m_count) {
            case 0:
                b2Settings.b2Assert(false);
                break;
            case 1:
                pA.SetV(this.m_v1.wA);
                pB.SetV(this.m_v1.wB);
                break;
            case 2:
                pA.x = this.m_v1.a * this.m_v1.wA.x + this.m_v2.a * this.m_v2.wA.x;
                pA.y = this.m_v1.a * this.m_v1.wA.y + this.m_v2.a * this.m_v2.wA.y;
                pB.x = this.m_v1.a * this.m_v1.wB.x + this.m_v2.a * this.m_v2.wB.x;
                pB.y = this.m_v1.a * this.m_v1.wB.y + this.m_v2.a * this.m_v2.wB.y;
                break;
            case 3:
                pB.x = pA.x = this.m_v1.a * this.m_v1.wA.x + this.m_v2.a * this.m_v2.wA.x + this.m_v3.a * this.m_v3.wA.x;
                pB.y = pA.y = this.m_v1.a * this.m_v1.wA.y + this.m_v2.a * this.m_v2.wA.y + this.m_v3.a * this.m_v3.wA.y;
                break;
            default:
                b2Settings.b2Assert(false);
                break;
        }
    }
    b2Simplex.prototype.GetMetric = function () {
        switch (this.m_count) {
            case 0:
                b2Settings.b2Assert(false);
                return 0.0;
            case 1:
                return 0.0;
            case 2:
                return b2Math.SubtractVV(this.m_v1.w, this.m_v2.w).Length();
            case 3:
                return b2Math.CrossVV(b2Math.SubtractVV(this.m_v2.w, this.m_v1.w), b2Math.SubtractVV(this.m_v3.w, this.m_v1.w));
            default:
                b2Settings.b2Assert(false);
                return 0.0;
        }
    }
    b2Simplex.prototype.Solve2 = function () {
        var w1 = this.m_v1.w;
        var w2 = this.m_v2.w;
        var e12 = b2Math.SubtractVV(w2, w1);
        var d12_2 = (-(w1.x * e12.x + w1.y * e12.y));
        if (d12_2 <= 0.0) {
            this.m_v1.a = 1.0;
            this.m_count = 1;
            return;
        }
        var d12_1 = (w2.x * e12.x + w2.y * e12.y);
        if (d12_1 <= 0.0) {
            this.m_v2.a = 1.0;
            this.m_count = 1;
            this.m_v1.Set(this.m_v2);
            return;
        }
        var inv_d12 = 1.0 / (d12_1 + d12_2);
        this.m_v1.a = d12_1 * inv_d12;
        this.m_v2.a = d12_2 * inv_d12;
        this.m_count = 2;
    }
    b2Simplex.prototype.Solve3 = function () {
        var w1 = this.m_v1.w;
        var w2 = this.m_v2.w;
        var w3 = this.m_v3.w;
        var e12 = b2Math.SubtractVV(w2, w1);
        var w1e12 = b2Math.Dot(w1, e12);
        var w2e12 = b2Math.Dot(w2, e12);
        var d12_1 = w2e12;
        var d12_2 = (-w1e12);
        var e13 = b2Math.SubtractVV(w3, w1);
        var w1e13 = b2Math.Dot(w1, e13);
        var w3e13 = b2Math.Dot(w3, e13);
        var d13_1 = w3e13;
        var d13_2 = (-w1e13);
        var e23 = b2Math.SubtractVV(w3, w2);
        var w2e23 = b2Math.Dot(w2, e23);
        var w3e23 = b2Math.Dot(w3, e23);
        var d23_1 = w3e23;
        var d23_2 = (-w2e23);
        var n123 = b2Math.CrossVV(e12, e13);
        var d123_1 = n123 * b2Math.CrossVV(w2, w3);
        var d123_2 = n123 * b2Math.CrossVV(w3, w1);
        var d123_3 = n123 * b2Math.CrossVV(w1, w2);
        if (d12_2 <= 0.0 && d13_2 <= 0.0) {
            this.m_v1.a = 1.0;
            this.m_count = 1;
            return;
        }
        if (d12_1 > 0.0 && d12_2 > 0.0 && d123_3 <= 0.0) {
            var inv_d12 = 1.0 / (d12_1 + d12_2);
            this.m_v1.a = d12_1 * inv_d12;
            this.m_v2.a = d12_2 * inv_d12;
            this.m_count = 2;
            return;
        }
        if (d13_1 > 0.0 && d13_2 > 0.0 && d123_2 <= 0.0) {
            var inv_d13 = 1.0 / (d13_1 + d13_2);
            this.m_v1.a = d13_1 * inv_d13;
            this.m_v3.a = d13_2 * inv_d13;
            this.m_count = 2;
            this.m_v2.Set(this.m_v3);
            return;
        }
        if (d12_1 <= 0.0 && d23_2 <= 0.0) {
            this.m_v2.a = 1.0;
            this.m_count = 1;
            this.m_v1.Set(this.m_v2);
            return;
        }
        if (d13_1 <= 0.0 && d23_1 <= 0.0) {
            this.m_v3.a = 1.0;
            this.m_count = 1;
            this.m_v1.Set(this.m_v3);
            return;
        }
        if (d23_1 > 0.0 && d23_2 > 0.0 && d123_1 <= 0.0) {
            var inv_d23 = 1.0 / (d23_1 + d23_2);
            this.m_v2.a = d23_1 * inv_d23;
            this.m_v3.a = d23_2 * inv_d23;
            this.m_count = 2;
            this.m_v1.Set(this.m_v3);
            return;
        }
        var inv_d123 = 1.0 / (d123_1 + d123_2 + d123_3);
        this.m_v1.a = d123_1 * inv_d123;
        this.m_v2.a = d123_2 * inv_d123;
        this.m_v3.a = d123_3 * inv_d123;
        this.m_count = 3;
    }
    b2SimplexCache.b2SimplexCache = function () {
        this.indexA = new Vector_a2j_Number(3);
        this.indexB = new Vector_a2j_Number(3);
    };
    b2SimplexVertex.b2SimplexVertex = function () {};
    b2SimplexVertex.prototype.Set = function (other) {
        this.wA.SetV(other.wA);
        this.wB.SetV(other.wB);
        this.w.SetV(other.w);
        this.a = other.a;
        this.indexA = other.indexA;
        this.indexB = other.indexB;
    }
    b2TimeOfImpact.b2TimeOfImpact = function () {};
    b2TimeOfImpact.TimeOfImpact = function (input) {
        ++b2TimeOfImpact.b2_toiCalls;
        var proxyA = input.proxyA;
        var proxyB = input.proxyB;
        var sweepA = input.sweepA;
        var sweepB = input.sweepB;
        b2Settings.b2Assert(sweepA.t0 == sweepB.t0);
        b2Settings.b2Assert(1.0 - sweepA.t0 > Number.MIN_VALUE);
        var radius = proxyA.m_radius + proxyB.m_radius;
        var tolerance = input.tolerance;
        var alpha = 0.0;
        var k_maxIterations = 1000;
        var iter = 0;
        var target = 0.0;
        b2TimeOfImpact.s_cache.count = 0;
        b2TimeOfImpact.s_distanceInput.useRadii = false;
        for (;;) {
            sweepA.GetTransform(b2TimeOfImpact.s_xfA, alpha);
            sweepB.GetTransform(b2TimeOfImpact.s_xfB, alpha);
            b2TimeOfImpact.s_distanceInput.proxyA = proxyA;
            b2TimeOfImpact.s_distanceInput.proxyB = proxyB;
            b2TimeOfImpact.s_distanceInput.transformA = b2TimeOfImpact.s_xfA;
            b2TimeOfImpact.s_distanceInput.transformB = b2TimeOfImpact.s_xfB;
            b2Distance.Distance(b2TimeOfImpact.s_distanceOutput, b2TimeOfImpact.s_cache, b2TimeOfImpact.s_distanceInput);
            if (b2TimeOfImpact.s_distanceOutput.distance <= 0.0) {
                alpha = 1.0;
                break;
            }
            b2TimeOfImpact.s_fcn.Initialize(b2TimeOfImpact.s_cache, proxyA, b2TimeOfImpact.s_xfA, proxyB, b2TimeOfImpact.s_xfB);
            var separation = b2TimeOfImpact.s_fcn.Evaluate(b2TimeOfImpact.s_xfA, b2TimeOfImpact.s_xfB);
            if (separation <= 0.0) {
                alpha = 1.0;
                break;
            }
            if (iter == 0) {
                if (separation > radius) {
                    target = b2Math.Max(radius - tolerance, 0.75 * radius);
                }
                else {
                    target = b2Math.Max(separation - tolerance, 0.02 * radius);
                }
            }
            if (separation - target < 0.5 * tolerance) {
                if (iter == 0) {
                    alpha = 1.0;
                    break;
                }
                break;
            }
            var newAlpha = alpha; {
                var x1 = alpha;
                var x2 = 1.0;
                var f1 = separation;
                sweepA.GetTransform(b2TimeOfImpact.s_xfA, x2);
                sweepB.GetTransform(b2TimeOfImpact.s_xfB, x2);
                var f2 = b2TimeOfImpact.s_fcn.Evaluate(b2TimeOfImpact.s_xfA, b2TimeOfImpact.s_xfB);
                if (f2 >= target) {
                    alpha = 1.0;
                    break;
                }
                var rootIterCount = 0;
                for (;;) {
                    var x = 0;
                    if (rootIterCount & 1) {
                        x = x1 + (target - f1) * (x2 - x1) / (f2 - f1);
                    }
                    else {
                        x = 0.5 * (x1 + x2);
                    }
                    sweepA.GetTransform(b2TimeOfImpact.s_xfA, x);
                    sweepB.GetTransform(b2TimeOfImpact.s_xfB, x);
                    var f = b2TimeOfImpact.s_fcn.Evaluate(b2TimeOfImpact.s_xfA, b2TimeOfImpact.s_xfB);
                    if (b2Math.Abs(f - target) < 0.025 * tolerance) {
                        newAlpha = x;
                        break;
                    }
                    if (f > target) {
                        x1 = x;
                        f1 = f;
                    }
                    else {
                        x2 = x;
                        f2 = f;
                    }++rootIterCount;
                    ++b2TimeOfImpact.b2_toiRootIters;
                    if (rootIterCount == 50) {
                        break;
                    }
                }
                b2TimeOfImpact.b2_toiMaxRootIters = b2Math.Max(b2TimeOfImpact.b2_toiMaxRootIters, rootIterCount);
            }
            if (newAlpha < (1.0 + 100.0 * Number.MIN_VALUE) * alpha) {
                break;
            }
            alpha = newAlpha;
            iter++;
            ++b2TimeOfImpact.b2_toiIters;
            if (iter == k_maxIterations) {
                break;
            }
        }
        b2TimeOfImpact.b2_toiMaxIters = b2Math.Max(b2TimeOfImpact.b2_toiMaxIters, iter);
        return alpha;
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.b2TimeOfImpact.b2_toiCalls = 0;
        Box2D.Collision.b2TimeOfImpact.b2_toiIters = 0;
        Box2D.Collision.b2TimeOfImpact.b2_toiMaxIters = 0;
        Box2D.Collision.b2TimeOfImpact.b2_toiRootIters = 0;
        Box2D.Collision.b2TimeOfImpact.b2_toiMaxRootIters = 0;
        Box2D.Collision.b2TimeOfImpact.s_cache = new b2SimplexCache();
        Box2D.Collision.b2TimeOfImpact.s_distanceInput = new b2DistanceInput();
        Box2D.Collision.b2TimeOfImpact.s_xfA = new b2Transform();
        Box2D.Collision.b2TimeOfImpact.s_xfB = new b2Transform();
        Box2D.Collision.b2TimeOfImpact.s_fcn = new b2SeparationFunction();
        Box2D.Collision.b2TimeOfImpact.s_distanceOutput = new b2DistanceOutput();
    });
    b2TOIInput.b2TOIInput = function () {
        this.proxyA = new b2DistanceProxy();
        this.proxyB = new b2DistanceProxy();
        this.sweepA = new b2Sweep();
        this.sweepB = new b2Sweep();
    };
    b2WorldManifold.b2WorldManifold = function () {
        this.m_normal = new b2Vec2();
    };
    b2WorldManifold.prototype.b2WorldManifold = function () {
        this.m_points = new Vector(b2Settings.b2_maxManifoldPoints);
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++) {
            this.m_points[i] = new b2Vec2();
        }
    }
    b2WorldManifold.prototype.Initialize = function (manifold, xfA, radiusA, xfB, radiusB) {
        if (radiusA === undefined) radiusA = 0;
        if (radiusB === undefined) radiusB = 0;
        if (manifold.m_pointCount == 0) {
            return;
        }
        var i = 0;
        var tVec;
        var tMat;
        var normalX = 0;
        var normalY = 0;
        var planePointX = 0;
        var planePointY = 0;
        var clipPointX = 0;
        var clipPointY = 0;
        switch (manifold.m_type) {
            case b2Manifold.e_circles:
            {
                tMat = xfA.R;
                tVec = manifold.m_localPoint;
                var pointAX = xfA.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                var pointAY = xfA.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tMat = xfB.R;
                tVec = manifold.m_points[0].m_localPoint;
                var pointBX = xfB.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                var pointBY = xfB.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                var dX = pointBX - pointAX;
                var dY = pointBY - pointAY;
                var d2 = dX * dX + dY * dY;
                if (d2 > Number.MIN_VALUE * Number.MIN_VALUE) {
                    var d = Math.sqrt(d2);
                    this.m_normal.x = dX / d;
                    this.m_normal.y = dY / d;
                }
                else {
                    this.m_normal.x = 1;
                    this.m_normal.y = 0;
                }
                var cAX = pointAX + radiusA * this.m_normal.x;
                var cAY = pointAY + radiusA * this.m_normal.y;
                var cBX = pointBX - radiusB * this.m_normal.x;
                var cBY = pointBY - radiusB * this.m_normal.y;
                this.m_points[0].x = 0.5 * (cAX + cBX);
                this.m_points[0].y = 0.5 * (cAY + cBY);
            }
                break;
            case b2Manifold.e_faceA:
            {
                tMat = xfA.R;
                tVec = manifold.m_localPlaneNormal;
                normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tMat = xfA.R;
                tVec = manifold.m_localPoint;
                planePointX = xfA.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                planePointY = xfA.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                this.m_normal.x = normalX;
                this.m_normal.y = normalY;
                for (i = 0;
                     i < manifold.m_pointCount; i++) {
                    tMat = xfB.R;
                    tVec = manifold.m_points[i].m_localPoint;
                    clipPointX = xfB.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                    clipPointY = xfB.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                    this.m_points[i].x = clipPointX + 0.5 * (radiusA - (clipPointX - planePointX) * normalX - (clipPointY - planePointY) * normalY - radiusB) * normalX;
                    this.m_points[i].y = clipPointY + 0.5 * (radiusA - (clipPointX - planePointX) * normalX - (clipPointY - planePointY) * normalY - radiusB) * normalY;
                }
            }
                break;
            case b2Manifold.e_faceB:
            {
                tMat = xfB.R;
                tVec = manifold.m_localPlaneNormal;
                normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tMat = xfB.R;
                tVec = manifold.m_localPoint;
                planePointX = xfB.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                planePointY = xfB.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                this.m_normal.x = (-normalX);
                this.m_normal.y = (-normalY);
                for (i = 0;
                     i < manifold.m_pointCount; i++) {
                    tMat = xfA.R;
                    tVec = manifold.m_points[i].m_localPoint;
                    clipPointX = xfA.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                    clipPointY = xfA.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                    this.m_points[i].x = clipPointX + 0.5 * (radiusB - (clipPointX - planePointX) * normalX - (clipPointY - planePointY) * normalY - radiusA) * normalX;
                    this.m_points[i].y = clipPointY + 0.5 * (radiusB - (clipPointX - planePointX) * normalX - (clipPointY - planePointY) * normalY - radiusA) * normalY;
                }
            }
                break;
        }
    }
    ClipVertex.ClipVertex = function () {
        this.v = new b2Vec2();
        this.id = new b2ContactID();
    };
    ClipVertex.prototype.Set = function (other) {
        this.v.SetV(other.v);
        this.id.Set(other.id);
    }
    Features.Features = function () {};
    Object.defineProperty(Features.prototype, 'referenceEdge', {
        enumerable: false,
        configurable: true,
        get: function () {
            return this._referenceEdge;
        }
    });
    Object.defineProperty(Features.prototype, 'referenceEdge', {
        enumerable: false,
        configurable: true,
        set: function (value) {
            if (value === undefined) value = 0;
            this._referenceEdge = value;
            this._m_id._key = (this._m_id._key & 0xffffff00) | (this._referenceEdge & 0x000000ff);
        }
    });
    Object.defineProperty(Features.prototype, 'incidentEdge', {
        enumerable: false,
        configurable: true,
        get: function () {
            return this._incidentEdge;
        }
    });
    Object.defineProperty(Features.prototype, 'incidentEdge', {
        enumerable: false,
        configurable: true,
        set: function (value) {
            if (value === undefined) value = 0;
            this._incidentEdge = value;
            this._m_id._key = (this._m_id._key & 0xffff00ff) | ((this._incidentEdge << 8) & 0x0000ff00);
        }
    });
    Object.defineProperty(Features.prototype, 'incidentVertex', {
        enumerable: false,
        configurable: true,
        get: function () {
            return this._incidentVertex;
        }
    });
    Object.defineProperty(Features.prototype, 'incidentVertex', {
        enumerable: false,
        configurable: true,
        set: function (value) {
            if (value === undefined) value = 0;
            this._incidentVertex = value;
            this._m_id._key = (this._m_id._key & 0xff00ffff) | ((this._incidentVertex << 16) & 0x00ff0000);
        }
    });
    Object.defineProperty(Features.prototype, 'flip', {
        enumerable: false,
        configurable: true,
        get: function () {
            return this._flip;
        }
    });
    Object.defineProperty(Features.prototype, 'flip', {
        enumerable: false,
        configurable: true,
        set: function (value) {
            if (value === undefined) value = 0;
            this._flip = value;
            this._m_id._key = (this._m_id._key & 0x00ffffff) | ((this._flip << 24) & 0xff000000);
        }
    });
})();
(function () {
    var b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
        b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
        b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
        b2MassData = Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
        b2Shape = Box2D.Collision.Shapes.b2Shape,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3,
        b2Body = Box2D.Dynamics.b2Body,
        b2BodyDef = Box2D.Dynamics.b2BodyDef,
        b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
        b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
        b2ContactListener = Box2D.Dynamics.b2ContactListener,
        b2ContactManager = Box2D.Dynamics.b2ContactManager,
        b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
        b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
        b2FilterData = Box2D.Dynamics.b2FilterData,
        b2Fixture = Box2D.Dynamics.b2Fixture,
        b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
        b2Island = Box2D.Dynamics.b2Island,
        b2TimeStep = Box2D.Dynamics.b2TimeStep,
        b2World = Box2D.Dynamics.b2World,
        b2AABB = Box2D.Collision.b2AABB,
        b2Bound = Box2D.Collision.b2Bound,
        b2BoundValues = Box2D.Collision.b2BoundValues,
        b2Collision = Box2D.Collision.b2Collision,
        b2ContactID = Box2D.Collision.b2ContactID,
        b2ContactPoint = Box2D.Collision.b2ContactPoint,
        b2Distance = Box2D.Collision.b2Distance,
        b2DistanceInput = Box2D.Collision.b2DistanceInput,
        b2DistanceOutput = Box2D.Collision.b2DistanceOutput,
        b2DistanceProxy = Box2D.Collision.b2DistanceProxy,
        b2DynamicTree = Box2D.Collision.b2DynamicTree,
        b2DynamicTreeBroadPhase = Box2D.Collision.b2DynamicTreeBroadPhase,
        b2DynamicTreeNode = Box2D.Collision.b2DynamicTreeNode,
        b2DynamicTreePair = Box2D.Collision.b2DynamicTreePair,
        b2Manifold = Box2D.Collision.b2Manifold,
        b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint,
        b2Point = Box2D.Collision.b2Point,
        b2RayCastInput = Box2D.Collision.b2RayCastInput,
        b2RayCastOutput = Box2D.Collision.b2RayCastOutput,
        b2Segment = Box2D.Collision.b2Segment,
        b2SeparationFunction = Box2D.Collision.b2SeparationFunction,
        b2Simplex = Box2D.Collision.b2Simplex,
        b2SimplexCache = Box2D.Collision.b2SimplexCache,
        b2SimplexVertex = Box2D.Collision.b2SimplexVertex,
        b2TimeOfImpact = Box2D.Collision.b2TimeOfImpact,
        b2TOIInput = Box2D.Collision.b2TOIInput,
        b2WorldManifold = Box2D.Collision.b2WorldManifold,
        ClipVertex = Box2D.Collision.ClipVertex,
        Features = Box2D.Collision.Features,
        IBroadPhase = Box2D.Collision.IBroadPhase;
    Box2D.inherit(b2CircleShape, Box2D.Collision.Shapes.b2Shape);
    b2CircleShape.prototype.__super = Box2D.Collision.Shapes.b2Shape.prototype;
    b2CircleShape.b2CircleShape = function () {
        Box2D.Collision.Shapes.b2Shape.b2Shape.apply(this, arguments);
        this.m_p = new b2Vec2();
    };
    b2CircleShape.prototype.Copy = function () {
        var s = new b2CircleShape();
        s.Set(this);
        return s;
    }
    b2CircleShape.prototype.Set = function (other) {
        this.__super.Set.call(this, other);
        if (Box2D.is(other, b2CircleShape)) {
            var other2 = (other instanceof b2CircleShape ? other : null);
            this.m_p.SetV(other2.m_p);
        }
    }
    b2CircleShape.prototype.TestPoint = function (transform, p) {
        var tMat = transform.R;
        var dX = transform.position.x + (tMat.col1.x * this.m_p.x + tMat.col2.x * this.m_p.y);
        var dY = transform.position.y + (tMat.col1.y * this.m_p.x + tMat.col2.y * this.m_p.y);
        dX = p.x - dX;
        dY = p.y - dY;
        return (dX * dX + dY * dY) <= this.m_radius * this.m_radius;
    }
    b2CircleShape.prototype.RayCast = function (output, input, transform) {
        var tMat = transform.R;
        var positionX = transform.position.x + (tMat.col1.x * this.m_p.x + tMat.col2.x * this.m_p.y);
        var positionY = transform.position.y + (tMat.col1.y * this.m_p.x + tMat.col2.y * this.m_p.y);
        var sX = input.p1.x - positionX;
        var sY = input.p1.y - positionY;
        var b = (sX * sX + sY * sY) - this.m_radius * this.m_radius;
        var rX = input.p2.x - input.p1.x;
        var rY = input.p2.y - input.p1.y;
        var c = (sX * rX + sY * rY);
        var rr = (rX * rX + rY * rY);
        var sigma = c * c - rr * b;
        if (sigma < 0.0 || rr < Number.MIN_VALUE) {
            return false;
        }
        var a = (-(c + Math.sqrt(sigma)));
        if (0.0 <= a && a <= input.maxFraction * rr) {
            a /= rr;
            output.fraction = a;
            output.normal.x = sX + a * rX;
            output.normal.y = sY + a * rY;
            output.normal.Normalize();
            return true;
        }
        return false;
    }
    b2CircleShape.prototype.ComputeAABB = function (aabb, transform) {
        var tMat = transform.R;
        var pX = transform.position.x + (tMat.col1.x * this.m_p.x + tMat.col2.x * this.m_p.y);
        var pY = transform.position.y + (tMat.col1.y * this.m_p.x + tMat.col2.y * this.m_p.y);
        aabb.lowerBound.Set(pX - this.m_radius, pY - this.m_radius);
        aabb.upperBound.Set(pX + this.m_radius, pY + this.m_radius);
    }
    b2CircleShape.prototype.ComputeMass = function (massData, density) {
        if (density === undefined) density = 0;
        massData.mass = density * b2Settings.b2_pi * this.m_radius * this.m_radius;
        massData.center.SetV(this.m_p);
        massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + (this.m_p.x * this.m_p.x + this.m_p.y * this.m_p.y));
    }
    b2CircleShape.prototype.ComputeSubmergedArea = function (normal, offset, xf, c) {
        if (offset === undefined) offset = 0;
        var p = b2Math.MulX(xf, this.m_p);
        var l = (-(b2Math.Dot(normal, p) - offset));
        if (l < (-this.m_radius) + Number.MIN_VALUE) {
            return 0;
        }
        if (l > this.m_radius) {
            c.SetV(p);
            return Math.PI * this.m_radius * this.m_radius;
        }
        var r2 = this.m_radius * this.m_radius;
        var l2 = l * l;
        var area = r2 * (Math.asin(l / this.m_radius) + Math.PI / 2) + l * Math.sqrt(r2 - l2);
        var com = (-2 / 3 * Math.pow(r2 - l2, 1.5) / area);
        c.x = p.x + normal.x * com;
        c.y = p.y + normal.y * com;
        return area;
    }
    b2CircleShape.prototype.GetLocalPosition = function () {
        return this.m_p;
    }
    b2CircleShape.prototype.SetLocalPosition = function (position) {
        this.m_p.SetV(position);
    }
    b2CircleShape.prototype.GetRadius = function () {
        return this.m_radius;
    }
    b2CircleShape.prototype.SetRadius = function (radius) {
        if (radius === undefined) radius = 0;
        this.m_radius = radius;
    }
    b2CircleShape.prototype.b2CircleShape = function (radius) {
        if (radius === undefined) radius = 0;
        this.__super.b2Shape.call(this);
        this.m_type = b2Shape.e_circleShape;
        this.m_radius = radius;
    }
    b2EdgeChainDef.b2EdgeChainDef = function () {};
    b2EdgeChainDef.prototype.b2EdgeChainDef = function () {
        this.vertexCount = 0;
        this.isALoop = true;
        this.vertices = [];
    }
    Box2D.inherit(b2EdgeShape, Box2D.Collision.Shapes.b2Shape);
    b2EdgeShape.prototype.__super = Box2D.Collision.Shapes.b2Shape.prototype;
    b2EdgeShape.b2EdgeShape = function () {
        Box2D.Collision.Shapes.b2Shape.b2Shape.apply(this, arguments);
        this.s_supportVec = new b2Vec2();
        this.m_v1 = new b2Vec2();
        this.m_v2 = new b2Vec2();
        this.m_coreV1 = new b2Vec2();
        this.m_coreV2 = new b2Vec2();
        this.m_normal = new b2Vec2();
        this.m_direction = new b2Vec2();
        this.m_cornerDir1 = new b2Vec2();
        this.m_cornerDir2 = new b2Vec2();
    };
    b2EdgeShape.prototype.TestPoint = function (transform, p) {
        return false;
    }
    b2EdgeShape.prototype.RayCast = function (output, input, transform) {
        var tMat;
        var rX = input.p2.x - input.p1.x;
        var rY = input.p2.y - input.p1.y;
        tMat = transform.R;
        var v1X = transform.position.x + (tMat.col1.x * this.m_v1.x + tMat.col2.x * this.m_v1.y);
        var v1Y = transform.position.y + (tMat.col1.y * this.m_v1.x + tMat.col2.y * this.m_v1.y);
        var nX = transform.position.y + (tMat.col1.y * this.m_v2.x + tMat.col2.y * this.m_v2.y) - v1Y;
        var nY = (-(transform.position.x + (tMat.col1.x * this.m_v2.x + tMat.col2.x * this.m_v2.y) - v1X));
        var k_slop = 100.0 * Number.MIN_VALUE;
        var denom = (-(rX * nX + rY * nY));
        if (denom > k_slop) {
            var bX = input.p1.x - v1X;
            var bY = input.p1.y - v1Y;
            var a = (bX * nX + bY * nY);
            if (0.0 <= a && a <= input.maxFraction * denom) {
                var mu2 = (-rX * bY) + rY * bX;
                if ((-k_slop * denom) <= mu2 && mu2 <= denom * (1.0 + k_slop)) {
                    a /= denom;
                    output.fraction = a;
                    var nLen = Math.sqrt(nX * nX + nY * nY);
                    output.normal.x = nX / nLen;
                    output.normal.y = nY / nLen;
                    return true;
                }
            }
        }
        return false;
    }
    b2EdgeShape.prototype.ComputeAABB = function (aabb, transform) {
        var tMat = transform.R;
        var v1X = transform.position.x + (tMat.col1.x * this.m_v1.x + tMat.col2.x * this.m_v1.y);
        var v1Y = transform.position.y + (tMat.col1.y * this.m_v1.x + tMat.col2.y * this.m_v1.y);
        var v2X = transform.position.x + (tMat.col1.x * this.m_v2.x + tMat.col2.x * this.m_v2.y);
        var v2Y = transform.position.y + (tMat.col1.y * this.m_v2.x + tMat.col2.y * this.m_v2.y);
        if (v1X < v2X) {
            aabb.lowerBound.x = v1X;
            aabb.upperBound.x = v2X;
        }
        else {
            aabb.lowerBound.x = v2X;
            aabb.upperBound.x = v1X;
        }
        if (v1Y < v2Y) {
            aabb.lowerBound.y = v1Y;
            aabb.upperBound.y = v2Y;
        }
        else {
            aabb.lowerBound.y = v2Y;
            aabb.upperBound.y = v1Y;
        }
    }
    b2EdgeShape.prototype.ComputeMass = function (massData, density) {
        if (density === undefined) density = 0;
        massData.mass = 0;
        massData.center.SetV(this.m_v1);
        massData.I = 0;
    }
    b2EdgeShape.prototype.ComputeSubmergedArea = function (normal, offset, xf, c) {
        if (offset === undefined) offset = 0;
        var v0 = new b2Vec2(normal.x * offset, normal.y * offset);
        var v1 = b2Math.MulX(xf, this.m_v1);
        var v2 = b2Math.MulX(xf, this.m_v2);
        var d1 = b2Math.Dot(normal, v1) - offset;
        var d2 = b2Math.Dot(normal, v2) - offset;
        if (d1 > 0) {
            if (d2 > 0) {
                return 0;
            }
            else {
                v1.x = (-d2 / (d1 - d2) * v1.x) + d1 / (d1 - d2) * v2.x;
                v1.y = (-d2 / (d1 - d2) * v1.y) + d1 / (d1 - d2) * v2.y;
            }
        }
        else {
            if (d2 > 0) {
                v2.x = (-d2 / (d1 - d2) * v1.x) + d1 / (d1 - d2) * v2.x;
                v2.y = (-d2 / (d1 - d2) * v1.y) + d1 / (d1 - d2) * v2.y;
            }
            else {}
        }
        c.x = (v0.x + v1.x + v2.x) / 3;
        c.y = (v0.y + v1.y + v2.y) / 3;
        return 0.5 * ((v1.x - v0.x) * (v2.y - v0.y) - (v1.y - v0.y) * (v2.x - v0.x));
    }
    b2EdgeShape.prototype.GetLength = function () {
        return this.m_length;
    }
    b2EdgeShape.prototype.GetVertex1 = function () {
        return this.m_v1;
    }
    b2EdgeShape.prototype.GetVertex2 = function () {
        return this.m_v2;
    }
    b2EdgeShape.prototype.GetCoreVertex1 = function () {
        return this.m_coreV1;
    }
    b2EdgeShape.prototype.GetCoreVertex2 = function () {
        return this.m_coreV2;
    }
    b2EdgeShape.prototype.GetNormalVector = function () {
        return this.m_normal;
    }
    b2EdgeShape.prototype.GetDirectionVector = function () {
        return this.m_direction;
    }
    b2EdgeShape.prototype.GetCorner1Vector = function () {
        return this.m_cornerDir1;
    }
    b2EdgeShape.prototype.GetCorner2Vector = function () {
        return this.m_cornerDir2;
    }
    b2EdgeShape.prototype.Corner1IsConvex = function () {
        return this.m_cornerConvex1;
    }
    b2EdgeShape.prototype.Corner2IsConvex = function () {
        return this.m_cornerConvex2;
    }
    b2EdgeShape.prototype.GetFirstVertex = function (xf) {
        var tMat = xf.R;
        return new b2Vec2(xf.position.x + (tMat.col1.x * this.m_coreV1.x + tMat.col2.x * this.m_coreV1.y), xf.position.y + (tMat.col1.y * this.m_coreV1.x + tMat.col2.y * this.m_coreV1.y));
    }
    b2EdgeShape.prototype.GetNextEdge = function () {
        return this.m_nextEdge;
    }
    b2EdgeShape.prototype.GetPrevEdge = function () {
        return this.m_prevEdge;
    }
    b2EdgeShape.prototype.Support = function (xf, dX, dY) {
        if (dX === undefined) dX = 0;
        if (dY === undefined) dY = 0;
        var tMat = xf.R;
        var v1X = xf.position.x + (tMat.col1.x * this.m_coreV1.x + tMat.col2.x * this.m_coreV1.y);
        var v1Y = xf.position.y + (tMat.col1.y * this.m_coreV1.x + tMat.col2.y * this.m_coreV1.y);
        var v2X = xf.position.x + (tMat.col1.x * this.m_coreV2.x + tMat.col2.x * this.m_coreV2.y);
        var v2Y = xf.position.y + (tMat.col1.y * this.m_coreV2.x + tMat.col2.y * this.m_coreV2.y);
        if ((v1X * dX + v1Y * dY) > (v2X * dX + v2Y * dY)) {
            this.s_supportVec.x = v1X;
            this.s_supportVec.y = v1Y;
        }
        else {
            this.s_supportVec.x = v2X;
            this.s_supportVec.y = v2Y;
        }
        return this.s_supportVec;
    }
    b2EdgeShape.prototype.b2EdgeShape = function (v1, v2) {
        this.__super.b2Shape.call(this);
        this.m_type = b2Shape.e_edgeShape;
        this.m_prevEdge = null;
        this.m_nextEdge = null;
        this.m_v1 = v1;
        this.m_v2 = v2;
        this.m_direction.Set(this.m_v2.x - this.m_v1.x, this.m_v2.y - this.m_v1.y);
        this.m_length = this.m_direction.Normalize();
        this.m_normal.Set(this.m_direction.y, (-this.m_direction.x));
        this.m_coreV1.Set((-b2Settings.b2_toiSlop * (this.m_normal.x - this.m_direction.x)) + this.m_v1.x, (-b2Settings.b2_toiSlop * (this.m_normal.y - this.m_direction.y)) + this.m_v1.y);
        this.m_coreV2.Set((-b2Settings.b2_toiSlop * (this.m_normal.x + this.m_direction.x)) + this.m_v2.x, (-b2Settings.b2_toiSlop * (this.m_normal.y + this.m_direction.y)) + this.m_v2.y);
        this.m_cornerDir1 = this.m_normal;
        this.m_cornerDir2.Set((-this.m_normal.x), (-this.m_normal.y));
    }
    b2EdgeShape.prototype.SetPrevEdge = function (edge, core, cornerDir, convex) {
        this.m_prevEdge = edge;
        this.m_coreV1 = core;
        this.m_cornerDir1 = cornerDir;
        this.m_cornerConvex1 = convex;
    }
    b2EdgeShape.prototype.SetNextEdge = function (edge, core, cornerDir, convex) {
        this.m_nextEdge = edge;
        this.m_coreV2 = core;
        this.m_cornerDir2 = cornerDir;
        this.m_cornerConvex2 = convex;
    }
    b2MassData.b2MassData = function () {
        this.mass = 0.0;
        this.center = new b2Vec2(0, 0);
        this.I = 0.0;
    };
    Box2D.inherit(b2PolygonShape, Box2D.Collision.Shapes.b2Shape);
    b2PolygonShape.prototype.__super = Box2D.Collision.Shapes.b2Shape.prototype;
    b2PolygonShape.b2PolygonShape = function () {
        Box2D.Collision.Shapes.b2Shape.b2Shape.apply(this, arguments);
    };
    b2PolygonShape.prototype.Copy = function () {
        var s = new b2PolygonShape();
        s.Set(this);
        return s;
    }
    b2PolygonShape.prototype.Set = function (other) {
        this.__super.Set.call(this, other);
        if (Box2D.is(other, b2PolygonShape)) {
            var other2 = (other instanceof b2PolygonShape ? other : null);
            this.m_centroid.SetV(other2.m_centroid);
            this.m_vertexCount = other2.m_vertexCount;
            this.Reserve(this.m_vertexCount);
            for (var i = 0; i < this.m_vertexCount; i++) {
                this.m_vertices[i].SetV(other2.m_vertices[i]);
                this.m_normals[i].SetV(other2.m_normals[i]);
            }
        }
    }
    b2PolygonShape.prototype.SetAsArray = function (vertices, vertexCount) {
        if (vertexCount === undefined) vertexCount = 0;
        var v = new Vector();
        var i = 0,
            tVec;
        for (i = 0;
             i < vertices.length; ++i) {
            tVec = vertices[i];
            v.push(tVec);
        }
        this.SetAsVector(v, vertexCount);
    }
    b2PolygonShape.AsArray = function (vertices, vertexCount) {
        if (vertexCount === undefined) vertexCount = 0;
        var polygonShape = new b2PolygonShape();
        polygonShape.SetAsArray(vertices, vertexCount);
        return polygonShape;
    }
    b2PolygonShape.prototype.SetAsVector = function (vertices, vertexCount) {
        if (vertexCount === undefined) vertexCount = 0;
        if (vertexCount == 0) vertexCount = vertices.length;
        b2Settings.b2Assert(2 <= vertexCount);
        this.m_vertexCount = vertexCount;
        this.Reserve(vertexCount);
        var i = 0;
        for (i = 0;
             i < this.m_vertexCount; i++) {
            this.m_vertices[i].SetV(vertices[i]);
        }
        for (i = 0;
             i < this.m_vertexCount; ++i) {
            var i1 = parseInt(i);
            var i2 = parseInt(i + 1 < this.m_vertexCount ? i + 1 : 0);
            var edge = b2Math.SubtractVV(this.m_vertices[i2], this.m_vertices[i1]);
            b2Settings.b2Assert(edge.LengthSquared() > Number.MIN_VALUE);
            this.m_normals[i].SetV(b2Math.CrossVF(edge, 1.0));
            this.m_normals[i].Normalize();
        }
        this.m_centroid = b2PolygonShape.ComputeCentroid(this.m_vertices, this.m_vertexCount);
    }
    b2PolygonShape.AsVector = function (vertices, vertexCount) {
        if (vertexCount === undefined) vertexCount = 0;
        var polygonShape = new b2PolygonShape();
        polygonShape.SetAsVector(vertices, vertexCount);
        return polygonShape;
    }
    b2PolygonShape.prototype.SetAsBox = function (hx, hy) {
        if (hx === undefined) hx = 0;
        if (hy === undefined) hy = 0;
        this.m_vertexCount = 4;
        this.Reserve(4);
        this.m_vertices[0].Set((-hx), (-hy));
        this.m_vertices[1].Set(hx, (-hy));
        this.m_vertices[2].Set(hx, hy);
        this.m_vertices[3].Set((-hx), hy);
        this.m_normals[0].Set(0.0, (-1.0));
        this.m_normals[1].Set(1.0, 0.0);
        this.m_normals[2].Set(0.0, 1.0);
        this.m_normals[3].Set((-1.0), 0.0);
        this.m_centroid.SetZero();
    }
    b2PolygonShape.AsBox = function (hx, hy) {
        if (hx === undefined) hx = 0;
        if (hy === undefined) hy = 0;
        var polygonShape = new b2PolygonShape();
        polygonShape.SetAsBox(hx, hy);
        return polygonShape;
    }
    b2PolygonShape.prototype.SetAsOrientedBox = function (hx, hy, center, angle) {
        if (hx === undefined) hx = 0;
        if (hy === undefined) hy = 0;
        if (center === undefined) center = null;
        if (angle === undefined) angle = 0.0;
        this.m_vertexCount = 4;
        this.Reserve(4);
        this.m_vertices[0].Set((-hx), (-hy));
        this.m_vertices[1].Set(hx, (-hy));
        this.m_vertices[2].Set(hx, hy);
        this.m_vertices[3].Set((-hx), hy);
        this.m_normals[0].Set(0.0, (-1.0));
        this.m_normals[1].Set(1.0, 0.0);
        this.m_normals[2].Set(0.0, 1.0);
        this.m_normals[3].Set((-1.0), 0.0);
        this.m_centroid = center;
        var xf = new b2Transform();
        xf.position = center;
        xf.R.Set(angle);
        for (var i = 0; i < this.m_vertexCount; ++i) {
            this.m_vertices[i] = b2Math.MulX(xf, this.m_vertices[i]);
            this.m_normals[i] = b2Math.MulMV(xf.R, this.m_normals[i]);
        }
    }
    b2PolygonShape.AsOrientedBox = function (hx, hy, center, angle) {
        if (hx === undefined) hx = 0;
        if (hy === undefined) hy = 0;
        if (center === undefined) center = null;
        if (angle === undefined) angle = 0.0;
        var polygonShape = new b2PolygonShape();
        polygonShape.SetAsOrientedBox(hx, hy, center, angle);
        return polygonShape;
    }
    b2PolygonShape.prototype.SetAsEdge = function (v1, v2) {
        this.m_vertexCount = 2;
        this.Reserve(2);
        this.m_vertices[0].SetV(v1);
        this.m_vertices[1].SetV(v2);
        this.m_centroid.x = 0.5 * (v1.x + v2.x);
        this.m_centroid.y = 0.5 * (v1.y + v2.y);
        this.m_normals[0] = b2Math.CrossVF(b2Math.SubtractVV(v2, v1), 1.0);
        this.m_normals[0].Normalize();
        this.m_normals[1].x = (-this.m_normals[0].x);
        this.m_normals[1].y = (-this.m_normals[0].y);
    }
    b2PolygonShape.AsEdge = function (v1, v2) {
        var polygonShape = new b2PolygonShape();
        polygonShape.SetAsEdge(v1, v2);
        return polygonShape;
    }
    b2PolygonShape.prototype.TestPoint = function (xf, p) {
        var tVec;
        var tMat = xf.R;
        var tX = p.x - xf.position.x;
        var tY = p.y - xf.position.y;
        var pLocalX = (tX * tMat.col1.x + tY * tMat.col1.y);
        var pLocalY = (tX * tMat.col2.x + tY * tMat.col2.y);
        for (var i = 0; i < this.m_vertexCount; ++i) {
            tVec = this.m_vertices[i];
            tX = pLocalX - tVec.x;
            tY = pLocalY - tVec.y;
            tVec = this.m_normals[i];
            var dot = (tVec.x * tX + tVec.y * tY);
            if (dot > 0.0) {
                return false;
            }
        }
        return true;
    }
    b2PolygonShape.prototype.RayCast = function (output, input, transform) {
        var lower = 0.0;
        var upper = input.maxFraction;
        var tX = 0;
        var tY = 0;
        var tMat;
        var tVec;
        tX = input.p1.x - transform.position.x;
        tY = input.p1.y - transform.position.y;
        tMat = transform.R;
        var p1X = (tX * tMat.col1.x + tY * tMat.col1.y);
        var p1Y = (tX * tMat.col2.x + tY * tMat.col2.y);
        tX = input.p2.x - transform.position.x;
        tY = input.p2.y - transform.position.y;
        tMat = transform.R;
        var p2X = (tX * tMat.col1.x + tY * tMat.col1.y);
        var p2Y = (tX * tMat.col2.x + tY * tMat.col2.y);
        var dX = p2X - p1X;
        var dY = p2Y - p1Y;
        var index = parseInt((-1));
        for (var i = 0; i < this.m_vertexCount; ++i) {
            tVec = this.m_vertices[i];
            tX = tVec.x - p1X;
            tY = tVec.y - p1Y;
            tVec = this.m_normals[i];
            var numerator = (tVec.x * tX + tVec.y * tY);
            var denominator = (tVec.x * dX + tVec.y * dY);
            if (denominator == 0.0) {
                if (numerator < 0.0) {
                    return false;
                }
            }
            else {
                if (denominator < 0.0 && numerator < lower * denominator) {
                    lower = numerator / denominator;
                    index = i;
                }
                else if (denominator > 0.0 && numerator < upper * denominator) {
                    upper = numerator / denominator;
                }
            }
            if (upper < lower - Number.MIN_VALUE) {
                return false;
            }
        }
        if (index >= 0) {
            output.fraction = lower;
            tMat = transform.R;
            tVec = this.m_normals[index];
            output.normal.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            output.normal.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            return true;
        }
        return false;
    }
    b2PolygonShape.prototype.ComputeAABB = function (aabb, xf) {
        var tMat = xf.R;
        var tVec = this.m_vertices[0];
        var lowerX = xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        var lowerY = xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        var upperX = lowerX;
        var upperY = lowerY;
        for (var i = 1; i < this.m_vertexCount; ++i) {
            tVec = this.m_vertices[i];
            var vX = xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
            var vY = xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
            lowerX = lowerX < vX ? lowerX : vX;
            lowerY = lowerY < vY ? lowerY : vY;
            upperX = upperX > vX ? upperX : vX;
            upperY = upperY > vY ? upperY : vY;
        }
        aabb.lowerBound.x = lowerX - this.m_radius;
        aabb.lowerBound.y = lowerY - this.m_radius;
        aabb.upperBound.x = upperX + this.m_radius;
        aabb.upperBound.y = upperY + this.m_radius;
    }
    b2PolygonShape.prototype.ComputeMass = function (massData, density) {
        if (density === undefined) density = 0;
        if (this.m_vertexCount == 2) {
            massData.center.x = 0.5 * (this.m_vertices[0].x + this.m_vertices[1].x);
            massData.center.y = 0.5 * (this.m_vertices[0].y + this.m_vertices[1].y);
            massData.mass = 0.0;
            massData.I = 0.0;
            return;
        }
        var centerX = 0.0;
        var centerY = 0.0;
        var area = 0.0;
        var I = 0.0;
        var p1X = 0.0;
        var p1Y = 0.0;
        var k_inv3 = 1.0 / 3.0;
        for (var i = 0; i < this.m_vertexCount; ++i) {
            var p2 = this.m_vertices[i];
            var p3 = i + 1 < this.m_vertexCount ? this.m_vertices[parseInt(i + 1)] : this.m_vertices[0];
            var e1X = p2.x - p1X;
            var e1Y = p2.y - p1Y;
            var e2X = p3.x - p1X;
            var e2Y = p3.y - p1Y;
            var D = e1X * e2Y - e1Y * e2X;
            var triangleArea = 0.5 * D;area += triangleArea;
            centerX += triangleArea * k_inv3 * (p1X + p2.x + p3.x);
            centerY += triangleArea * k_inv3 * (p1Y + p2.y + p3.y);
            var px = p1X;
            var py = p1Y;
            var ex1 = e1X;
            var ey1 = e1Y;
            var ex2 = e2X;
            var ey2 = e2Y;
            var intx2 = k_inv3 * (0.25 * (ex1 * ex1 + ex2 * ex1 + ex2 * ex2) + (px * ex1 + px * ex2)) + 0.5 * px * px;
            var inty2 = k_inv3 * (0.25 * (ey1 * ey1 + ey2 * ey1 + ey2 * ey2) + (py * ey1 + py * ey2)) + 0.5 * py * py;I += D * (intx2 + inty2);
        }
        massData.mass = density * area;
        centerX *= 1.0 / area;
        centerY *= 1.0 / area;
        massData.center.Set(centerX, centerY);
        massData.I = density * I;
    }
    b2PolygonShape.prototype.ComputeSubmergedArea = function (normal, offset, xf, c) {
        if (offset === undefined) offset = 0;
        var normalL = b2Math.MulTMV(xf.R, normal);
        var offsetL = offset - b2Math.Dot(normal, xf.position);
        var depths = new Vector_a2j_Number();
        var diveCount = 0;
        var intoIndex = parseInt((-1));
        var outoIndex = parseInt((-1));
        var lastSubmerged = false;
        var i = 0;
        for (i = 0;
             i < this.m_vertexCount; ++i) {
            depths[i] = b2Math.Dot(normalL, this.m_vertices[i]) - offsetL;
            var isSubmerged = depths[i] < (-Number.MIN_VALUE);
            if (i > 0) {
                if (isSubmerged) {
                    if (!lastSubmerged) {
                        intoIndex = i - 1;
                        diveCount++;
                    }
                }
                else {
                    if (lastSubmerged) {
                        outoIndex = i - 1;
                        diveCount++;
                    }
                }
            }
            lastSubmerged = isSubmerged;
        }
        switch (diveCount) {
            case 0:
                if (lastSubmerged) {
                    var md = new b2MassData();
                    this.ComputeMass(md, 1);
                    c.SetV(b2Math.MulX(xf, md.center));
                    return md.mass;
                }
                else {
                    return 0;
                }
                break;
            case 1:
                if (intoIndex == (-1)) {
                    intoIndex = this.m_vertexCount - 1;
                }
                else {
                    outoIndex = this.m_vertexCount - 1;
                }
                break;
        }
        var intoIndex2 = parseInt((intoIndex + 1) % this.m_vertexCount);
        var outoIndex2 = parseInt((outoIndex + 1) % this.m_vertexCount);
        var intoLamdda = (0 - depths[intoIndex]) / (depths[intoIndex2] - depths[intoIndex]);
        var outoLamdda = (0 - depths[outoIndex]) / (depths[outoIndex2] - depths[outoIndex]);
        var intoVec = new b2Vec2(this.m_vertices[intoIndex].x * (1 - intoLamdda) + this.m_vertices[intoIndex2].x * intoLamdda, this.m_vertices[intoIndex].y * (1 - intoLamdda) + this.m_vertices[intoIndex2].y * intoLamdda);
        var outoVec = new b2Vec2(this.m_vertices[outoIndex].x * (1 - outoLamdda) + this.m_vertices[outoIndex2].x * outoLamdda, this.m_vertices[outoIndex].y * (1 - outoLamdda) + this.m_vertices[outoIndex2].y * outoLamdda);
        var area = 0;
        var center = new b2Vec2();
        var p2 = this.m_vertices[intoIndex2];
        var p3;
        i = intoIndex2;
        while (i != outoIndex2) {
            i = (i + 1) % this.m_vertexCount;
            if (i == outoIndex2) p3 = outoVec;
            else p3 = this.m_vertices[i];
            var triangleArea = 0.5 * ((p2.x - intoVec.x) * (p3.y - intoVec.y) - (p2.y - intoVec.y) * (p3.x - intoVec.x));
            area += triangleArea;
            center.x += triangleArea * (intoVec.x + p2.x + p3.x) / 3;
            center.y += triangleArea * (intoVec.y + p2.y + p3.y) / 3;
            p2 = p3;
        }
        center.Multiply(1 / area);
        c.SetV(b2Math.MulX(xf, center));
        return area;
    }
    b2PolygonShape.prototype.GetVertexCount = function () {
        return this.m_vertexCount;
    }
    b2PolygonShape.prototype.GetVertices = function () {
        return this.m_vertices;
    }
    b2PolygonShape.prototype.GetNormals = function () {
        return this.m_normals;
    }
    b2PolygonShape.prototype.GetSupport = function (d) {
        var bestIndex = 0;
        var bestValue = this.m_vertices[0].x * d.x + this.m_vertices[0].y * d.y;
        for (var i = 1; i < this.m_vertexCount; ++i) {
            var value = this.m_vertices[i].x * d.x + this.m_vertices[i].y * d.y;
            if (value > bestValue) {
                bestIndex = i;
                bestValue = value;
            }
        }
        return bestIndex;
    }
    b2PolygonShape.prototype.GetSupportVertex = function (d) {
        var bestIndex = 0;
        var bestValue = this.m_vertices[0].x * d.x + this.m_vertices[0].y * d.y;
        for (var i = 1; i < this.m_vertexCount; ++i) {
            var value = this.m_vertices[i].x * d.x + this.m_vertices[i].y * d.y;
            if (value > bestValue) {
                bestIndex = i;
                bestValue = value;
            }
        }
        return this.m_vertices[bestIndex];
    }
    b2PolygonShape.prototype.Validate = function () {
        return false;
    }
    b2PolygonShape.prototype.b2PolygonShape = function () {
        this.__super.b2Shape.call(this);
        this.m_type = b2Shape.e_polygonShape;
        this.m_centroid = new b2Vec2();
        this.m_vertices = new Vector();
        this.m_normals = new Vector();
    }
    b2PolygonShape.prototype.Reserve = function (count) {
        if (count === undefined) count = 0;
        for (var i = parseInt(this.m_vertices.length); i < count; i++) {
            this.m_vertices[i] = new b2Vec2();
            this.m_normals[i] = new b2Vec2();
        }
    }
    b2PolygonShape.ComputeCentroid = function (vs, count) {
        if (count === undefined) count = 0;
        var c = new b2Vec2();
        var area = 0.0;
        var p1X = 0.0;
        var p1Y = 0.0;
        var inv3 = 1.0 / 3.0;
        for (var i = 0; i < count; ++i) {
            var p2 = vs[i];
            var p3 = i + 1 < count ? vs[parseInt(i + 1)] : vs[0];
            var e1X = p2.x - p1X;
            var e1Y = p2.y - p1Y;
            var e2X = p3.x - p1X;
            var e2Y = p3.y - p1Y;
            var D = (e1X * e2Y - e1Y * e2X);
            var triangleArea = 0.5 * D;area += triangleArea;
            c.x += triangleArea * inv3 * (p1X + p2.x + p3.x);
            c.y += triangleArea * inv3 * (p1Y + p2.y + p3.y);
        }
        c.x *= 1.0 / area;
        c.y *= 1.0 / area;
        return c;
    }
    b2PolygonShape.ComputeOBB = function (obb, vs, count) {
        if (count === undefined) count = 0;
        var i = 0;
        var p = new Vector(count + 1);
        for (i = 0;
             i < count; ++i) {
            p[i] = vs[i];
        }
        p[count] = p[0];
        var minArea = Number.MAX_VALUE;
        for (i = 1;
             i <= count; ++i) {
            var root = p[parseInt(i - 1)];
            var uxX = p[i].x - root.x;
            var uxY = p[i].y - root.y;
            var length = Math.sqrt(uxX * uxX + uxY * uxY);
            uxX /= length;
            uxY /= length;
            var uyX = (-uxY);
            var uyY = uxX;
            var lowerX = Number.MAX_VALUE;
            var lowerY = Number.MAX_VALUE;
            var upperX = (-Number.MAX_VALUE);
            var upperY = (-Number.MAX_VALUE);
            for (var j = 0; j < count; ++j) {
                var dX = p[j].x - root.x;
                var dY = p[j].y - root.y;
                var rX = (uxX * dX + uxY * dY);
                var rY = (uyX * dX + uyY * dY);
                if (rX < lowerX) lowerX = rX;
                if (rY < lowerY) lowerY = rY;
                if (rX > upperX) upperX = rX;
                if (rY > upperY) upperY = rY;
            }
            var area = (upperX - lowerX) * (upperY - lowerY);
            if (area < 0.95 * minArea) {
                minArea = area;
                obb.R.col1.x = uxX;
                obb.R.col1.y = uxY;
                obb.R.col2.x = uyX;
                obb.R.col2.y = uyY;
                var centerX = 0.5 * (lowerX + upperX);
                var centerY = 0.5 * (lowerY + upperY);
                var tMat = obb.R;
                obb.center.x = root.x + (tMat.col1.x * centerX + tMat.col2.x * centerY);
                obb.center.y = root.y + (tMat.col1.y * centerX + tMat.col2.y * centerY);
                obb.extents.x = 0.5 * (upperX - lowerX);
                obb.extents.y = 0.5 * (upperY - lowerY);
            }
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.Shapes.b2PolygonShape.s_mat = new b2Mat22();
    });
    b2Shape.b2Shape = function () {};
    b2Shape.prototype.Copy = function () {
        return null;
    }
    b2Shape.prototype.Set = function (other) {
        this.m_radius = other.m_radius;
    }
    b2Shape.prototype.GetType = function () {
        return this.m_type;
    }
    b2Shape.prototype.TestPoint = function (xf, p) {
        return false;
    }
    b2Shape.prototype.RayCast = function (output, input, transform) {
        return false;
    }
    b2Shape.prototype.ComputeAABB = function (aabb, xf) {}
    b2Shape.prototype.ComputeMass = function (massData, density) {
        if (density === undefined) density = 0;
    }
    b2Shape.prototype.ComputeSubmergedArea = function (normal, offset, xf, c) {
        if (offset === undefined) offset = 0;
        return 0;
    }
    b2Shape.TestOverlap = function (shape1, transform1, shape2, transform2) {
        var input = new b2DistanceInput();
        input.proxyA = new b2DistanceProxy();
        input.proxyA.Set(shape1);
        input.proxyB = new b2DistanceProxy();
        input.proxyB.Set(shape2);
        input.transformA = transform1;
        input.transformB = transform2;
        input.useRadii = true;
        var simplexCache = new b2SimplexCache();
        simplexCache.count = 0;
        var output = new b2DistanceOutput();
        b2Distance.Distance(output, simplexCache, input);
        return output.distance < 10.0 * Number.MIN_VALUE;
    }
    b2Shape.prototype.b2Shape = function () {
        this.m_type = b2Shape.e_unknownShape;
        this.m_radius = b2Settings.b2_linearSlop;
    }
    Box2D.postDefs.push(function () {
        Box2D.Collision.Shapes.b2Shape.e_unknownShape = parseInt((-1));
        Box2D.Collision.Shapes.b2Shape.e_circleShape = 0;
        Box2D.Collision.Shapes.b2Shape.e_polygonShape = 1;
        Box2D.Collision.Shapes.b2Shape.e_edgeShape = 2;
        Box2D.Collision.Shapes.b2Shape.e_shapeTypeCount = 3;
        Box2D.Collision.Shapes.b2Shape.e_hitCollide = 1;
        Box2D.Collision.Shapes.b2Shape.e_missCollide = 0;
        Box2D.Collision.Shapes.b2Shape.e_startsInsideCollide = parseInt((-1));
    });
})();
(function () {
    var b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3;
    b2Color.b2Color = function () {
        this._r = 0;
        this._g = 0;
        this._b = 0;
    };
    b2Color.prototype.b2Color = function (rr, gg, bb) {
        if (rr === undefined) rr = 0;
        if (gg === undefined) gg = 0;
        if (bb === undefined) bb = 0;
        this._r = Box2D.parseUInt(255 * b2Math.Clamp(rr, 0.0, 1.0));
        this._g = Box2D.parseUInt(255 * b2Math.Clamp(gg, 0.0, 1.0));
        this._b = Box2D.parseUInt(255 * b2Math.Clamp(bb, 0.0, 1.0));
    }
    b2Color.prototype.Set = function (rr, gg, bb) {
        if (rr === undefined) rr = 0;
        if (gg === undefined) gg = 0;
        if (bb === undefined) bb = 0;
        this._r = Box2D.parseUInt(255 * b2Math.Clamp(rr, 0.0, 1.0));
        this._g = Box2D.parseUInt(255 * b2Math.Clamp(gg, 0.0, 1.0));
        this._b = Box2D.parseUInt(255 * b2Math.Clamp(bb, 0.0, 1.0));
    }
    Object.defineProperty(b2Color.prototype, 'r', {
        enumerable: false,
        configurable: true,
        set: function (rr) {
            if (rr === undefined) rr = 0;
            this._r = Box2D.parseUInt(255 * b2Math.Clamp(rr, 0.0, 1.0));
        }
    });
    Object.defineProperty(b2Color.prototype, 'g', {
        enumerable: false,
        configurable: true,
        set: function (gg) {
            if (gg === undefined) gg = 0;
            this._g = Box2D.parseUInt(255 * b2Math.Clamp(gg, 0.0, 1.0));
        }
    });
    Object.defineProperty(b2Color.prototype, 'b', {
        enumerable: false,
        configurable: true,
        set: function (bb) {
            if (bb === undefined) bb = 0;
            this._b = Box2D.parseUInt(255 * b2Math.Clamp(bb, 0.0, 1.0));
        }
    });
    Object.defineProperty(b2Color.prototype, 'color', {
        enumerable: false,
        configurable: true,
        get: function () {
            return (this._r << 16) | (this._g << 8) | (this._b);
        }
    });
    b2Settings.b2Settings = function () {};
    b2Settings.b2MixFriction = function (friction1, friction2) {
        if (friction1 === undefined) friction1 = 0;
        if (friction2 === undefined) friction2 = 0;
        return Math.sqrt(friction1 * friction2);
    }
    b2Settings.b2MixRestitution = function (restitution1, restitution2) {
        if (restitution1 === undefined) restitution1 = 0;
        if (restitution2 === undefined) restitution2 = 0;
        return restitution1 > restitution2 ? restitution1 : restitution2;
    }
    b2Settings.b2Assert = function (a) {
        if (!a) {
            throw "Assertion Failed";
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Common.b2Settings.VERSION = "2.1alpha";
        Box2D.Common.b2Settings.USHRT_MAX = 0x0000ffff;
        Box2D.Common.b2Settings.b2_pi = Math.PI;
        Box2D.Common.b2Settings.b2_maxManifoldPoints = 2;
        Box2D.Common.b2Settings.b2_aabbExtension = 0.1;
        Box2D.Common.b2Settings.b2_aabbMultiplier = 2.0;
        Box2D.Common.b2Settings.b2_polygonRadius = 2.0 * b2Settings.b2_linearSlop;
        Box2D.Common.b2Settings.b2_linearSlop = 0.005;
        Box2D.Common.b2Settings.b2_angularSlop = 2.0 / 180.0 * b2Settings.b2_pi;
        Box2D.Common.b2Settings.b2_toiSlop = 8.0 * b2Settings.b2_linearSlop;
        Box2D.Common.b2Settings.b2_maxTOIContactsPerIsland = 32;
        Box2D.Common.b2Settings.b2_maxTOIJointsPerIsland = 32;
        Box2D.Common.b2Settings.b2_velocityThreshold = 1.0;
        Box2D.Common.b2Settings.b2_maxLinearCorrection = 0.2;
        Box2D.Common.b2Settings.b2_maxAngularCorrection = 8.0 / 180.0 * b2Settings.b2_pi;
        Box2D.Common.b2Settings.b2_maxTranslation = 2.0;
        Box2D.Common.b2Settings.b2_maxTranslationSquared = b2Settings.b2_maxTranslation * b2Settings.b2_maxTranslation;
        Box2D.Common.b2Settings.b2_maxRotation = 0.5 * b2Settings.b2_pi;
        Box2D.Common.b2Settings.b2_maxRotationSquared = b2Settings.b2_maxRotation * b2Settings.b2_maxRotation;
        Box2D.Common.b2Settings.b2_contactBaumgarte = 0.2;
        Box2D.Common.b2Settings.b2_timeToSleep = 0.5;
        Box2D.Common.b2Settings.b2_linearSleepTolerance = 0.01;
        Box2D.Common.b2Settings.b2_angularSleepTolerance = 2.0 / 180.0 * b2Settings.b2_pi;
    });
})();
(function () {
    var b2AABB = Box2D.Collision.b2AABB,
        b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3;
    b2Mat22.b2Mat22 = function () {
        this.col1 = new b2Vec2();
        this.col2 = new b2Vec2();
    };
    b2Mat22.prototype.b2Mat22 = function () {
        this.SetIdentity();
    }
    b2Mat22.FromAngle = function (angle) {
        if (angle === undefined) angle = 0;
        var mat = new b2Mat22();
        mat.Set(angle);
        return mat;
    }
    b2Mat22.FromVV = function (c1, c2) {
        var mat = new b2Mat22();
        mat.SetVV(c1, c2);
        return mat;
    }
    b2Mat22.prototype.Set = function (angle) {
        if (angle === undefined) angle = 0;
        var c = Math.cos(angle);
        var s = Math.sin(angle);
        this.col1.x = c;
        this.col2.x = (-s);
        this.col1.y = s;
        this.col2.y = c;
    }
    b2Mat22.prototype.SetVV = function (c1, c2) {
        this.col1.SetV(c1);
        this.col2.SetV(c2);
    }
    b2Mat22.prototype.Copy = function () {
        var mat = new b2Mat22();
        mat.SetM(this);
        return mat;
    }
    b2Mat22.prototype.SetM = function (m) {
        this.col1.SetV(m.col1);
        this.col2.SetV(m.col2);
    }
    b2Mat22.prototype.AddM = function (m) {
        this.col1.x += m.col1.x;
        this.col1.y += m.col1.y;
        this.col2.x += m.col2.x;
        this.col2.y += m.col2.y;
    }
    b2Mat22.prototype.SetIdentity = function () {
        this.col1.x = 1.0;
        this.col2.x = 0.0;
        this.col1.y = 0.0;
        this.col2.y = 1.0;
    }
    b2Mat22.prototype.SetZero = function () {
        this.col1.x = 0.0;
        this.col2.x = 0.0;
        this.col1.y = 0.0;
        this.col2.y = 0.0;
    }
    b2Mat22.prototype.GetAngle = function () {
        return Math.atan2(this.col1.y, this.col1.x);
    }
    b2Mat22.prototype.GetInverse = function (out) {
        var a = this.col1.x;
        var b = this.col2.x;
        var c = this.col1.y;
        var d = this.col2.y;
        var det = a * d - b * c;
        if (det != 0.0) {
            det = 1.0 / det;
        }
        out.col1.x = det * d;
        out.col2.x = (-det * b);
        out.col1.y = (-det * c);
        out.col2.y = det * a;
        return out;
    }
    b2Mat22.prototype.Solve = function (out, bX, bY) {
        if (bX === undefined) bX = 0;
        if (bY === undefined) bY = 0;
        var a11 = this.col1.x;
        var a12 = this.col2.x;
        var a21 = this.col1.y;
        var a22 = this.col2.y;
        var det = a11 * a22 - a12 * a21;
        if (det != 0.0) {
            det = 1.0 / det;
        }
        out.x = det * (a22 * bX - a12 * bY);
        out.y = det * (a11 * bY - a21 * bX);
        return out;
    }
    b2Mat22.prototype.Abs = function () {
        this.col1.Abs();
        this.col2.Abs();
    }
    b2Mat33.b2Mat33 = function () {
        this.col1 = new b2Vec3();
        this.col2 = new b2Vec3();
        this.col3 = new b2Vec3();
    };
    b2Mat33.prototype.b2Mat33 = function (c1, c2, c3) {
        if (c1 === undefined) c1 = null;
        if (c2 === undefined) c2 = null;
        if (c3 === undefined) c3 = null;
        if (!c1 && !c2 && !c3) {
            this.col1.SetZero();
            this.col2.SetZero();
            this.col3.SetZero();
        }
        else {
            this.col1.SetV(c1);
            this.col2.SetV(c2);
            this.col3.SetV(c3);
        }
    }
    b2Mat33.prototype.SetVVV = function (c1, c2, c3) {
        this.col1.SetV(c1);
        this.col2.SetV(c2);
        this.col3.SetV(c3);
    }
    b2Mat33.prototype.Copy = function () {
        return new b2Mat33(this.col1, this.col2, this.col3);
    }
    b2Mat33.prototype.SetM = function (m) {
        this.col1.SetV(m.col1);
        this.col2.SetV(m.col2);
        this.col3.SetV(m.col3);
    }
    b2Mat33.prototype.AddM = function (m) {
        this.col1.x += m.col1.x;
        this.col1.y += m.col1.y;
        this.col1.z += m.col1.z;
        this.col2.x += m.col2.x;
        this.col2.y += m.col2.y;
        this.col2.z += m.col2.z;
        this.col3.x += m.col3.x;
        this.col3.y += m.col3.y;
        this.col3.z += m.col3.z;
    }
    b2Mat33.prototype.SetIdentity = function () {
        this.col1.x = 1.0;
        this.col2.x = 0.0;
        this.col3.x = 0.0;
        this.col1.y = 0.0;
        this.col2.y = 1.0;
        this.col3.y = 0.0;
        this.col1.z = 0.0;
        this.col2.z = 0.0;
        this.col3.z = 1.0;
    }
    b2Mat33.prototype.SetZero = function () {
        this.col1.x = 0.0;
        this.col2.x = 0.0;
        this.col3.x = 0.0;
        this.col1.y = 0.0;
        this.col2.y = 0.0;
        this.col3.y = 0.0;
        this.col1.z = 0.0;
        this.col2.z = 0.0;
        this.col3.z = 0.0;
    }
    b2Mat33.prototype.Solve22 = function (out, bX, bY) {
        if (bX === undefined) bX = 0;
        if (bY === undefined) bY = 0;
        var a11 = this.col1.x;
        var a12 = this.col2.x;
        var a21 = this.col1.y;
        var a22 = this.col2.y;
        var det = a11 * a22 - a12 * a21;
        if (det != 0.0) {
            det = 1.0 / det;
        }
        out.x = det * (a22 * bX - a12 * bY);
        out.y = det * (a11 * bY - a21 * bX);
        return out;
    }
    b2Mat33.prototype.Solve33 = function (out, bX, bY, bZ) {
        if (bX === undefined) bX = 0;
        if (bY === undefined) bY = 0;
        if (bZ === undefined) bZ = 0;
        var a11 = this.col1.x;
        var a21 = this.col1.y;
        var a31 = this.col1.z;
        var a12 = this.col2.x;
        var a22 = this.col2.y;
        var a32 = this.col2.z;
        var a13 = this.col3.x;
        var a23 = this.col3.y;
        var a33 = this.col3.z;
        var det = a11 * (a22 * a33 - a32 * a23) + a21 * (a32 * a13 - a12 * a33) + a31 * (a12 * a23 - a22 * a13);
        if (det != 0.0) {
            det = 1.0 / det;
        }
        out.x = det * (bX * (a22 * a33 - a32 * a23) + bY * (a32 * a13 - a12 * a33) + bZ * (a12 * a23 - a22 * a13));
        out.y = det * (a11 * (bY * a33 - bZ * a23) + a21 * (bZ * a13 - bX * a33) + a31 * (bX * a23 - bY * a13));
        out.z = det * (a11 * (a22 * bZ - a32 * bY) + a21 * (a32 * bX - a12 * bZ) + a31 * (a12 * bY - a22 * bX));
        return out;
    }
    b2Math.b2Math = function () {};
    b2Math.IsValid = function (x) {
        if (x === undefined) x = 0;
        return isFinite(x);
    }
    b2Math.Dot = function (a, b) {
        return a.x * b.x + a.y * b.y;
    }
    b2Math.CrossVV = function (a, b) {
        return a.x * b.y - a.y * b.x;
    }
    b2Math.CrossVF = function (a, s) {
        if (s === undefined) s = 0;
        var v = new b2Vec2(s * a.y, (-s * a.x));
        return v;
    }
    b2Math.CrossFV = function (s, a) {
        if (s === undefined) s = 0;
        var v = new b2Vec2((-s * a.y), s * a.x);
        return v;
    }
    b2Math.MulMV = function (A, v) {
        var u = new b2Vec2(A.col1.x * v.x + A.col2.x * v.y, A.col1.y * v.x + A.col2.y * v.y);
        return u;
    }
    b2Math.MulTMV = function (A, v) {
        var u = new b2Vec2(b2Math.Dot(v, A.col1), b2Math.Dot(v, A.col2));
        return u;
    }
    b2Math.MulX = function (T, v) {
        var a = b2Math.MulMV(T.R, v);
        a.x += T.position.x;
        a.y += T.position.y;
        return a;
    }
    b2Math.MulXT = function (T, v) {
        var a = b2Math.SubtractVV(v, T.position);
        var tX = (a.x * T.R.col1.x + a.y * T.R.col1.y);
        a.y = (a.x * T.R.col2.x + a.y * T.R.col2.y);
        a.x = tX;
        return a;
    }
    b2Math.AddVV = function (a, b) {
        var v = new b2Vec2(a.x + b.x, a.y + b.y);
        return v;
    }
    b2Math.SubtractVV = function (a, b) {
        var v = new b2Vec2(a.x - b.x, a.y - b.y);
        return v;
    }
    b2Math.Distance = function (a, b) {
        var cX = a.x - b.x;
        var cY = a.y - b.y;
        return Math.sqrt(cX * cX + cY * cY);
    }
    b2Math.DistanceSquared = function (a, b) {
        var cX = a.x - b.x;
        var cY = a.y - b.y;
        return (cX * cX + cY * cY);
    }
    b2Math.MulFV = function (s, a) {
        if (s === undefined) s = 0;
        var v = new b2Vec2(s * a.x, s * a.y);
        return v;
    }
    b2Math.AddMM = function (A, B) {
        var C = b2Mat22.FromVV(b2Math.AddVV(A.col1, B.col1), b2Math.AddVV(A.col2, B.col2));
        return C;
    }
    b2Math.MulMM = function (A, B) {
        var C = b2Mat22.FromVV(b2Math.MulMV(A, B.col1), b2Math.MulMV(A, B.col2));
        return C;
    }
    b2Math.MulTMM = function (A, B) {
        var c1 = new b2Vec2(b2Math.Dot(A.col1, B.col1), b2Math.Dot(A.col2, B.col1));
        var c2 = new b2Vec2(b2Math.Dot(A.col1, B.col2), b2Math.Dot(A.col2, B.col2));
        var C = b2Mat22.FromVV(c1, c2);
        return C;
    }
    b2Math.Abs = function (a) {
        if (a === undefined) a = 0;
        return a > 0.0 ? a : (-a);
    }
    b2Math.AbsV = function (a) {
        var b = new b2Vec2(b2Math.Abs(a.x), b2Math.Abs(a.y));
        return b;
    }
    b2Math.AbsM = function (A) {
        var B = b2Mat22.FromVV(b2Math.AbsV(A.col1), b2Math.AbsV(A.col2));
        return B;
    }
    b2Math.Min = function (a, b) {
        if (a === undefined) a = 0;
        if (b === undefined) b = 0;
        return a < b ? a : b;
    }
    b2Math.MinV = function (a, b) {
        var c = new b2Vec2(b2Math.Min(a.x, b.x), b2Math.Min(a.y, b.y));
        return c;
    }
    b2Math.Max = function (a, b) {
        if (a === undefined) a = 0;
        if (b === undefined) b = 0;
        return a > b ? a : b;
    }
    b2Math.MaxV = function (a, b) {
        var c = new b2Vec2(b2Math.Max(a.x, b.x), b2Math.Max(a.y, b.y));
        return c;
    }
    b2Math.Clamp = function (a, low, high) {
        if (a === undefined) a = 0;
        if (low === undefined) low = 0;
        if (high === undefined) high = 0;
        return a < low ? low : a > high ? high : a;
    }
    b2Math.ClampV = function (a, low, high) {
        return b2Math.MaxV(low, b2Math.MinV(a, high));
    }
    b2Math.Swap = function (a, b) {
        var tmp = a[0];
        a[0] = b[0];
        b[0] = tmp;
    }
    b2Math.Random = function () {
        return Math.random() * 2 - 1;
    }
    b2Math.RandomRange = function (lo, hi) {
        if (lo === undefined) lo = 0;
        if (hi === undefined) hi = 0;
        var r = Math.random();
        r = (hi - lo) * r + lo;
        return r;
    }
    b2Math.NextPowerOfTwo = function (x) {
        if (x === undefined) x = 0;
        x |= (x >> 1) & 0x7FFFFFFF;
        x |= (x >> 2) & 0x3FFFFFFF;
        x |= (x >> 4) & 0x0FFFFFFF;
        x |= (x >> 8) & 0x00FFFFFF;
        x |= (x >> 16) & 0x0000FFFF;
        return x + 1;
    }
    b2Math.IsPowerOfTwo = function (x) {
        if (x === undefined) x = 0;
        var result = x > 0 && (x & (x - 1)) == 0;
        return result;
    }
    Box2D.postDefs.push(function () {
        Box2D.Common.Math.b2Math.b2Vec2_zero = new b2Vec2(0.0, 0.0);
        Box2D.Common.Math.b2Math.b2Mat22_identity = b2Mat22.FromVV(new b2Vec2(1.0, 0.0), new b2Vec2(0.0, 1.0));
        Box2D.Common.Math.b2Math.b2Transform_identity = new b2Transform(b2Math.b2Vec2_zero, b2Math.b2Mat22_identity);
    });
    b2Sweep.b2Sweep = function () {
        this.localCenter = new b2Vec2();
        this.c0 = new b2Vec2;
        this.c = new b2Vec2();
    };
    b2Sweep.prototype.Set = function (other) {
        this.localCenter.SetV(other.localCenter);
        this.c0.SetV(other.c0);
        this.c.SetV(other.c);
        this.a0 = other.a0;
        this.a = other.a;
        this.t0 = other.t0;
    }
    b2Sweep.prototype.Copy = function () {
        var copy = new b2Sweep();
        copy.localCenter.SetV(this.localCenter);
        copy.c0.SetV(this.c0);
        copy.c.SetV(this.c);
        copy.a0 = this.a0;
        copy.a = this.a;
        copy.t0 = this.t0;
        return copy;
    }
    b2Sweep.prototype.GetTransform = function (xf, alpha) {
        if (alpha === undefined) alpha = 0;
        xf.position.x = (1.0 - alpha) * this.c0.x + alpha * this.c.x;
        xf.position.y = (1.0 - alpha) * this.c0.y + alpha * this.c.y;
        var angle = (1.0 - alpha) * this.a0 + alpha * this.a;
        xf.R.Set(angle);
        var tMat = xf.R;
        xf.position.x -= (tMat.col1.x * this.localCenter.x + tMat.col2.x * this.localCenter.y);
        xf.position.y -= (tMat.col1.y * this.localCenter.x + tMat.col2.y * this.localCenter.y);
    }
    b2Sweep.prototype.Advance = function (t) {
        if (t === undefined) t = 0;
        if (this.t0 < t && 1.0 - this.t0 > Number.MIN_VALUE) {
            var alpha = (t - this.t0) / (1.0 - this.t0);
            this.c0.x = (1.0 - alpha) * this.c0.x + alpha * this.c.x;
            this.c0.y = (1.0 - alpha) * this.c0.y + alpha * this.c.y;
            this.a0 = (1.0 - alpha) * this.a0 + alpha * this.a;
            this.t0 = t;
        }
    }
    b2Transform.b2Transform = function () {
        this.position = new b2Vec2;
        this.R = new b2Mat22();
    };
    b2Transform.prototype.b2Transform = function (pos, r) {
        if (pos === undefined) pos = null;
        if (r === undefined) r = null;
        if (pos) {
            this.position.SetV(pos);
            this.R.SetM(r);
        }
    }
    b2Transform.prototype.Initialize = function (pos, r) {
        this.position.SetV(pos);
        this.R.SetM(r);
    }
    b2Transform.prototype.SetIdentity = function () {
        this.position.SetZero();
        this.R.SetIdentity();
    }
    b2Transform.prototype.Set = function (x) {
        this.position.SetV(x.position);
        this.R.SetM(x.R);
    }
    b2Transform.prototype.GetAngle = function () {
        return Math.atan2(this.R.col1.y, this.R.col1.x);
    }
    b2Vec2.b2Vec2 = function () {};
    b2Vec2.prototype.b2Vec2 = function (x_, y_) {
        if (x_ === undefined) x_ = 0;
        if (y_ === undefined) y_ = 0;
        this.x = x_;
        this.y = y_;
    }
    b2Vec2.prototype.SetZero = function () {
        this.x = 0.0;
        this.y = 0.0;
    }
    b2Vec2.prototype.Set = function (x_, y_) {
        if (x_ === undefined) x_ = 0;
        if (y_ === undefined) y_ = 0;
        this.x = x_;
        this.y = y_;
    }
    b2Vec2.prototype.SetV = function (v) {
        this.x = v.x;
        this.y = v.y;
    }
    b2Vec2.prototype.GetNegative = function () {
        return new b2Vec2((-this.x), (-this.y));
    }
    b2Vec2.prototype.NegativeSelf = function () {
        this.x = (-this.x);
        this.y = (-this.y);
    }
    b2Vec2.Make = function (x_, y_) {
        if (x_ === undefined) x_ = 0;
        if (y_ === undefined) y_ = 0;
        return new b2Vec2(x_, y_);
    }
    b2Vec2.prototype.Copy = function () {
        return new b2Vec2(this.x, this.y);
    }
    b2Vec2.prototype.Add = function (v) {
        this.x += v.x;
        this.y += v.y;
    }
    b2Vec2.prototype.Subtract = function (v) {
        this.x -= v.x;
        this.y -= v.y;
    }
    b2Vec2.prototype.Multiply = function (a) {
        if (a === undefined) a = 0;
        this.x *= a;
        this.y *= a;
    }
    b2Vec2.prototype.MulM = function (A) {
        var tX = this.x;
        this.x = A.col1.x * tX + A.col2.x * this.y;
        this.y = A.col1.y * tX + A.col2.y * this.y;
    }
    b2Vec2.prototype.MulTM = function (A) {
        var tX = b2Math.Dot(this, A.col1);
        this.y = b2Math.Dot(this, A.col2);
        this.x = tX;
    }
    b2Vec2.prototype.CrossVF = function (s) {
        if (s === undefined) s = 0;
        var tX = this.x;
        this.x = s * this.y;
        this.y = (-s * tX);
    }
    b2Vec2.prototype.CrossFV = function (s) {
        if (s === undefined) s = 0;
        var tX = this.x;
        this.x = (-s * this.y);
        this.y = s * tX;
    }
    b2Vec2.prototype.MinV = function (b) {
        this.x = this.x < b.x ? this.x : b.x;
        this.y = this.y < b.y ? this.y : b.y;
    }
    b2Vec2.prototype.MaxV = function (b) {
        this.x = this.x > b.x ? this.x : b.x;
        this.y = this.y > b.y ? this.y : b.y;
    }
    b2Vec2.prototype.Abs = function () {
        if (this.x < 0) this.x = (-this.x);
        if (this.y < 0) this.y = (-this.y);
    }
    b2Vec2.prototype.Length = function () {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }
    b2Vec2.prototype.LengthSquared = function () {
        return (this.x * this.x + this.y * this.y);
    }
    b2Vec2.prototype.Normalize = function () {
        var length = Math.sqrt(this.x * this.x + this.y * this.y);
        if (length < Number.MIN_VALUE) {
            return 0.0;
        }
        var invLength = 1.0 / length;
        this.x *= invLength;
        this.y *= invLength;
        return length;
    }
    b2Vec2.prototype.IsValid = function () {
        return b2Math.IsValid(this.x) && b2Math.IsValid(this.y);
    }
    b2Vec3.b2Vec3 = function () {};
    b2Vec3.prototype.b2Vec3 = function (x, y, z) {
        if (x === undefined) x = 0;
        if (y === undefined) y = 0;
        if (z === undefined) z = 0;
        this.x = x;
        this.y = y;
        this.z = z;
    }
    b2Vec3.prototype.SetZero = function () {
        this.x = this.y = this.z = 0.0;
    }
    b2Vec3.prototype.Set = function (x, y, z) {
        if (x === undefined) x = 0;
        if (y === undefined) y = 0;
        if (z === undefined) z = 0;
        this.x = x;
        this.y = y;
        this.z = z;
    }
    b2Vec3.prototype.SetV = function (v) {
        this.x = v.x;
        this.y = v.y;
        this.z = v.z;
    }
    b2Vec3.prototype.GetNegative = function () {
        return new b2Vec3((-this.x), (-this.y), (-this.z));
    }
    b2Vec3.prototype.NegativeSelf = function () {
        this.x = (-this.x);
        this.y = (-this.y);
        this.z = (-this.z);
    }
    b2Vec3.prototype.Copy = function () {
        return new b2Vec3(this.x, this.y, this.z);
    }
    b2Vec3.prototype.Add = function (v) {
        this.x += v.x;
        this.y += v.y;
        this.z += v.z;
    }
    b2Vec3.prototype.Subtract = function (v) {
        this.x -= v.x;
        this.y -= v.y;
        this.z -= v.z;
    }
    b2Vec3.prototype.Multiply = function (a) {
        if (a === undefined) a = 0;
        this.x *= a;
        this.y *= a;
        this.z *= a;
    }
})();
(function () {
    var b2ControllerEdge = Box2D.Dynamics.Controllers.b2ControllerEdge,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3,
        b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2AABB = Box2D.Collision.b2AABB,
        b2Bound = Box2D.Collision.b2Bound,
        b2BoundValues = Box2D.Collision.b2BoundValues,
        b2Collision = Box2D.Collision.b2Collision,
        b2ContactID = Box2D.Collision.b2ContactID,
        b2ContactPoint = Box2D.Collision.b2ContactPoint,
        b2Distance = Box2D.Collision.b2Distance,
        b2DistanceInput = Box2D.Collision.b2DistanceInput,
        b2DistanceOutput = Box2D.Collision.b2DistanceOutput,
        b2DistanceProxy = Box2D.Collision.b2DistanceProxy,
        b2DynamicTree = Box2D.Collision.b2DynamicTree,
        b2DynamicTreeBroadPhase = Box2D.Collision.b2DynamicTreeBroadPhase,
        b2DynamicTreeNode = Box2D.Collision.b2DynamicTreeNode,
        b2DynamicTreePair = Box2D.Collision.b2DynamicTreePair,
        b2Manifold = Box2D.Collision.b2Manifold,
        b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint,
        b2Point = Box2D.Collision.b2Point,
        b2RayCastInput = Box2D.Collision.b2RayCastInput,
        b2RayCastOutput = Box2D.Collision.b2RayCastOutput,
        b2Segment = Box2D.Collision.b2Segment,
        b2SeparationFunction = Box2D.Collision.b2SeparationFunction,
        b2Simplex = Box2D.Collision.b2Simplex,
        b2SimplexCache = Box2D.Collision.b2SimplexCache,
        b2SimplexVertex = Box2D.Collision.b2SimplexVertex,
        b2TimeOfImpact = Box2D.Collision.b2TimeOfImpact,
        b2TOIInput = Box2D.Collision.b2TOIInput,
        b2WorldManifold = Box2D.Collision.b2WorldManifold,
        ClipVertex = Box2D.Collision.ClipVertex,
        Features = Box2D.Collision.Features,
        IBroadPhase = Box2D.Collision.IBroadPhase,
        b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
        b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
        b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
        b2MassData = Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
        b2Shape = Box2D.Collision.Shapes.b2Shape,
        b2Body = Box2D.Dynamics.b2Body,
        b2BodyDef = Box2D.Dynamics.b2BodyDef,
        b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
        b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
        b2ContactListener = Box2D.Dynamics.b2ContactListener,
        b2ContactManager = Box2D.Dynamics.b2ContactManager,
        b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
        b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
        b2FilterData = Box2D.Dynamics.b2FilterData,
        b2Fixture = Box2D.Dynamics.b2Fixture,
        b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
        b2Island = Box2D.Dynamics.b2Island,
        b2TimeStep = Box2D.Dynamics.b2TimeStep,
        b2World = Box2D.Dynamics.b2World,
        b2CircleContact = Box2D.Dynamics.Contacts.b2CircleContact,
        b2Contact = Box2D.Dynamics.Contacts.b2Contact,
        b2ContactConstraint = Box2D.Dynamics.Contacts.b2ContactConstraint,
        b2ContactConstraintPoint = Box2D.Dynamics.Contacts.b2ContactConstraintPoint,
        b2ContactEdge = Box2D.Dynamics.Contacts.b2ContactEdge,
        b2ContactFactory = Box2D.Dynamics.Contacts.b2ContactFactory,
        b2ContactRegister = Box2D.Dynamics.Contacts.b2ContactRegister,
        b2ContactResult = Box2D.Dynamics.Contacts.b2ContactResult,
        b2ContactSolver = Box2D.Dynamics.Contacts.b2ContactSolver,
        b2EdgeAndCircleContact = Box2D.Dynamics.Contacts.b2EdgeAndCircleContact,
        b2NullContact = Box2D.Dynamics.Contacts.b2NullContact,
        b2PolyAndCircleContact = Box2D.Dynamics.Contacts.b2PolyAndCircleContact,
        b2PolyAndEdgeContact = Box2D.Dynamics.Contacts.b2PolyAndEdgeContact,
        b2PolygonContact = Box2D.Dynamics.Contacts.b2PolygonContact,
        b2PositionSolverManifold = Box2D.Dynamics.Contacts.b2PositionSolverManifold,
        b2Controller = Box2D.Dynamics.Controllers.b2Controller,
        b2DistanceJoint = Box2D.Dynamics.Joints.b2DistanceJoint,
        b2DistanceJointDef = Box2D.Dynamics.Joints.b2DistanceJointDef,
        b2FrictionJoint = Box2D.Dynamics.Joints.b2FrictionJoint,
        b2FrictionJointDef = Box2D.Dynamics.Joints.b2FrictionJointDef,
        b2GearJoint = Box2D.Dynamics.Joints.b2GearJoint,
        b2GearJointDef = Box2D.Dynamics.Joints.b2GearJointDef,
        b2Jacobian = Box2D.Dynamics.Joints.b2Jacobian,
        b2Joint = Box2D.Dynamics.Joints.b2Joint,
        b2JointDef = Box2D.Dynamics.Joints.b2JointDef,
        b2JointEdge = Box2D.Dynamics.Joints.b2JointEdge,
        b2LineJoint = Box2D.Dynamics.Joints.b2LineJoint,
        b2LineJointDef = Box2D.Dynamics.Joints.b2LineJointDef,
        b2MouseJoint = Box2D.Dynamics.Joints.b2MouseJoint,
        b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef,
        b2PrismaticJoint = Box2D.Dynamics.Joints.b2PrismaticJoint,
        b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef,
        b2PulleyJoint = Box2D.Dynamics.Joints.b2PulleyJoint,
        b2PulleyJointDef = Box2D.Dynamics.Joints.b2PulleyJointDef,
        b2RevoluteJoint = Box2D.Dynamics.Joints.b2RevoluteJoint,
        b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef,
        b2WeldJoint = Box2D.Dynamics.Joints.b2WeldJoint,
        b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef;
    b2Body.b2Body = function () {
        this.m_xf = new b2Transform();
        this.m_sweep = new b2Sweep();
        this.m_linearVelocity = new b2Vec2();
        this.m_force = new b2Vec2();
    };
    b2Body.prototype.connectEdges = function (s1, s2, angle1) {
        if (angle1 === undefined) angle1 = 0;
        var angle2 = Math.atan2(s2.GetDirectionVector().y, s2.GetDirectionVector().x);
        var coreOffset = Math.tan((angle2 - angle1) * 0.5);
        var core = b2Math.MulFV(coreOffset, s2.GetDirectionVector());
        core = b2Math.SubtractVV(core, s2.GetNormalVector());
        core = b2Math.MulFV(b2Settings.b2_toiSlop, core);
        core = b2Math.AddVV(core, s2.GetVertex1());
        var cornerDir = b2Math.AddVV(s1.GetDirectionVector(), s2.GetDirectionVector());
        cornerDir.Normalize();
        var convex = b2Math.Dot(s1.GetDirectionVector(), s2.GetNormalVector()) > 0.0;
        s1.SetNextEdge(s2, core, cornerDir, convex);
        s2.SetPrevEdge(s1, core, cornerDir, convex);
        return angle2;
    }
    b2Body.prototype.CreateFixture = function (def) {
        if (this.m_world.IsLocked() == true) {
            return null;
        }
        var fixture = new b2Fixture();
        fixture.Create(this, this.m_xf, def);
        if (this.m_flags & b2Body.e_activeFlag) {
            var broadPhase = this.m_world.m_contactManager.m_broadPhase;
            fixture.CreateProxy(broadPhase, this.m_xf);
        }
        fixture.m_next = this.m_fixtureList;
        this.m_fixtureList = fixture;
        ++this.m_fixtureCount;
        fixture.m_body = this;
        if (fixture.m_density > 0.0) {
            this.ResetMassData();
        }
        this.m_world.m_flags |= b2World.e_newFixture;
        return fixture;
    }
    b2Body.prototype.CreateFixture2 = function (shape, density) {
        if (density === undefined) density = 0.0;
        var def = new b2FixtureDef();
        def.shape = shape;
        def.density = density;
        return this.CreateFixture(def);
    }
    b2Body.prototype.DestroyFixture = function (fixture) {
        if (this.m_world.IsLocked() == true) {
            return;
        }
        var node = this.m_fixtureList;
        var ppF = null;
        var found = false;
        while (node != null) {
            if (node == fixture) {
                if (ppF) ppF.m_next = fixture.m_next;
                else this.m_fixtureList = fixture.m_next;
                found = true;
                break;
            }
            ppF = node;
            node = node.m_next;
        }
        var edge = this.m_contactList;
        while (edge) {
            var c = edge.contact;
            edge = edge.next;
            var fixtureA = c.GetFixtureA();
            var fixtureB = c.GetFixtureB();
            if (fixture == fixtureA || fixture == fixtureB) {
                this.m_world.m_contactManager.Destroy(c);
            }
        }
        if (this.m_flags & b2Body.e_activeFlag) {
            var broadPhase = this.m_world.m_contactManager.m_broadPhase;
            fixture.DestroyProxy(broadPhase);
        }
        else {}
        fixture.Destroy();
        fixture.m_body = null;
        fixture.m_next = null;
        --this.m_fixtureCount;
        this.ResetMassData();
    }
    b2Body.prototype.SetPositionAndAngle = function (position, angle) {
        if (angle === undefined) angle = 0;
        var f;
        if (this.m_world.IsLocked() == true) {
            return;
        }
        this.m_xf.R.Set(angle);
        this.m_xf.position.SetV(position);
        var tMat = this.m_xf.R;
        var tVec = this.m_sweep.localCenter;
        this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        this.m_sweep.c.x += this.m_xf.position.x;
        this.m_sweep.c.y += this.m_xf.position.y;
        this.m_sweep.c0.SetV(this.m_sweep.c);
        this.m_sweep.a0 = this.m_sweep.a = angle;
        var broadPhase = this.m_world.m_contactManager.m_broadPhase;
        for (f = this.m_fixtureList;
             f; f = f.m_next) {
            f.Synchronize(broadPhase, this.m_xf, this.m_xf);
        }
        this.m_world.m_contactManager.FindNewContacts();
    }
    b2Body.prototype.SetTransform = function (xf) {
        this.SetPositionAndAngle(xf.position, xf.GetAngle());
    }
    b2Body.prototype.GetTransform = function () {
        return this.m_xf;
    }
    b2Body.prototype.GetPosition = function () {
        return this.m_xf.position;
    }
    b2Body.prototype.SetPosition = function (position) {
        this.SetPositionAndAngle(position, this.GetAngle());
    }
    b2Body.prototype.GetAngle = function () {
        return this.m_sweep.a;
    }
    b2Body.prototype.SetAngle = function (angle) {
        if (angle === undefined) angle = 0;
        this.SetPositionAndAngle(this.GetPosition(), angle);
    }
    b2Body.prototype.GetWorldCenter = function () {
        return this.m_sweep.c;
    }
    b2Body.prototype.GetLocalCenter = function () {
        return this.m_sweep.localCenter;
    }
    b2Body.prototype.SetLinearVelocity = function (v) {
        if (this.m_type == b2Body.b2_staticBody) {
            return;
        }
        this.m_linearVelocity.SetV(v);
    }
    b2Body.prototype.GetLinearVelocity = function () {
        return this.m_linearVelocity;
    }
    b2Body.prototype.SetAngularVelocity = function (omega) {
        if (omega === undefined) omega = 0;
        if (this.m_type == b2Body.b2_staticBody) {
            return;
        }
        this.m_angularVelocity = omega;
    }
    b2Body.prototype.GetAngularVelocity = function () {
        return this.m_angularVelocity;
    }
    b2Body.prototype.GetDefinition = function () {
        var bd = new b2BodyDef();
        bd.type = this.GetType();
        bd.allowSleep = (this.m_flags & b2Body.e_allowSleepFlag) == b2Body.e_allowSleepFlag;
        bd.angle = this.GetAngle();
        bd.angularDamping = this.m_angularDamping;
        bd.angularVelocity = this.m_angularVelocity;
        bd.fixedRotation = (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag;
        bd.bullet = (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag;
        bd.awake = (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag;
        bd.linearDamping = this.m_linearDamping;
        bd.linearVelocity.SetV(this.GetLinearVelocity());
        bd.position = this.GetPosition();
        bd.userData = this.GetUserData();
        return bd;
    }
    b2Body.prototype.ApplyForce = function (force, point) {
        if (this.m_type != b2Body.b2_dynamicBody) {
            return;
        }
        if (this.IsAwake() == false) {
            this.SetAwake(true);
        }
        this.m_force.x += force.x;
        this.m_force.y += force.y;
        this.m_torque += ((point.x - this.m_sweep.c.x) * force.y - (point.y - this.m_sweep.c.y) * force.x);
    }
    b2Body.prototype.ApplyTorque = function (torque) {
        if (torque === undefined) torque = 0;
        if (this.m_type != b2Body.b2_dynamicBody) {
            return;
        }
        if (this.IsAwake() == false) {
            this.SetAwake(true);
        }
        this.m_torque += torque;
    }
    b2Body.prototype.ApplyImpulse = function (impulse, point) {
        if (this.m_type != b2Body.b2_dynamicBody) {
            return;
        }
        if (this.IsAwake() == false) {
            this.SetAwake(true);
        }
        this.m_linearVelocity.x += this.m_invMass * impulse.x;
        this.m_linearVelocity.y += this.m_invMass * impulse.y;
        this.m_angularVelocity += this.m_invI * ((point.x - this.m_sweep.c.x) * impulse.y - (point.y - this.m_sweep.c.y) * impulse.x);
    }
    b2Body.prototype.Split = function (callback) {
        var linearVelocity = this.GetLinearVelocity().Copy();
        var angularVelocity = this.GetAngularVelocity();
        var center = this.GetWorldCenter();
        var body1 = this;
        var body2 = this.m_world.CreateBody(this.GetDefinition());
        var prev;
        for (var f = body1.m_fixtureList; f;) {
            if (callback(f)) {
                var next = f.m_next;
                if (prev) {
                    prev.m_next = next;
                }
                else {
                    body1.m_fixtureList = next;
                }
                body1.m_fixtureCount--;
                f.m_next = body2.m_fixtureList;
                body2.m_fixtureList = f;
                body2.m_fixtureCount++;
                f.m_body = body2;
                f = next;
            }
            else {
                prev = f;
                f = f.m_next;
            }
        }
        body1.ResetMassData();
        body2.ResetMassData();
        var center1 = body1.GetWorldCenter();
        var center2 = body2.GetWorldCenter();
        var velocity1 = b2Math.AddVV(linearVelocity, b2Math.CrossFV(angularVelocity, b2Math.SubtractVV(center1, center)));
        var velocity2 = b2Math.AddVV(linearVelocity, b2Math.CrossFV(angularVelocity, b2Math.SubtractVV(center2, center)));
        body1.SetLinearVelocity(velocity1);
        body2.SetLinearVelocity(velocity2);
        body1.SetAngularVelocity(angularVelocity);
        body2.SetAngularVelocity(angularVelocity);
        body1.SynchronizeFixtures();
        body2.SynchronizeFixtures();
        return body2;
    }
    b2Body.prototype.Merge = function (other) {
        var f;
        for (f = other.m_fixtureList;
             f;) {
            var next = f.m_next;
            other.m_fixtureCount--;
            f.m_next = this.m_fixtureList;
            this.m_fixtureList = f;
            this.m_fixtureCount++;
            f.m_body = body2;
            f = next;
        }
        body1.m_fixtureCount = 0;
        var body1 = this;
        var body2 = other;
        var center1 = body1.GetWorldCenter();
        var center2 = body2.GetWorldCenter();
        var velocity1 = body1.GetLinearVelocity().Copy();
        var velocity2 = body2.GetLinearVelocity().Copy();
        var angular1 = body1.GetAngularVelocity();
        var angular = body2.GetAngularVelocity();
        body1.ResetMassData();
        this.SynchronizeFixtures();
    }
    b2Body.prototype.GetMass = function () {
        return this.m_mass;
    }
    b2Body.prototype.GetInertia = function () {
        return this.m_I;
    }
    b2Body.prototype.GetMassData = function (data) {
        data.mass = this.m_mass;
        data.I = this.m_I;
        data.center.SetV(this.m_sweep.localCenter);
    }
    b2Body.prototype.SetMassData = function (massData) {
        b2Settings.b2Assert(this.m_world.IsLocked() == false);
        if (this.m_world.IsLocked() == true) {
            return;
        }
        if (this.m_type != b2Body.b2_dynamicBody) {
            return;
        }
        this.m_invMass = 0.0;
        this.m_I = 0.0;
        this.m_invI = 0.0;
        this.m_mass = massData.mass;
        if (this.m_mass <= 0.0) {
            this.m_mass = 1.0;
        }
        this.m_invMass = 1.0 / this.m_mass;
        if (massData.I > 0.0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) {
            this.m_I = massData.I - this.m_mass * (massData.center.x * massData.center.x + massData.center.y * massData.center.y);
            this.m_invI = 1.0 / this.m_I;
        }
        var oldCenter = this.m_sweep.c.Copy();
        this.m_sweep.localCenter.SetV(massData.center);
        this.m_sweep.c0.SetV(b2Math.MulX(this.m_xf, this.m_sweep.localCenter));
        this.m_sweep.c.SetV(this.m_sweep.c0);
        this.m_linearVelocity.x += this.m_angularVelocity * (-(this.m_sweep.c.y - oldCenter.y));
        this.m_linearVelocity.y += this.m_angularVelocity * (+(this.m_sweep.c.x - oldCenter.x));
    }
    b2Body.prototype.ResetMassData = function () {
        this.m_mass = 0.0;
        this.m_invMass = 0.0;
        this.m_I = 0.0;
        this.m_invI = 0.0;
        this.m_sweep.localCenter.SetZero();
        if (this.m_type == b2Body.b2_staticBody || this.m_type == b2Body.b2_kinematicBody) {
            return;
        }
        var center = b2Vec2.Make(0, 0);
        for (var f = this.m_fixtureList; f; f = f.m_next) {
            if (f.m_density == 0.0) {
                continue;
            }
            var massData = f.GetMassData();
            this.m_mass += massData.mass;
            center.x += massData.center.x * massData.mass;
            center.y += massData.center.y * massData.mass;
            this.m_I += massData.I;
        }
        if (this.m_mass > 0.0) {
            this.m_invMass = 1.0 / this.m_mass;
            center.x *= this.m_invMass;
            center.y *= this.m_invMass;
        }
        else {
            this.m_mass = 1.0;
            this.m_invMass = 1.0;
        }
        if (this.m_I > 0.0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) {
            this.m_I -= this.m_mass * (center.x * center.x + center.y * center.y);
            this.m_I *= this.m_inertiaScale;
            b2Settings.b2Assert(this.m_I > 0);
            this.m_invI = 1.0 / this.m_I;
        }
        else {
            this.m_I = 0.0;
            this.m_invI = 0.0;
        }
        var oldCenter = this.m_sweep.c.Copy();
        this.m_sweep.localCenter.SetV(center);
        this.m_sweep.c0.SetV(b2Math.MulX(this.m_xf, this.m_sweep.localCenter));
        this.m_sweep.c.SetV(this.m_sweep.c0);
        this.m_linearVelocity.x += this.m_angularVelocity * (-(this.m_sweep.c.y - oldCenter.y));
        this.m_linearVelocity.y += this.m_angularVelocity * (+(this.m_sweep.c.x - oldCenter.x));
    }
    b2Body.prototype.GetWorldPoint = function (localPoint) {
        var A = this.m_xf.R;
        var u = new b2Vec2(A.col1.x * localPoint.x + A.col2.x * localPoint.y, A.col1.y * localPoint.x + A.col2.y * localPoint.y);
        u.x += this.m_xf.position.x;
        u.y += this.m_xf.position.y;
        return u;
    }
    b2Body.prototype.GetWorldVector = function (localVector) {
        return b2Math.MulMV(this.m_xf.R, localVector);
    }
    b2Body.prototype.GetLocalPoint = function (worldPoint) {
        return b2Math.MulXT(this.m_xf, worldPoint);
    }
    b2Body.prototype.GetLocalVector = function (worldVector) {
        return b2Math.MulTMV(this.m_xf.R, worldVector);
    }
    b2Body.prototype.GetLinearVelocityFromWorldPoint = function (worldPoint) {
        return new b2Vec2(this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y), this.m_linearVelocity.y + this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x));
    }
    b2Body.prototype.GetLinearVelocityFromLocalPoint = function (localPoint) {
        var A = this.m_xf.R;
        var worldPoint = new b2Vec2(A.col1.x * localPoint.x + A.col2.x * localPoint.y, A.col1.y * localPoint.x + A.col2.y * localPoint.y);
        worldPoint.x += this.m_xf.position.x;
        worldPoint.y += this.m_xf.position.y;
        return new b2Vec2(this.m_linearVelocity.x - this.m_angularVelocity * (worldPoint.y - this.m_sweep.c.y), this.m_linearVelocity.y + this.m_angularVelocity * (worldPoint.x - this.m_sweep.c.x));
    }
    b2Body.prototype.GetLinearDamping = function () {
        return this.m_linearDamping;
    }
    b2Body.prototype.SetLinearDamping = function (linearDamping) {
        if (linearDamping === undefined) linearDamping = 0;
        this.m_linearDamping = linearDamping;
    }
    b2Body.prototype.GetAngularDamping = function () {
        return this.m_angularDamping;
    }
    b2Body.prototype.SetAngularDamping = function (angularDamping) {
        if (angularDamping === undefined) angularDamping = 0;
        this.m_angularDamping = angularDamping;
    }
    b2Body.prototype.SetType = function (type) {
        if (type === undefined) type = 0;
        if (this.m_type == type) {
            return;
        }
        this.m_type = type;
        this.ResetMassData();
        if (this.m_type == b2Body.b2_staticBody) {
            this.m_linearVelocity.SetZero();
            this.m_angularVelocity = 0.0;
        }
        this.SetAwake(true);
        this.m_force.SetZero();
        this.m_torque = 0.0;
        for (var ce = this.m_contactList; ce; ce = ce.next) {
            ce.contact.FlagForFiltering();
        }
    }
    b2Body.prototype.GetType = function () {
        return this.m_type;
    }
    b2Body.prototype.SetBullet = function (flag) {
        if (flag) {
            this.m_flags |= b2Body.e_bulletFlag;
        }
        else {
            this.m_flags &= ~b2Body.e_bulletFlag;
        }
    }
    b2Body.prototype.IsBullet = function () {
        return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag;
    }
    b2Body.prototype.SetSleepingAllowed = function (flag) {
        if (flag) {
            this.m_flags |= b2Body.e_allowSleepFlag;
        }
        else {
            this.m_flags &= ~b2Body.e_allowSleepFlag;
            this.SetAwake(true);
        }
    }
    b2Body.prototype.SetAwake = function (flag) {
        if (flag) {
            this.m_flags |= b2Body.e_awakeFlag;
            this.m_sleepTime = 0.0;
        }
        else {
            this.m_flags &= ~b2Body.e_awakeFlag;
            this.m_sleepTime = 0.0;
            this.m_linearVelocity.SetZero();
            this.m_angularVelocity = 0.0;
            this.m_force.SetZero();
            this.m_torque = 0.0;
        }
    }
    b2Body.prototype.IsAwake = function () {
        return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag;
    }
    b2Body.prototype.SetFixedRotation = function (fixed) {
        if (fixed) {
            this.m_flags |= b2Body.e_fixedRotationFlag;
        }
        else {
            this.m_flags &= ~b2Body.e_fixedRotationFlag;
        }
        this.ResetMassData();
    }
    b2Body.prototype.IsFixedRotation = function () {
        return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag;
    }
    b2Body.prototype.SetActive = function (flag) {
        if (flag == this.IsActive()) {
            return;
        }
        var broadPhase;
        var f;
        if (flag) {
            this.m_flags |= b2Body.e_activeFlag;
            broadPhase = this.m_world.m_contactManager.m_broadPhase;
            for (f = this.m_fixtureList;
                 f; f = f.m_next) {
                f.CreateProxy(broadPhase, this.m_xf);
            }
        }
        else {
            this.m_flags &= ~b2Body.e_activeFlag;
            broadPhase = this.m_world.m_contactManager.m_broadPhase;
            for (f = this.m_fixtureList;
                 f; f = f.m_next) {
                f.DestroyProxy(broadPhase);
            }
            var ce = this.m_contactList;
            while (ce) {
                var ce0 = ce;
                ce = ce.next;
                this.m_world.m_contactManager.Destroy(ce0.contact);
            }
            this.m_contactList = null;
        }
    }
    b2Body.prototype.IsActive = function () {
        return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag;
    }
    b2Body.prototype.IsSleepingAllowed = function () {
        return (this.m_flags & b2Body.e_allowSleepFlag) == b2Body.e_allowSleepFlag;
    }
    b2Body.prototype.GetFixtureList = function () {
        return this.m_fixtureList;
    }
    b2Body.prototype.GetJointList = function () {
        return this.m_jointList;
    }
    b2Body.prototype.GetControllerList = function () {
        return this.m_controllerList;
    }
    b2Body.prototype.GetContactList = function () {
        return this.m_contactList;
    }
    b2Body.prototype.GetNext = function () {
        return this.m_next;
    }
    b2Body.prototype.GetUserData = function () {
        return this.m_userData;
    }
    b2Body.prototype.SetUserData = function (data) {
        this.m_userData = data;
    }
    b2Body.prototype.GetWorld = function () {
        return this.m_world;
    }
    b2Body.prototype.b2Body = function (bd, world) {
        this.m_flags = 0;
        if (bd.bullet) {
            this.m_flags |= b2Body.e_bulletFlag;
        }
        if (bd.fixedRotation) {
            this.m_flags |= b2Body.e_fixedRotationFlag;
        }
        if (bd.allowSleep) {
            this.m_flags |= b2Body.e_allowSleepFlag;
        }
        if (bd.awake) {
            this.m_flags |= b2Body.e_awakeFlag;
        }
        if (bd.active) {
            this.m_flags |= b2Body.e_activeFlag;
        }
        this.m_world = world;
        this.m_xf.position.SetV(bd.position);
        this.m_xf.R.Set(bd.angle);
        this.m_sweep.localCenter.SetZero();
        this.m_sweep.t0 = 1.0;
        this.m_sweep.a0 = this.m_sweep.a = bd.angle;
        var tMat = this.m_xf.R;
        var tVec = this.m_sweep.localCenter;
        this.m_sweep.c.x = (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        this.m_sweep.c.y = (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        this.m_sweep.c.x += this.m_xf.position.x;
        this.m_sweep.c.y += this.m_xf.position.y;
        this.m_sweep.c0.SetV(this.m_sweep.c);
        this.m_jointList = null;
        this.m_controllerList = null;
        this.m_contactList = null;
        this.m_controllerCount = 0;
        this.m_prev = null;
        this.m_next = null;
        this.m_linearVelocity.SetV(bd.linearVelocity);
        this.m_angularVelocity = bd.angularVelocity;
        this.m_linearDamping = bd.linearDamping;
        this.m_angularDamping = bd.angularDamping;
        this.m_force.Set(0.0, 0.0);
        this.m_torque = 0.0;
        this.m_sleepTime = 0.0;
        this.m_type = bd.type;
        if (this.m_type == b2Body.b2_dynamicBody) {
            this.m_mass = 1.0;
            this.m_invMass = 1.0;
        }
        else {
            this.m_mass = 0.0;
            this.m_invMass = 0.0;
        }
        this.m_I = 0.0;
        this.m_invI = 0.0;
        this.m_inertiaScale = bd.inertiaScale;
        this.m_userData = bd.userData;
        this.m_fixtureList = null;
        this.m_fixtureCount = 0;
    }
    b2Body.prototype.SynchronizeFixtures = function () {
        var xf1 = b2Body.s_xf1;
        xf1.R.Set(this.m_sweep.a0);
        var tMat = xf1.R;
        var tVec = this.m_sweep.localCenter;
        xf1.position.x = this.m_sweep.c0.x - (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        xf1.position.y = this.m_sweep.c0.y - (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
        var f;
        var broadPhase = this.m_world.m_contactManager.m_broadPhase;
        for (f = this.m_fixtureList;
             f; f = f.m_next) {
            f.Synchronize(broadPhase, xf1, this.m_xf);
        }
    }
    b2Body.prototype.SynchronizeTransform = function () {
        this.m_xf.R.Set(this.m_sweep.a);
        var tMat = this.m_xf.R;
        var tVec = this.m_sweep.localCenter;
        this.m_xf.position.x = this.m_sweep.c.x - (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
        this.m_xf.position.y = this.m_sweep.c.y - (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
    }
    b2Body.prototype.ShouldCollide = function (other) {
        if (this.m_type != b2Body.b2_dynamicBody && other.m_type != b2Body.b2_dynamicBody) {
            return false;
        }
        for (var jn = this.m_jointList; jn; jn = jn.next) {
            if (jn.other == other) if (jn.joint.m_collideConnected == false) {
                return false;
            }
        }
        return true;
    }
    b2Body.prototype.Advance = function (t) {
        if (t === undefined) t = 0;
        this.m_sweep.Advance(t);
        this.m_sweep.c.SetV(this.m_sweep.c0);
        this.m_sweep.a = this.m_sweep.a0;
        this.SynchronizeTransform();
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2Body.s_xf1 = new b2Transform();
        Box2D.Dynamics.b2Body.e_islandFlag = 0x0001;
        Box2D.Dynamics.b2Body.e_awakeFlag = 0x0002;
        Box2D.Dynamics.b2Body.e_allowSleepFlag = 0x0004;
        Box2D.Dynamics.b2Body.e_bulletFlag = 0x0008;
        Box2D.Dynamics.b2Body.e_fixedRotationFlag = 0x0010;
        Box2D.Dynamics.b2Body.e_activeFlag = 0x0020;
        Box2D.Dynamics.b2Body.b2_staticBody = 0;
        Box2D.Dynamics.b2Body.b2_kinematicBody = 1;
        Box2D.Dynamics.b2Body.b2_dynamicBody = 2;
    });
    b2BodyDef.b2BodyDef = function () {
        this.position = new b2Vec2();
        this.linearVelocity = new b2Vec2();
    };
    b2BodyDef.prototype.b2BodyDef = function () {
        this.userData = null;
        this.position.Set(0.0, 0.0);
        this.angle = 0.0;
        this.linearVelocity.Set(0, 0);
        this.angularVelocity = 0.0;
        this.linearDamping = 0.0;
        this.angularDamping = 0.0;
        this.allowSleep = true;
        this.awake = true;
        this.fixedRotation = false;
        this.bullet = false;
        this.type = b2Body.b2_staticBody;
        this.active = true;
        this.inertiaScale = 1.0;
    }
    b2ContactFilter.b2ContactFilter = function () {};
    b2ContactFilter.prototype.ShouldCollide = function (fixtureA, fixtureB) {
        var filter1 = fixtureA.GetFilterData();
        var filter2 = fixtureB.GetFilterData();
        if (filter1.groupIndex == filter2.groupIndex && filter1.groupIndex != 0) {
            return filter1.groupIndex > 0;
        }
        var collide = (filter1.maskBits & filter2.categoryBits) != 0 && (filter1.categoryBits & filter2.maskBits) != 0;
        return collide;
    }
    b2ContactFilter.prototype.RayCollide = function (userData, fixture) {
        if (!userData) return true;
        return this.ShouldCollide((userData instanceof b2Fixture ? userData : null), fixture);
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2ContactFilter.b2_defaultFilter = new b2ContactFilter();
    });
    b2ContactImpulse.b2ContactImpulse = function () {
        this.normalImpulses = new Vector_a2j_Number(b2Settings.b2_maxManifoldPoints);
        this.tangentImpulses = new Vector_a2j_Number(b2Settings.b2_maxManifoldPoints);
    };
    b2ContactListener.b2ContactListener = function () {};
    b2ContactListener.prototype.BeginContact = function (contact) {}
    b2ContactListener.prototype.EndContact = function (contact) {}
    b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {}
    b2ContactListener.prototype.PostSolve = function (contact, impulse) {}
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2ContactListener.b2_defaultListener = new b2ContactListener();
    });
    b2ContactManager.b2ContactManager = function () {};
    b2ContactManager.prototype.b2ContactManager = function () {
        this.m_world = null;
        this.m_contactCount = 0;
        this.m_contactFilter = b2ContactFilter.b2_defaultFilter;
        this.m_contactListener = b2ContactListener.b2_defaultListener;
        this.m_contactFactory = new b2ContactFactory(this.m_allocator);
        this.m_broadPhase = new b2DynamicTreeBroadPhase();
    }
    b2ContactManager.prototype.AddPair = function (proxyUserDataA, proxyUserDataB) {
        var fixtureA = (proxyUserDataA instanceof b2Fixture ? proxyUserDataA : null);
        var fixtureB = (proxyUserDataB instanceof b2Fixture ? proxyUserDataB : null);
        var bodyA = fixtureA.GetBody();
        var bodyB = fixtureB.GetBody();
        if (bodyA == bodyB) return;
        var edge = bodyB.GetContactList();
        while (edge) {
            if (edge.other == bodyA) {
                var fA = edge.contact.GetFixtureA();
                var fB = edge.contact.GetFixtureB();
                if (fA == fixtureA && fB == fixtureB) return;
                if (fA == fixtureB && fB == fixtureA) return;
            }
            edge = edge.next;
        }
        if (bodyB.ShouldCollide(bodyA) == false) {
            return;
        }
        if (this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) {
            return;
        }
        var c = this.m_contactFactory.Create(fixtureA, fixtureB);
        fixtureA = c.GetFixtureA();
        fixtureB = c.GetFixtureB();
        bodyA = fixtureA.m_body;
        bodyB = fixtureB.m_body;
        c.m_prev = null;
        c.m_next = this.m_world.m_contactList;
        if (this.m_world.m_contactList != null) {
            this.m_world.m_contactList.m_prev = c;
        }
        this.m_world.m_contactList = c;
        c.m_nodeA.contact = c;
        c.m_nodeA.other = bodyB;
        c.m_nodeA.prev = null;
        c.m_nodeA.next = bodyA.m_contactList;
        if (bodyA.m_contactList != null) {
            bodyA.m_contactList.prev = c.m_nodeA;
        }
        bodyA.m_contactList = c.m_nodeA;
        c.m_nodeB.contact = c;
        c.m_nodeB.other = bodyA;
        c.m_nodeB.prev = null;
        c.m_nodeB.next = bodyB.m_contactList;
        if (bodyB.m_contactList != null) {
            bodyB.m_contactList.prev = c.m_nodeB;
        }
        bodyB.m_contactList = c.m_nodeB;
        ++this.m_world.m_contactCount;
        return;
    }
    b2ContactManager.prototype.FindNewContacts = function () {
        this.m_broadPhase.UpdatePairs(Box2D.generateCallback(this, this.AddPair));
    }
    b2ContactManager.prototype.Destroy = function (c) {
        var fixtureA = c.GetFixtureA();
        var fixtureB = c.GetFixtureB();
        var bodyA = fixtureA.GetBody();
        var bodyB = fixtureB.GetBody();
        if (c.IsTouching()) {
            this.m_contactListener.EndContact(c);
        }
        if (c.m_prev) {
            c.m_prev.m_next = c.m_next;
        }
        if (c.m_next) {
            c.m_next.m_prev = c.m_prev;
        }
        if (c == this.m_world.m_contactList) {
            this.m_world.m_contactList = c.m_next;
        }
        if (c.m_nodeA.prev) {
            c.m_nodeA.prev.next = c.m_nodeA.next;
        }
        if (c.m_nodeA.next) {
            c.m_nodeA.next.prev = c.m_nodeA.prev;
        }
        if (c.m_nodeA == bodyA.m_contactList) {
            bodyA.m_contactList = c.m_nodeA.next;
        }
        if (c.m_nodeB.prev) {
            c.m_nodeB.prev.next = c.m_nodeB.next;
        }
        if (c.m_nodeB.next) {
            c.m_nodeB.next.prev = c.m_nodeB.prev;
        }
        if (c.m_nodeB == bodyB.m_contactList) {
            bodyB.m_contactList = c.m_nodeB.next;
        }
        this.m_contactFactory.Destroy(c);
        --this.m_contactCount;
    }
    b2ContactManager.prototype.Collide = function () {
        var c = this.m_world.m_contactList;
        while (c) {
            var fixtureA = c.GetFixtureA();
            var fixtureB = c.GetFixtureB();
            var bodyA = fixtureA.GetBody();
            var bodyB = fixtureB.GetBody();
            if (bodyA.IsAwake() == false && bodyB.IsAwake() == false) {
                c = c.GetNext();
                continue;
            }
            if (c.m_flags & b2Contact.e_filterFlag) {
                if (bodyB.ShouldCollide(bodyA) == false) {
                    var cNuke = c;
                    c = cNuke.GetNext();
                    this.Destroy(cNuke);
                    continue;
                }
                if (this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) {
                    cNuke = c;
                    c = cNuke.GetNext();
                    this.Destroy(cNuke);
                    continue;
                }
                c.m_flags &= ~b2Contact.e_filterFlag;
            }
            var proxyA = fixtureA.m_proxy;
            var proxyB = fixtureB.m_proxy;
            var overlap = this.m_broadPhase.TestOverlap(proxyA, proxyB);
            if (overlap == false) {
                cNuke = c;
                c = cNuke.GetNext();
                this.Destroy(cNuke);
                continue;
            }
            c.Update(this.m_contactListener);
            c = c.GetNext();
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2ContactManager.s_evalCP = new b2ContactPoint();
    });
    b2DebugDraw.b2DebugDraw = function () {};
    b2DebugDraw.prototype.b2DebugDraw = function () {}
    b2DebugDraw.prototype.SetFlags = function (flags) {
        if (flags === undefined) flags = 0;
    }
    b2DebugDraw.prototype.GetFlags = function () {}
    b2DebugDraw.prototype.AppendFlags = function (flags) {
        if (flags === undefined) flags = 0;
    }
    b2DebugDraw.prototype.ClearFlags = function (flags) {
        if (flags === undefined) flags = 0;
    }
    b2DebugDraw.prototype.SetSprite = function (sprite) {}
    b2DebugDraw.prototype.GetSprite = function () {}
    b2DebugDraw.prototype.SetDrawScale = function (drawScale) {
        if (drawScale === undefined) drawScale = 0;
    }
    b2DebugDraw.prototype.GetDrawScale = function () {}
    b2DebugDraw.prototype.SetLineThickness = function (lineThickness) {
        if (lineThickness === undefined) lineThickness = 0;
    }
    b2DebugDraw.prototype.GetLineThickness = function () {}
    b2DebugDraw.prototype.SetAlpha = function (alpha) {
        if (alpha === undefined) alpha = 0;
    }
    b2DebugDraw.prototype.GetAlpha = function () {}
    b2DebugDraw.prototype.SetFillAlpha = function (alpha) {
        if (alpha === undefined) alpha = 0;
    }
    b2DebugDraw.prototype.GetFillAlpha = function () {}
    b2DebugDraw.prototype.SetXFormScale = function (xformScale) {
        if (xformScale === undefined) xformScale = 0;
    }
    b2DebugDraw.prototype.GetXFormScale = function () {}
    b2DebugDraw.prototype.DrawPolygon = function (vertices, vertexCount, color) {
        if (vertexCount === undefined) vertexCount = 0;
    }
    b2DebugDraw.prototype.DrawSolidPolygon = function (vertices, vertexCount, color) {
        if (vertexCount === undefined) vertexCount = 0;
    }
    b2DebugDraw.prototype.DrawCircle = function (center, radius, color) {
        if (radius === undefined) radius = 0;
    }
    b2DebugDraw.prototype.DrawSolidCircle = function (center, radius, axis, color) {
        if (radius === undefined) radius = 0;
    }
    b2DebugDraw.prototype.DrawSegment = function (p1, p2, color) {}
    b2DebugDraw.prototype.DrawTransform = function (xf) {}
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2DebugDraw.e_shapeBit = 0x0001;
        Box2D.Dynamics.b2DebugDraw.e_jointBit = 0x0002;
        Box2D.Dynamics.b2DebugDraw.e_aabbBit = 0x0004;
        Box2D.Dynamics.b2DebugDraw.e_pairBit = 0x0008;
        Box2D.Dynamics.b2DebugDraw.e_centerOfMassBit = 0x0010;
        Box2D.Dynamics.b2DebugDraw.e_controllerBit = 0x0020;
    });
    b2DestructionListener.b2DestructionListener = function () {};
    b2DestructionListener.prototype.SayGoodbyeJoint = function (joint) {}
    b2DestructionListener.prototype.SayGoodbyeFixture = function (fixture) {}
    b2FilterData.b2FilterData = function () {
        this.categoryBits = 0x0001;
        this.maskBits = 0xFFFF;
        this.groupIndex = 0;
    };
    b2FilterData.prototype.Copy = function () {
        var copy = new b2FilterData();
        copy.categoryBits = this.categoryBits;
        copy.maskBits = this.maskBits;
        copy.groupIndex = this.groupIndex;
        return copy;
    }
    b2Fixture.b2Fixture = function () {
        this.m_filter = new b2FilterData();
    };
    b2Fixture.prototype.GetType = function () {
        return this.m_shape.GetType();
    }
    b2Fixture.prototype.GetShape = function () {
        return this.m_shape;
    }
    b2Fixture.prototype.SetSensor = function (sensor) {
        if (this.m_isSensor == sensor) return;
        this.m_isSensor = sensor;
        if (this.m_body == null) return;
        var edge = this.m_body.GetContactList();
        while (edge) {
            var contact = edge.contact;
            var fixtureA = contact.GetFixtureA();
            var fixtureB = contact.GetFixtureB();
            if (fixtureA == this || fixtureB == this) contact.SetSensor(fixtureA.IsSensor() || fixtureB.IsSensor());
            edge = edge.next;
        }
    }
    b2Fixture.prototype.IsSensor = function () {
        return this.m_isSensor;
    }
    b2Fixture.prototype.SetFilterData = function (filter) {
        this.m_filter = filter.Copy();
        if (this.m_body) return;
        var edge = this.m_body.GetContactList();
        while (edge) {
            var contact = edge.contact;
            var fixtureA = contact.GetFixtureA();
            var fixtureB = contact.GetFixtureB();
            if (fixtureA == this || fixtureB == this) contact.FlagForFiltering();
            edge = edge.next;
        }
    }
    b2Fixture.prototype.GetFilterData = function () {
        return this.m_filter.Copy();
    }
    b2Fixture.prototype.GetBody = function () {
        return this.m_body;
    }
    b2Fixture.prototype.GetNext = function () {
        return this.m_next;
    }
    b2Fixture.prototype.GetUserData = function () {
        return this.m_userData;
    }
    b2Fixture.prototype.SetUserData = function (data) {
        this.m_userData = data;
    }
    b2Fixture.prototype.TestPoint = function (p) {
        return this.m_shape.TestPoint(this.m_body.GetTransform(), p);
    }
    b2Fixture.prototype.RayCast = function (output, input) {
        return this.m_shape.RayCast(output, input, this.m_body.GetTransform());
    }
    b2Fixture.prototype.GetMassData = function (massData) {
        if (massData === undefined) massData = null;
        if (massData == null) {
            massData = new b2MassData();
        }
        this.m_shape.ComputeMass(massData, this.m_density);
        return massData;
    }
    b2Fixture.prototype.SetDensity = function (density) {
        if (density === undefined) density = 0;
        this.m_density = density;
    }
    b2Fixture.prototype.GetDensity = function () {
        return this.m_density;
    }
    b2Fixture.prototype.GetFriction = function () {
        return this.m_friction;
    }
    b2Fixture.prototype.SetFriction = function (friction) {
        if (friction === undefined) friction = 0;
        this.m_friction = friction;
    }
    b2Fixture.prototype.GetRestitution = function () {
        return this.m_restitution;
    }
    b2Fixture.prototype.SetRestitution = function (restitution) {
        if (restitution === undefined) restitution = 0;
        this.m_restitution = restitution;
    }
    b2Fixture.prototype.GetAABB = function () {
        return this.m_aabb;
    }
    b2Fixture.prototype.b2Fixture = function () {
        this.m_aabb = new b2AABB();
        this.m_userData = null;
        this.m_body = null;
        this.m_next = null;
        this.m_shape = null;
        this.m_density = 0.0;
        this.m_friction = 0.0;
        this.m_restitution = 0.0;
    }
    b2Fixture.prototype.Create = function (body, xf, def) {
        this.m_userData = def.userData;
        this.m_friction = def.friction;
        this.m_restitution = def.restitution;
        this.m_body = body;
        this.m_next = null;
        this.m_filter = def.filter.Copy();
        this.m_isSensor = def.isSensor;
        this.m_shape = def.shape.Copy();
        this.m_density = def.density;
    }
    b2Fixture.prototype.Destroy = function () {
        this.m_shape = null;
    }
    b2Fixture.prototype.CreateProxy = function (broadPhase, xf) {
        this.m_shape.ComputeAABB(this.m_aabb, xf);
        this.m_proxy = broadPhase.CreateProxy(this.m_aabb, this);
    }
    b2Fixture.prototype.DestroyProxy = function (broadPhase) {
        if (this.m_proxy == null) {
            return;
        }
        broadPhase.DestroyProxy(this.m_proxy);
        this.m_proxy = null;
    }
    b2Fixture.prototype.Synchronize = function (broadPhase, transform1, transform2) {
        if (!this.m_proxy) return;
        var aabb1 = new b2AABB();
        var aabb2 = new b2AABB();
        this.m_shape.ComputeAABB(aabb1, transform1);
        this.m_shape.ComputeAABB(aabb2, transform2);
        this.m_aabb.Combine(aabb1, aabb2);
        var displacement = b2Math.SubtractVV(transform2.position, transform1.position);
        broadPhase.MoveProxy(this.m_proxy, this.m_aabb, displacement);
    }
    b2FixtureDef.b2FixtureDef = function () {
        this.filter = new b2FilterData();
    };
    b2FixtureDef.prototype.b2FixtureDef = function () {
        this.shape = null;
        this.userData = null;
        this.friction = 0.2;
        this.restitution = 0.0;
        this.density = 0.0;
        this.filter.categoryBits = 0x0001;
        this.filter.maskBits = 0xFFFF;
        this.filter.groupIndex = 0;
        this.isSensor = false;
    }
    b2Island.b2Island = function () {};
    b2Island.prototype.b2Island = function () {
        this.m_bodies = new Vector();
        this.m_contacts = new Vector();
        this.m_joints = new Vector();
    }
    b2Island.prototype.Initialize = function (bodyCapacity, contactCapacity, jointCapacity, allocator, listener, contactSolver) {
        if (bodyCapacity === undefined) bodyCapacity = 0;
        if (contactCapacity === undefined) contactCapacity = 0;
        if (jointCapacity === undefined) jointCapacity = 0;
        var i = 0;
        this.m_bodyCapacity = bodyCapacity;
        this.m_contactCapacity = contactCapacity;
        this.m_jointCapacity = jointCapacity;
        this.m_bodyCount = 0;
        this.m_contactCount = 0;
        this.m_jointCount = 0;
        this.m_allocator = allocator;
        this.m_listener = listener;
        this.m_contactSolver = contactSolver;
        for (i = this.m_bodies.length;
             i < bodyCapacity; i++)
            this.m_bodies[i] = null;
        for (i = this.m_contacts.length;
             i < contactCapacity; i++)
            this.m_contacts[i] = null;
        for (i = this.m_joints.length;
             i < jointCapacity; i++)
            this.m_joints[i] = null;
    }
    b2Island.prototype.Clear = function () {
        this.m_bodyCount = 0;
        this.m_contactCount = 0;
        this.m_jointCount = 0;
    }
    b2Island.prototype.Solve = function (step, gravity, allowSleep) {
        var i = 0;
        var j = 0;
        var b;
        var joint;
        for (i = 0;
             i < this.m_bodyCount; ++i) {
            b = this.m_bodies[i];
            if (b.GetType() != b2Body.b2_dynamicBody) continue;
            b.m_linearVelocity.x += step.dt * (gravity.x + b.m_invMass * b.m_force.x);
            b.m_linearVelocity.y += step.dt * (gravity.y + b.m_invMass * b.m_force.y);
            b.m_angularVelocity += step.dt * b.m_invI * b.m_torque;
            b.m_linearVelocity.Multiply(b2Math.Clamp(1.0 - step.dt * b.m_linearDamping, 0.0, 1.0));
            b.m_angularVelocity *= b2Math.Clamp(1.0 - step.dt * b.m_angularDamping, 0.0, 1.0);
        }
        this.m_contactSolver.Initialize(step, this.m_contacts, this.m_contactCount, this.m_allocator);
        var contactSolver = this.m_contactSolver;
        contactSolver.InitVelocityConstraints(step);
        for (i = 0;
             i < this.m_jointCount; ++i) {
            joint = this.m_joints[i];
            joint.InitVelocityConstraints(step);
        }
        for (i = 0;
             i < step.velocityIterations; ++i) {
            for (j = 0;
                 j < this.m_jointCount; ++j) {
                joint = this.m_joints[j];
                joint.SolveVelocityConstraints(step);
            }
            contactSolver.SolveVelocityConstraints();
        }
        for (i = 0;
             i < this.m_jointCount; ++i) {
            joint = this.m_joints[i];
            joint.FinalizeVelocityConstraints();
        }
        contactSolver.FinalizeVelocityConstraints();
        for (i = 0;
             i < this.m_bodyCount; ++i) {
            b = this.m_bodies[i];
            if (b.GetType() == b2Body.b2_staticBody) continue;
            var translationX = step.dt * b.m_linearVelocity.x;
            var translationY = step.dt * b.m_linearVelocity.y;
            if ((translationX * translationX + translationY * translationY) > b2Settings.b2_maxTranslationSquared) {
                b.m_linearVelocity.Normalize();
                b.m_linearVelocity.x *= b2Settings.b2_maxTranslation * step.inv_dt;
                b.m_linearVelocity.y *= b2Settings.b2_maxTranslation * step.inv_dt;
            }
            var rotation = step.dt * b.m_angularVelocity;
            if (rotation * rotation > b2Settings.b2_maxRotationSquared) {
                if (b.m_angularVelocity < 0.0) {
                    b.m_angularVelocity = (-b2Settings.b2_maxRotation * step.inv_dt);
                }
                else {
                    b.m_angularVelocity = b2Settings.b2_maxRotation * step.inv_dt;
                }
            }
            b.m_sweep.c0.SetV(b.m_sweep.c);
            b.m_sweep.a0 = b.m_sweep.a;
            b.m_sweep.c.x += step.dt * b.m_linearVelocity.x;
            b.m_sweep.c.y += step.dt * b.m_linearVelocity.y;
            b.m_sweep.a += step.dt * b.m_angularVelocity;
            b.SynchronizeTransform();
        }
        for (i = 0;
             i < step.positionIterations; ++i) {
            var contactsOkay = contactSolver.SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
            var jointsOkay = true;
            for (j = 0;
                 j < this.m_jointCount; ++j) {
                joint = this.m_joints[j];
                var jointOkay = joint.SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
                jointsOkay = jointsOkay && jointOkay;
            }
            if (contactsOkay && jointsOkay) {
                break;
            }
        }
        this.Report(contactSolver.m_constraints);
        if (allowSleep) {
            var minSleepTime = Number.MAX_VALUE;
            var linTolSqr = b2Settings.b2_linearSleepTolerance * b2Settings.b2_linearSleepTolerance;
            var angTolSqr = b2Settings.b2_angularSleepTolerance * b2Settings.b2_angularSleepTolerance;
            for (i = 0;
                 i < this.m_bodyCount; ++i) {
                b = this.m_bodies[i];
                if (b.GetType() == b2Body.b2_staticBody) {
                    continue;
                }
                if ((b.m_flags & b2Body.e_allowSleepFlag) == 0) {
                    b.m_sleepTime = 0.0;
                    minSleepTime = 0.0;
                }
                if ((b.m_flags & b2Body.e_allowSleepFlag) == 0 || b.m_angularVelocity * b.m_angularVelocity > angTolSqr || b2Math.Dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) {
                    b.m_sleepTime = 0.0;
                    minSleepTime = 0.0;
                }
                else {
                    b.m_sleepTime += step.dt;
                    minSleepTime = b2Math.Min(minSleepTime, b.m_sleepTime);
                }
            }
            if (minSleepTime >= b2Settings.b2_timeToSleep) {
                for (i = 0;
                     i < this.m_bodyCount; ++i) {
                    b = this.m_bodies[i];
                    b.SetAwake(false);
                }
            }
        }
    }
    b2Island.prototype.SolveTOI = function (subStep) {
        var i = 0;
        var j = 0;
        this.m_contactSolver.Initialize(subStep, this.m_contacts, this.m_contactCount, this.m_allocator);
        var contactSolver = this.m_contactSolver;
        for (i = 0;
             i < this.m_jointCount; ++i) {
            this.m_joints[i].InitVelocityConstraints(subStep);
        }
        for (i = 0;
             i < subStep.velocityIterations; ++i) {
            contactSolver.SolveVelocityConstraints();
            for (j = 0;
                 j < this.m_jointCount; ++j) {
                this.m_joints[j].SolveVelocityConstraints(subStep);
            }
        }
        for (i = 0;
             i < this.m_bodyCount; ++i) {
            var b = this.m_bodies[i];
            if (b.GetType() == b2Body.b2_staticBody) continue;
            var translationX = subStep.dt * b.m_linearVelocity.x;
            var translationY = subStep.dt * b.m_linearVelocity.y;
            if ((translationX * translationX + translationY * translationY) > b2Settings.b2_maxTranslationSquared) {
                b.m_linearVelocity.Normalize();
                b.m_linearVelocity.x *= b2Settings.b2_maxTranslation * subStep.inv_dt;
                b.m_linearVelocity.y *= b2Settings.b2_maxTranslation * subStep.inv_dt;
            }
            var rotation = subStep.dt * b.m_angularVelocity;
            if (rotation * rotation > b2Settings.b2_maxRotationSquared) {
                if (b.m_angularVelocity < 0.0) {
                    b.m_angularVelocity = (-b2Settings.b2_maxRotation * subStep.inv_dt);
                }
                else {
                    b.m_angularVelocity = b2Settings.b2_maxRotation * subStep.inv_dt;
                }
            }
            b.m_sweep.c0.SetV(b.m_sweep.c);
            b.m_sweep.a0 = b.m_sweep.a;
            b.m_sweep.c.x += subStep.dt * b.m_linearVelocity.x;
            b.m_sweep.c.y += subStep.dt * b.m_linearVelocity.y;
            b.m_sweep.a += subStep.dt * b.m_angularVelocity;
            b.SynchronizeTransform();
        }
        var k_toiBaumgarte = 0.75;
        for (i = 0;
             i < subStep.positionIterations; ++i) {
            var contactsOkay = contactSolver.SolvePositionConstraints(k_toiBaumgarte);
            var jointsOkay = true;
            for (j = 0;
                 j < this.m_jointCount; ++j) {
                var jointOkay = this.m_joints[j].SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
                jointsOkay = jointsOkay && jointOkay;
            }
            if (contactsOkay && jointsOkay) {
                break;
            }
        }
        this.Report(contactSolver.m_constraints);
    }
    b2Island.prototype.Report = function (constraints) {
        if (this.m_listener == null) {
            return;
        }
        for (var i = 0; i < this.m_contactCount; ++i) {
            var c = this.m_contacts[i];
            var cc = constraints[i];
            for (var j = 0; j < cc.pointCount; ++j) {
                b2Island.s_impulse.normalImpulses[j] = cc.points[j].normalImpulse;
                b2Island.s_impulse.tangentImpulses[j] = cc.points[j].tangentImpulse;
            }
            this.m_listener.PostSolve(c, b2Island.s_impulse);
        }
    }
    b2Island.prototype.AddBody = function (body) {
        body.m_islandIndex = this.m_bodyCount;
        this.m_bodies[this.m_bodyCount++] = body;
    }
    b2Island.prototype.AddContact = function (contact) {
        this.m_contacts[this.m_contactCount++] = contact;
    }
    b2Island.prototype.AddJoint = function (joint) {
        this.m_joints[this.m_jointCount++] = joint;
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2Island.s_impulse = new b2ContactImpulse();
    });
    b2TimeStep.b2TimeStep = function () {};
    b2TimeStep.prototype.Set = function (step) {
        this.dt = step.dt;
        this.inv_dt = step.inv_dt;
        this.positionIterations = step.positionIterations;
        this.velocityIterations = step.velocityIterations;
        this.warmStarting = step.warmStarting;
    }
    b2World.b2World = function () {
        this.s_stack = new Vector();
        this.m_contactManager = new b2ContactManager();
        this.m_contactSolver = new b2ContactSolver();
        this.m_island = new b2Island();
    };
    b2World.prototype.b2World = function (gravity, doSleep) {
        this.m_destructionListener = null;
        this.m_debugDraw = null;
        this.m_bodyList = null;
        this.m_contactList = null;
        this.m_jointList = null;
        this.m_controllerList = null;
        this.m_bodyCount = 0;
        this.m_contactCount = 0;
        this.m_jointCount = 0;
        this.m_controllerCount = 0;
        b2World.m_warmStarting = true;
        b2World.m_continuousPhysics = true;
        this.m_allowSleep = doSleep;
        gravity.y = gravity.y;
        this.m_gravity = gravity;
        this.m_inv_dt0 = 0.0;
        this.m_contactManager.m_world = this;
        var bd = new b2BodyDef();
        this.m_groundBody = this.CreateBody(bd);
    }
    b2World.prototype.SetDestructionListener = function (listener) {
        this.m_destructionListener = listener;
    }
    b2World.prototype.SetContactFilter = function (filter) {
        this.m_contactManager.m_contactFilter = filter;
    }
    b2World.prototype.SetContactListener = function (listener) {
        this.m_contactManager.m_contactListener = listener;
    }
    b2World.prototype.SetDebugDraw = function (debugDraw) {
        this.m_debugDraw = debugDraw;
    }
    b2World.prototype.SetBroadPhase = function (broadPhase) {
        var oldBroadPhase = this.m_contactManager.m_broadPhase;
        this.m_contactManager.m_broadPhase = broadPhase;
        for (var b = this.m_bodyList; b; b = b.m_next) {
            for (var f = b.m_fixtureList; f; f = f.m_next) {
                f.m_proxy = broadPhase.CreateProxy(oldBroadPhase.GetFatAABB(f.m_proxy), f);
            }
        }
    }
    b2World.prototype.Validate = function () {
        this.m_contactManager.m_broadPhase.Validate();
    }
    b2World.prototype.GetProxyCount = function () {
        return this.m_contactManager.m_broadPhase.GetProxyCount();
    }
    b2World.prototype.CreateBody = function (def) {
        if (this.IsLocked() == true) {
            return null;
        }
        var b = new b2Body(def, this);
        b.m_prev = null;
        b.m_next = this.m_bodyList;
        if (this.m_bodyList) {
            this.m_bodyList.m_prev = b;
        }
        this.m_bodyList = b;
        ++this.m_bodyCount;
        return b;
    }
    b2World.prototype.DestroyBody = function (b) {
        if (this.IsLocked() == true) {
            return;
        }
        var jn = b.m_jointList;
        while (jn) {
            var jn0 = jn;
            jn = jn.next;
            if (this.m_destructionListener) {
                this.m_destructionListener.SayGoodbyeJoint(jn0.joint);
            }
            this.DestroyJoint(jn0.joint);
        }
        var coe = b.m_controllerList;
        while (coe) {
            var coe0 = coe;
            coe = coe.nextController;
            coe0.controller.RemoveBody(b);
        }
        var ce = b.m_contactList;
        while (ce) {
            var ce0 = ce;
            ce = ce.next;
            this.m_contactManager.Destroy(ce0.contact);
        }
        b.m_contactList = null;
        var f = b.m_fixtureList;
        while (f) {
            var f0 = f;
            f = f.m_next;
            if (this.m_destructionListener) {
                this.m_destructionListener.SayGoodbyeFixture(f0);
            }
            f0.DestroyProxy(this.m_contactManager.m_broadPhase);
            f0.Destroy();
        }
        b.m_fixtureList = null;
        b.m_fixtureCount = 0;
        if (b.m_prev) {
            b.m_prev.m_next = b.m_next;
        }
        if (b.m_next) {
            b.m_next.m_prev = b.m_prev;
        }
        if (b == this.m_bodyList) {
            this.m_bodyList = b.m_next;
        }--this.m_bodyCount;
    }
    b2World.prototype.CreateJoint = function (def) {
        var j = b2Joint.Create(def, null);
        j.m_prev = null;
        j.m_next = this.m_jointList;
        if (this.m_jointList) {
            this.m_jointList.m_prev = j;
        }
        this.m_jointList = j;
        ++this.m_jointCount;
        j.m_edgeA.joint = j;
        j.m_edgeA.other = j.m_bodyB;
        j.m_edgeA.prev = null;
        j.m_edgeA.next = j.m_bodyA.m_jointList;
        if (j.m_bodyA.m_jointList) j.m_bodyA.m_jointList.prev = j.m_edgeA;
        j.m_bodyA.m_jointList = j.m_edgeA;
        j.m_edgeB.joint = j;
        j.m_edgeB.other = j.m_bodyA;
        j.m_edgeB.prev = null;
        j.m_edgeB.next = j.m_bodyB.m_jointList;
        if (j.m_bodyB.m_jointList) j.m_bodyB.m_jointList.prev = j.m_edgeB;
        j.m_bodyB.m_jointList = j.m_edgeB;
        var bodyA = def.bodyA;
        var bodyB = def.bodyB;
        if (def.collideConnected == false) {
            var edge = bodyB.GetContactList();
            while (edge) {
                if (edge.other == bodyA) {
                    edge.contact.FlagForFiltering();
                }
                edge = edge.next;
            }
        }
        return j;
    }
    b2World.prototype.DestroyJoint = function (j) {
        var collideConnected = j.m_collideConnected;
        if (j.m_prev) {
            j.m_prev.m_next = j.m_next;
        }
        if (j.m_next) {
            j.m_next.m_prev = j.m_prev;
        }
        if (j == this.m_jointList) {
            this.m_jointList = j.m_next;
        }
        var bodyA = j.m_bodyA;
        var bodyB = j.m_bodyB;
        bodyA.SetAwake(true);
        bodyB.SetAwake(true);
        if (j.m_edgeA.prev) {
            j.m_edgeA.prev.next = j.m_edgeA.next;
        }
        if (j.m_edgeA.next) {
            j.m_edgeA.next.prev = j.m_edgeA.prev;
        }
        if (j.m_edgeA == bodyA.m_jointList) {
            bodyA.m_jointList = j.m_edgeA.next;
        }
        j.m_edgeA.prev = null;
        j.m_edgeA.next = null;
        if (j.m_edgeB.prev) {
            j.m_edgeB.prev.next = j.m_edgeB.next;
        }
        if (j.m_edgeB.next) {
            j.m_edgeB.next.prev = j.m_edgeB.prev;
        }
        if (j.m_edgeB == bodyB.m_jointList) {
            bodyB.m_jointList = j.m_edgeB.next;
        }
        j.m_edgeB.prev = null;
        j.m_edgeB.next = null;
        b2Joint.Destroy(j, null);
        --this.m_jointCount;
        if (collideConnected == false) {
            var edge = bodyB.GetContactList();
            while (edge) {
                if (edge.other == bodyA) {
                    edge.contact.FlagForFiltering();
                }
                edge = edge.next;
            }
        }
    }
    b2World.prototype.AddController = function (c) {
        c.m_next = this.m_controllerList;
        c.m_prev = null;
        this.m_controllerList = c;
        c.m_world = this;
        this.m_controllerCount++;
        return c;
    }
    b2World.prototype.RemoveController = function (c) {
        if (c.m_prev) c.m_prev.m_next = c.m_next;
        if (c.m_next) c.m_next.m_prev = c.m_prev;
        if (this.m_controllerList == c) this.m_controllerList = c.m_next;
        this.m_controllerCount--;
    }
    b2World.prototype.CreateController = function (controller) {
        if (controller.m_world != this) throw new Error("Controller can only be a member of one world");
        controller.m_next = this.m_controllerList;
        controller.m_prev = null;
        if (this.m_controllerList) this.m_controllerList.m_prev = controller;
        this.m_controllerList = controller;
        ++this.m_controllerCount;
        controller.m_world = this;
        return controller;
    }
    b2World.prototype.DestroyController = function (controller) {
        controller.Clear();
        if (controller.m_next) controller.m_next.m_prev = controller.m_prev;
        if (controller.m_prev) controller.m_prev.m_next = controller.m_next;
        if (controller == this.m_controllerList) this.m_controllerList = controller.m_next;
        --this.m_controllerCount;
    }
    b2World.prototype.SetWarmStarting = function (flag) {
        b2World.m_warmStarting = flag;
    }
    b2World.prototype.SetContinuousPhysics = function (flag) {
        b2World.m_continuousPhysics = flag;
    }
    b2World.prototype.GetBodyCount = function () {
        return this.m_bodyCount;
    }
    b2World.prototype.GetJointCount = function () {
        return this.m_jointCount;
    }
    b2World.prototype.GetContactCount = function () {
        return this.m_contactCount;
    }
    b2World.prototype.SetGravity = function (gravity) {
        this.m_gravity = gravity;
    }
    b2World.prototype.GetGravity = function () {
        return this.m_gravity;
    }
    b2World.prototype.GetGroundBody = function () {
        return this.m_groundBody;
    }
    b2World.prototype.Step = function (dt, velocityIterations, positionIterations) {
        if (dt === undefined) dt = 0;
        if (velocityIterations === undefined) velocityIterations = 0;
        if (positionIterations === undefined) positionIterations = 0;
        if (this.m_flags & b2World.e_newFixture) {
            this.m_contactManager.FindNewContacts();
            this.m_flags &= ~b2World.e_newFixture;
        }
        this.m_flags |= b2World.e_locked;
        var step = b2World.s_timestep2;
        step.dt = dt;
        step.velocityIterations = velocityIterations;
        step.positionIterations = positionIterations;
        if (dt > 0.0) {
            step.inv_dt = 1.0 / dt;
        }
        else {
            step.inv_dt = 0.0;
        }
        step.dtRatio = this.m_inv_dt0 * dt;
        step.warmStarting = b2World.m_warmStarting;
        this.m_contactManager.Collide();
        if (step.dt > 0.0) {
            this.Solve(step);
        }
        if (b2World.m_continuousPhysics && step.dt > 0.0) {
            this.SolveTOI(step);
        }
        if (step.dt > 0.0) {
            this.m_inv_dt0 = step.inv_dt;
        }
        this.m_flags &= ~b2World.e_locked;
    }
    b2World.prototype.ClearForces = function () {
        for (var body = this.m_bodyList; body; body = body.m_next) {
            body.m_force.SetZero();
            body.m_torque = 0.0;
        }
    }
    b2World.prototype.DrawDebugData = function () {
        if (this.m_debugDraw == null) {
            return;
        }
        this.m_debugDraw.m_sprite.graphics.clear();
        var flags = this.m_debugDraw.GetFlags();
        var i = 0;
        var b;
        var f;
        var s;
        var j;
        var bp;
        var invQ = new b2Vec2;
        var x1 = new b2Vec2;
        var x2 = new b2Vec2;
        var xf;
        var b1 = new b2AABB();
        var b2 = new b2AABB();
        var vs = [new b2Vec2(), new b2Vec2(), new b2Vec2(), new b2Vec2()];
        var color = new b2Color(0, 0, 0);
        if (flags & b2DebugDraw.e_shapeBit) {
            for (b = this.m_bodyList;
                 b; b = b.m_next) {
                xf = b.m_xf;
                for (f = b.GetFixtureList();
                     f; f = f.m_next) {
                    s = f.GetShape();
                    if (b.IsActive() == false) {
                        color.Set(0.5, 0.5, 0.3);
                        this.DrawShape(s, xf, color);
                    }
                    else if (b.GetType() == b2Body.b2_staticBody) {
                        color.Set(0.5, 0.9, 0.5);
                        this.DrawShape(s, xf, color);
                    }
                    else if (b.GetType() == b2Body.b2_kinematicBody) {
                        color.Set(0.5, 0.5, 0.9);
                        this.DrawShape(s, xf, color);
                    }
                    else if (b.IsAwake() == false) {
                        color.Set(0.6, 0.6, 0.6);
                        this.DrawShape(s, xf, color);
                    }
                    else {
                        color.Set(0.9, 0.7, 0.7);
                        this.DrawShape(s, xf, color);
                    }
                }
            }
        }
        if (flags & b2DebugDraw.e_jointBit) {
            for (j = this.m_jointList;
                 j; j = j.m_next) {
                this.DrawJoint(j);
            }
        }
        if (flags & b2DebugDraw.e_controllerBit) {
            for (var c = this.m_controllerList; c; c = c.m_next) {
                c.Draw(this.m_debugDraw);
            }
        }
        if (flags & b2DebugDraw.e_pairBit) {
            color.Set(0.3, 0.9, 0.9);
            for (var contact = this.m_contactManager.m_contactList; contact; contact = contact.GetNext()) {
                var fixtureA = contact.GetFixtureA();
                var fixtureB = contact.GetFixtureB();
                var cA = fixtureA.GetAABB().GetCenter();
                var cB = fixtureB.GetAABB().GetCenter();
                this.m_debugDraw.DrawSegment(cA, cB, color);
            }
        }
        if (flags & b2DebugDraw.e_aabbBit) {
            bp = this.m_contactManager.m_broadPhase;
            vs = [new b2Vec2(), new b2Vec2(), new b2Vec2(), new b2Vec2()];
            for (b = this.m_bodyList;
                 b; b = b.GetNext()) {
                if (b.IsActive() == false) {
                    continue;
                }
                for (f = b.GetFixtureList();
                     f; f = f.GetNext()) {
                    var aabb = bp.GetFatAABB(f.m_proxy);
                    vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y);
                    vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y);
                    vs[2].Set(aabb.upperBound.x, aabb.upperBound.y);
                    vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y);
                    this.m_debugDraw.DrawPolygon(vs, 4, color);
                }
            }
        }
        if (flags & b2DebugDraw.e_centerOfMassBit) {
            for (b = this.m_bodyList;
                 b; b = b.m_next) {
                xf = b2World.s_xf;
                xf.R = b.m_xf.R;
                xf.position = b.GetWorldCenter();
                this.m_debugDraw.DrawTransform(xf);
            }
        }
    }
    b2World.prototype.QueryAABB = function (callback, aabb) {
        var __this = this;
        var broadPhase = __this.m_contactManager.m_broadPhase;
        function WorldQueryWrapper(proxy) {
            return callback(broadPhase.GetUserData(proxy));
        };
        broadPhase.Query(WorldQueryWrapper, aabb);
    }
    b2World.prototype.QueryShape = function (callback, shape, transform) {
        var __this = this;
        if (transform === undefined) transform = null;
        if (transform == null) {
            transform = new b2Transform();
            transform.SetIdentity();
        }
        var broadPhase = __this.m_contactManager.m_broadPhase;
        function WorldQueryWrapper(proxy) {
            var fixture = (broadPhase.GetUserData(proxy) instanceof b2Fixture ? broadPhase.GetUserData(proxy) : null);
            if (b2Shape.TestOverlap(shape, transform, fixture.GetShape(), fixture.GetBody().GetTransform())) return callback(fixture);
            return true;
        };
        var aabb = new b2AABB();
        shape.ComputeAABB(aabb, transform);
        broadPhase.Query(WorldQueryWrapper, aabb);
    }
    b2World.prototype.QueryPoint = function (callback, p) {
        var __this = this;
        var broadPhase = __this.m_contactManager.m_broadPhase;
        function WorldQueryWrapper(proxy) {
            var fixture = (broadPhase.GetUserData(proxy) instanceof b2Fixture ? broadPhase.GetUserData(proxy) : null);
            if (fixture.TestPoint(p)) return callback(fixture);
            return true;
        };
        var aabb = new b2AABB();
        aabb.lowerBound.Set(p.x - b2Settings.b2_linearSlop, p.y - b2Settings.b2_linearSlop);
        aabb.upperBound.Set(p.x + b2Settings.b2_linearSlop, p.y + b2Settings.b2_linearSlop);
        broadPhase.Query(WorldQueryWrapper, aabb);
    }
    b2World.prototype.RayCast = function (callback, point1, point2) {
        var __this = this;
        var broadPhase = __this.m_contactManager.m_broadPhase;
        var output = new b2RayCastOutput;
        function RayCastWrapper(input, proxy) {
            var userData = broadPhase.GetUserData(proxy);
            var fixture = (userData instanceof b2Fixture ? userData : null);
            var hit = fixture.RayCast(output, input);
            if (hit) {
                var fraction = output.fraction;
                var point = new b2Vec2((1.0 - fraction) * point1.x + fraction * point2.x, (1.0 - fraction) * point1.y + fraction * point2.y);
                return callback(fixture, point, output.normal, fraction);
            }
            return input.maxFraction;
        };
        var input = new b2RayCastInput(point1, point2);
        broadPhase.RayCast(RayCastWrapper, input);
    }
    b2World.prototype.RayCastOne = function (point1, point2) {
        var __this = this;
        var result;
        function RayCastOneWrapper(fixture, point, normal, fraction) {
            if (fraction === undefined) fraction = 0;
            result = fixture;
            return fraction;
        };
        __this.RayCast(RayCastOneWrapper, point1, point2);
        return result;
    }
    b2World.prototype.RayCastAll = function (point1, point2) {
        var __this = this;
        var result = new Vector();
        function RayCastAllWrapper(fixture, point, normal, fraction) {
            if (fraction === undefined) fraction = 0;
            result[result.length] = fixture;
            return 1;
        };
        __this.RayCast(RayCastAllWrapper, point1, point2);
        return result;
    }
    b2World.prototype.GetBodyList = function () {
        return this.m_bodyList;
    }
    b2World.prototype.GetJointList = function () {
        return this.m_jointList;
    }
    b2World.prototype.GetContactList = function () {
        return this.m_contactList;
    }
    b2World.prototype.IsLocked = function () {
        return (this.m_flags & b2World.e_locked) > 0;
    }
    b2World.prototype.Solve = function (step) {
        var b;
        for (var controller = this.m_controllerList; controller; controller = controller.m_next) {
            controller.Step(step);
        }
        var island = this.m_island;
        island.Initialize(this.m_bodyCount, this.m_contactCount, this.m_jointCount, null, this.m_contactManager.m_contactListener, this.m_contactSolver);
        for (b = this.m_bodyList;
             b; b = b.m_next) {
            b.m_flags &= ~b2Body.e_islandFlag;
        }
        for (var c = this.m_contactList; c; c = c.m_next) {
            c.m_flags &= ~b2Contact.e_islandFlag;
        }
        for (var j = this.m_jointList; j; j = j.m_next) {
            j.m_islandFlag = false;
        }
        var stackSize = parseInt(this.m_bodyCount);
        var stack = this.s_stack;
        for (var seed = this.m_bodyList; seed; seed = seed.m_next) {
            if (seed.m_flags & b2Body.e_islandFlag) {
                continue;
            }
            if (seed.IsAwake() == false || seed.IsActive() == false) {
                continue;
            }
            if (seed.GetType() == b2Body.b2_staticBody) {
                continue;
            }
            island.Clear();
            var stackCount = 0;
            stack[stackCount++] = seed;
            seed.m_flags |= b2Body.e_islandFlag;
            while (stackCount > 0) {
                b = stack[--stackCount];
                island.AddBody(b);
                if (b.IsAwake() == false) {
                    b.SetAwake(true);
                }
                if (b.GetType() == b2Body.b2_staticBody) {
                    continue;
                }
                var other;
                for (var ce = b.m_contactList; ce; ce = ce.next) {
                    if (ce.contact.m_flags & b2Contact.e_islandFlag) {
                        continue;
                    }
                    if (ce.contact.IsSensor() == true || ce.contact.IsEnabled() == false || ce.contact.IsTouching() == false) {
                        continue;
                    }
                    island.AddContact(ce.contact);
                    ce.contact.m_flags |= b2Contact.e_islandFlag;
                    other = ce.other;
                    if (other.m_flags & b2Body.e_islandFlag) {
                        continue;
                    }
                    stack[stackCount++] = other;
                    other.m_flags |= b2Body.e_islandFlag;
                }
                for (var jn = b.m_jointList; jn; jn = jn.next) {
                    if (jn.joint.m_islandFlag == true) {
                        continue;
                    }
                    other = jn.other;
                    if (other.IsActive() == false) {
                        continue;
                    }
                    island.AddJoint(jn.joint);
                    jn.joint.m_islandFlag = true;
                    if (other.m_flags & b2Body.e_islandFlag) {
                        continue;
                    }
                    stack[stackCount++] = other;
                    other.m_flags |= b2Body.e_islandFlag;
                }
            }
            island.Solve(step, this.m_gravity, this.m_allowSleep);
            for (var i = 0; i < island.m_bodyCount; ++i) {
                b = island.m_bodies[i];
                if (b.GetType() == b2Body.b2_staticBody) {
                    b.m_flags &= ~b2Body.e_islandFlag;
                }
            }
        }
        for (i = 0;
             i < stack.length; ++i) {
            if (!stack[i]) break;
            stack[i] = null;
        }
        for (b = this.m_bodyList;
             b; b = b.m_next) {
            if (b.IsAwake() == false || b.IsActive() == false) {
                continue;
            }
            if (b.GetType() == b2Body.b2_staticBody) {
                continue;
            }
            b.SynchronizeFixtures();
        }
        this.m_contactManager.FindNewContacts();
    }
    b2World.prototype.SolveTOI = function (step) {
        var b;
        var fA;
        var fB;
        var bA;
        var bB;
        var cEdge;
        var j;
        var island = this.m_island;
        island.Initialize(this.m_bodyCount, b2Settings.b2_maxTOIContactsPerIsland, b2Settings.b2_maxTOIJointsPerIsland, null, this.m_contactManager.m_contactListener, this.m_contactSolver);
        var queue = b2World.s_queue;
        for (b = this.m_bodyList;
             b; b = b.m_next) {
            b.m_flags &= ~b2Body.e_islandFlag;
            b.m_sweep.t0 = 0.0;
        }
        var c;
        for (c = this.m_contactList;
             c; c = c.m_next) {
            c.m_flags &= ~ (b2Contact.e_toiFlag | b2Contact.e_islandFlag);
        }
        for (j = this.m_jointList;
             j; j = j.m_next) {
            j.m_islandFlag = false;
        }
        for (;;) {
            var minContact = null;
            var minTOI = 1.0;
            for (c = this.m_contactList;
                 c; c = c.m_next) {
                if (c.IsSensor() == true || c.IsEnabled() == false || c.IsContinuous() == false) {
                    continue;
                }
                var toi = 1.0;
                if (c.m_flags & b2Contact.e_toiFlag) {
                    toi = c.m_toi;
                }
                else {
                    fA = c.m_fixtureA;
                    fB = c.m_fixtureB;
                    bA = fA.m_body;
                    bB = fB.m_body;
                    if ((bA.GetType() != b2Body.b2_dynamicBody || bA.IsAwake() == false) && (bB.GetType() != b2Body.b2_dynamicBody || bB.IsAwake() == false)) {
                        continue;
                    }
                    var t0 = bA.m_sweep.t0;
                    if (bA.m_sweep.t0 < bB.m_sweep.t0) {
                        t0 = bB.m_sweep.t0;
                        bA.m_sweep.Advance(t0);
                    }
                    else if (bB.m_sweep.t0 < bA.m_sweep.t0) {
                        t0 = bA.m_sweep.t0;
                        bB.m_sweep.Advance(t0);
                    }
                    toi = c.ComputeTOI(bA.m_sweep, bB.m_sweep);
                    b2Settings.b2Assert(0.0 <= toi && toi <= 1.0);
                    if (toi > 0.0 && toi < 1.0) {
                        toi = (1.0 - toi) * t0 + toi;
                        if (toi > 1) toi = 1;
                    }
                    c.m_toi = toi;
                    c.m_flags |= b2Contact.e_toiFlag;
                }
                if (Number.MIN_VALUE < toi && toi < minTOI) {
                    minContact = c;
                    minTOI = toi;
                }
            }
            if (minContact == null || 1.0 - 100.0 * Number.MIN_VALUE < minTOI) {
                break;
            }
            fA = minContact.m_fixtureA;
            fB = minContact.m_fixtureB;
            bA = fA.m_body;
            bB = fB.m_body;
            b2World.s_backupA.Set(bA.m_sweep);
            b2World.s_backupB.Set(bB.m_sweep);
            bA.Advance(minTOI);
            bB.Advance(minTOI);
            minContact.Update(this.m_contactManager.m_contactListener);
            minContact.m_flags &= ~b2Contact.e_toiFlag;
            if (minContact.IsSensor() == true || minContact.IsEnabled() == false) {
                bA.m_sweep.Set(b2World.s_backupA);
                bB.m_sweep.Set(b2World.s_backupB);
                bA.SynchronizeTransform();
                bB.SynchronizeTransform();
                continue;
            }
            if (minContact.IsTouching() == false) {
                continue;
            }
            var seed = bA;
            if (seed.GetType() != b2Body.b2_dynamicBody) {
                seed = bB;
            }
            island.Clear();
            var queueStart = 0;
            var queueSize = 0;
            queue[queueStart + queueSize++] = seed;
            seed.m_flags |= b2Body.e_islandFlag;
            while (queueSize > 0) {
                b = queue[queueStart++];
                --queueSize;
                island.AddBody(b);
                if (b.IsAwake() == false) {
                    b.SetAwake(true);
                }
                if (b.GetType() != b2Body.b2_dynamicBody) {
                    continue;
                }
                for (cEdge = b.m_contactList;
                     cEdge; cEdge = cEdge.next) {
                    if (island.m_contactCount == island.m_contactCapacity) {
                        break;
                    }
                    if (cEdge.contact.m_flags & b2Contact.e_islandFlag) {
                        continue;
                    }
                    if (cEdge.contact.IsSensor() == true || cEdge.contact.IsEnabled() == false || cEdge.contact.IsTouching() == false) {
                        continue;
                    }
                    island.AddContact(cEdge.contact);
                    cEdge.contact.m_flags |= b2Contact.e_islandFlag;
                    var other = cEdge.other;
                    if (other.m_flags & b2Body.e_islandFlag) {
                        continue;
                    }
                    if (other.GetType() != b2Body.b2_staticBody) {
                        other.Advance(minTOI);
                        other.SetAwake(true);
                    }
                    queue[queueStart + queueSize] = other;
                    ++queueSize;
                    other.m_flags |= b2Body.e_islandFlag;
                }
                for (var jEdge = b.m_jointList; jEdge; jEdge = jEdge.next) {
                    if (island.m_jointCount == island.m_jointCapacity) continue;
                    if (jEdge.joint.m_islandFlag == true) continue;
                    other = jEdge.other;
                    if (other.IsActive() == false) {
                        continue;
                    }
                    island.AddJoint(jEdge.joint);
                    jEdge.joint.m_islandFlag = true;
                    if (other.m_flags & b2Body.e_islandFlag) continue;
                    if (other.GetType() != b2Body.b2_staticBody) {
                        other.Advance(minTOI);
                        other.SetAwake(true);
                    }
                    queue[queueStart + queueSize] = other;
                    ++queueSize;
                    other.m_flags |= b2Body.e_islandFlag;
                }
            }
            var subStep = b2World.s_timestep;
            subStep.warmStarting = false;
            subStep.dt = (1.0 - minTOI) * step.dt;
            subStep.inv_dt = 1.0 / subStep.dt;
            subStep.dtRatio = 0.0;
            subStep.velocityIterations = step.velocityIterations;
            subStep.positionIterations = step.positionIterations;
            island.SolveTOI(subStep);
            var i = 0;
            for (i = 0;
                 i < island.m_bodyCount; ++i) {
                b = island.m_bodies[i];
                b.m_flags &= ~b2Body.e_islandFlag;
                if (b.IsAwake() == false) {
                    continue;
                }
                if (b.GetType() != b2Body.b2_dynamicBody) {
                    continue;
                }
                b.SynchronizeFixtures();
                for (cEdge = b.m_contactList;
                     cEdge; cEdge = cEdge.next) {
                    cEdge.contact.m_flags &= ~b2Contact.e_toiFlag;
                }
            }
            for (i = 0;
                 i < island.m_contactCount; ++i) {
                c = island.m_contacts[i];
                c.m_flags &= ~ (b2Contact.e_toiFlag | b2Contact.e_islandFlag);
            }
            for (i = 0;
                 i < island.m_jointCount; ++i) {
                j = island.m_joints[i];
                j.m_islandFlag = false;
            }
            this.m_contactManager.FindNewContacts();
        }
    }
    b2World.prototype.DrawJoint = function (joint) {
        var b1 = joint.GetBodyA();
        var b2 = joint.GetBodyB();
        var xf1 = b1.m_xf;
        var xf2 = b2.m_xf;
        var x1 = xf1.position;
        var x2 = xf2.position;
        var p1 = joint.GetAnchorA();
        var p2 = joint.GetAnchorB();
        var color = b2World.s_jointColor;
        switch (joint.m_type) {
            case b2Joint.e_distanceJoint:
                this.m_debugDraw.DrawSegment(p1, p2, color);
                break;
            case b2Joint.e_pulleyJoint:
            {
                var pulley = ((joint instanceof b2PulleyJoint ? joint : null));
                var s1 = pulley.GetGroundAnchorA();
                var s2 = pulley.GetGroundAnchorB();
                this.m_debugDraw.DrawSegment(s1, p1, color);
                this.m_debugDraw.DrawSegment(s2, p2, color);
                this.m_debugDraw.DrawSegment(s1, s2, color);
            }
                break;
            case b2Joint.e_mouseJoint:
                this.m_debugDraw.DrawSegment(p1, p2, color);
                break;
            default:
                if (b1 != this.m_groundBody) this.m_debugDraw.DrawSegment(x1, p1, color);
                this.m_debugDraw.DrawSegment(p1, p2, color);
                if (b2 != this.m_groundBody) this.m_debugDraw.DrawSegment(x2, p2, color);
        }
    }
    b2World.prototype.DrawShape = function (shape, xf, color) {
        switch (shape.m_type) {
            case b2Shape.e_circleShape:
            {
                var circle = ((shape instanceof b2CircleShape ? shape : null));
                var center = b2Math.MulX(xf, circle.m_p);
                var radius = circle.m_radius;
                var axis = xf.R.col1;
                this.m_debugDraw.DrawSolidCircle(center, radius, axis, color);
            }
                break;
            case b2Shape.e_polygonShape:
            {
                var i = 0;
                var poly = ((shape instanceof b2PolygonShape ? shape : null));
                var vertexCount = parseInt(poly.GetVertexCount());
                var localVertices = poly.GetVertices();
                var vertices = new Vector(vertexCount);
                for (i = 0;
                     i < vertexCount; ++i) {
                    vertices[i] = b2Math.MulX(xf, localVertices[i]);
                }
                this.m_debugDraw.DrawSolidPolygon(vertices, vertexCount, color);
            }
                break;
            case b2Shape.e_edgeShape:
            {
                var edge = (shape instanceof b2EdgeShape ? shape : null);
                this.m_debugDraw.DrawSegment(b2Math.MulX(xf, edge.GetVertex1()), b2Math.MulX(xf, edge.GetVertex2()), color);
            }
                break;
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.b2World.s_timestep2 = new b2TimeStep();
        Box2D.Dynamics.b2World.s_xf = new b2Transform();
        Box2D.Dynamics.b2World.s_backupA = new b2Sweep();
        Box2D.Dynamics.b2World.s_backupB = new b2Sweep();
        Box2D.Dynamics.b2World.s_timestep = new b2TimeStep();
        Box2D.Dynamics.b2World.s_queue = new Vector();
        Box2D.Dynamics.b2World.s_jointColor = new b2Color(0.5, 0.8, 0.8);
        Box2D.Dynamics.b2World.e_newFixture = 0x0001;
        Box2D.Dynamics.b2World.e_locked = 0x0002;
    });
})();
(function () {
    var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
        b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
        b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
        b2MassData = Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
        b2Shape = Box2D.Collision.Shapes.b2Shape,
        b2CircleContact = Box2D.Dynamics.Contacts.b2CircleContact,
        b2Contact = Box2D.Dynamics.Contacts.b2Contact,
        b2ContactConstraint = Box2D.Dynamics.Contacts.b2ContactConstraint,
        b2ContactConstraintPoint = Box2D.Dynamics.Contacts.b2ContactConstraintPoint,
        b2ContactEdge = Box2D.Dynamics.Contacts.b2ContactEdge,
        b2ContactFactory = Box2D.Dynamics.Contacts.b2ContactFactory,
        b2ContactRegister = Box2D.Dynamics.Contacts.b2ContactRegister,
        b2ContactResult = Box2D.Dynamics.Contacts.b2ContactResult,
        b2ContactSolver = Box2D.Dynamics.Contacts.b2ContactSolver,
        b2EdgeAndCircleContact = Box2D.Dynamics.Contacts.b2EdgeAndCircleContact,
        b2NullContact = Box2D.Dynamics.Contacts.b2NullContact,
        b2PolyAndCircleContact = Box2D.Dynamics.Contacts.b2PolyAndCircleContact,
        b2PolyAndEdgeContact = Box2D.Dynamics.Contacts.b2PolyAndEdgeContact,
        b2PolygonContact = Box2D.Dynamics.Contacts.b2PolygonContact,
        b2PositionSolverManifold = Box2D.Dynamics.Contacts.b2PositionSolverManifold,
        b2Body = Box2D.Dynamics.b2Body,
        b2BodyDef = Box2D.Dynamics.b2BodyDef,
        b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
        b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
        b2ContactListener = Box2D.Dynamics.b2ContactListener,
        b2ContactManager = Box2D.Dynamics.b2ContactManager,
        b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
        b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
        b2FilterData = Box2D.Dynamics.b2FilterData,
        b2Fixture = Box2D.Dynamics.b2Fixture,
        b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
        b2Island = Box2D.Dynamics.b2Island,
        b2TimeStep = Box2D.Dynamics.b2TimeStep,
        b2World = Box2D.Dynamics.b2World,
        b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3,
        b2AABB = Box2D.Collision.b2AABB,
        b2Bound = Box2D.Collision.b2Bound,
        b2BoundValues = Box2D.Collision.b2BoundValues,
        b2Collision = Box2D.Collision.b2Collision,
        b2ContactID = Box2D.Collision.b2ContactID,
        b2ContactPoint = Box2D.Collision.b2ContactPoint,
        b2Distance = Box2D.Collision.b2Distance,
        b2DistanceInput = Box2D.Collision.b2DistanceInput,
        b2DistanceOutput = Box2D.Collision.b2DistanceOutput,
        b2DistanceProxy = Box2D.Collision.b2DistanceProxy,
        b2DynamicTree = Box2D.Collision.b2DynamicTree,
        b2DynamicTreeBroadPhase = Box2D.Collision.b2DynamicTreeBroadPhase,
        b2DynamicTreeNode = Box2D.Collision.b2DynamicTreeNode,
        b2DynamicTreePair = Box2D.Collision.b2DynamicTreePair,
        b2Manifold = Box2D.Collision.b2Manifold,
        b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint,
        b2Point = Box2D.Collision.b2Point,
        b2RayCastInput = Box2D.Collision.b2RayCastInput,
        b2RayCastOutput = Box2D.Collision.b2RayCastOutput,
        b2Segment = Box2D.Collision.b2Segment,
        b2SeparationFunction = Box2D.Collision.b2SeparationFunction,
        b2Simplex = Box2D.Collision.b2Simplex,
        b2SimplexCache = Box2D.Collision.b2SimplexCache,
        b2SimplexVertex = Box2D.Collision.b2SimplexVertex,
        b2TimeOfImpact = Box2D.Collision.b2TimeOfImpact,
        b2TOIInput = Box2D.Collision.b2TOIInput,
        b2WorldManifold = Box2D.Collision.b2WorldManifold,
        ClipVertex = Box2D.Collision.ClipVertex,
        Features = Box2D.Collision.Features,
        IBroadPhase = Box2D.Collision.IBroadPhase;
    Box2D.inherit(b2CircleContact, Box2D.Dynamics.Contacts.b2Contact);
    b2CircleContact.prototype.__super = Box2D.Dynamics.Contacts.b2Contact.prototype;
    b2CircleContact.b2CircleContact = function () {
        Box2D.Dynamics.Contacts.b2Contact.b2Contact.apply(this, arguments);
    };
    b2CircleContact.Create = function (allocator) {
        return new b2CircleContact();
    }
    b2CircleContact.Destroy = function (contact, allocator) {}
    b2CircleContact.prototype.Reset = function (fixtureA, fixtureB) {
        this.__super.Reset.call(this, fixtureA, fixtureB);
    }
    b2CircleContact.prototype.Evaluate = function () {
        var bA = this.m_fixtureA.GetBody();
        var bB = this.m_fixtureB.GetBody();
        b2Collision.CollideCircles(this.m_manifold, (this.m_fixtureA.GetShape() instanceof b2CircleShape ? this.m_fixtureA.GetShape() : null), bA.m_xf, (this.m_fixtureB.GetShape() instanceof b2CircleShape ? this.m_fixtureB.GetShape() : null), bB.m_xf);
    }
    b2Contact.b2Contact = function () {
        this.m_nodeA = new b2ContactEdge();
        this.m_nodeB = new b2ContactEdge();
        this.m_manifold = new b2Manifold();
        this.m_oldManifold = new b2Manifold();
    };
    b2Contact.prototype.GetManifold = function () {
        return this.m_manifold;
    }
    b2Contact.prototype.GetWorldManifold = function (worldManifold) {
        var bodyA = this.m_fixtureA.GetBody();
        var bodyB = this.m_fixtureB.GetBody();
        var shapeA = this.m_fixtureA.GetShape();
        var shapeB = this.m_fixtureB.GetShape();
        worldManifold.Initialize(this.m_manifold, bodyA.GetTransform(), shapeA.m_radius, bodyB.GetTransform(), shapeB.m_radius);
    }
    b2Contact.prototype.IsTouching = function () {
        return (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag;
    }
    b2Contact.prototype.IsContinuous = function () {
        return (this.m_flags & b2Contact.e_continuousFlag) == b2Contact.e_continuousFlag;
    }
    b2Contact.prototype.SetSensor = function (sensor) {
        if (sensor) {
            this.m_flags |= b2Contact.e_sensorFlag;
        }
        else {
            this.m_flags &= ~b2Contact.e_sensorFlag;
        }
    }
    b2Contact.prototype.IsSensor = function () {
        return (this.m_flags & b2Contact.e_sensorFlag) == b2Contact.e_sensorFlag;
    }
    b2Contact.prototype.SetEnabled = function (flag) {
        if (flag) {
            this.m_flags |= b2Contact.e_enabledFlag;
        }
        else {
            this.m_flags &= ~b2Contact.e_enabledFlag;
        }
    }
    b2Contact.prototype.IsEnabled = function () {
        return (this.m_flags & b2Contact.e_enabledFlag) == b2Contact.e_enabledFlag;
    }
    b2Contact.prototype.GetNext = function () {
        return this.m_next;
    }
    b2Contact.prototype.GetFixtureA = function () {
        return this.m_fixtureA;
    }
    b2Contact.prototype.GetFixtureB = function () {
        return this.m_fixtureB;
    }
    b2Contact.prototype.FlagForFiltering = function () {
        this.m_flags |= b2Contact.e_filterFlag;
    }
    b2Contact.prototype.b2Contact = function () {}
    b2Contact.prototype.Reset = function (fixtureA, fixtureB) {
        if (fixtureA === undefined) fixtureA = null;
        if (fixtureB === undefined) fixtureB = null;
        this.m_flags = b2Contact.e_enabledFlag;
        if (!fixtureA || !fixtureB) {
            this.m_fixtureA = null;
            this.m_fixtureB = null;
            return;
        }
        if (fixtureA.IsSensor() || fixtureB.IsSensor()) {
            this.m_flags |= b2Contact.e_sensorFlag;
        }
        var bodyA = fixtureA.GetBody();
        var bodyB = fixtureB.GetBody();
        if (bodyA.GetType() != b2Body.b2_dynamicBody || bodyA.IsBullet() || bodyB.GetType() != b2Body.b2_dynamicBody || bodyB.IsBullet()) {
            this.m_flags |= b2Contact.e_continuousFlag;
        }
        this.m_fixtureA = fixtureA;
        this.m_fixtureB = fixtureB;
        this.m_manifold.m_pointCount = 0;
        this.m_prev = null;
        this.m_next = null;
        this.m_nodeA.contact = null;
        this.m_nodeA.prev = null;
        this.m_nodeA.next = null;
        this.m_nodeA.other = null;
        this.m_nodeB.contact = null;
        this.m_nodeB.prev = null;
        this.m_nodeB.next = null;
        this.m_nodeB.other = null;
    }
    b2Contact.prototype.Update = function (listener) {
        var tManifold = this.m_oldManifold;
        this.m_oldManifold = this.m_manifold;
        this.m_manifold = tManifold;
        this.m_flags |= b2Contact.e_enabledFlag;
        var touching = false;
        var wasTouching = (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag;
        var bodyA = this.m_fixtureA.m_body;
        var bodyB = this.m_fixtureB.m_body;
        var aabbOverlap = this.m_fixtureA.m_aabb.TestOverlap(this.m_fixtureB.m_aabb);
        if (this.m_flags & b2Contact.e_sensorFlag) {
            if (aabbOverlap) {
                var shapeA = this.m_fixtureA.GetShape();
                var shapeB = this.m_fixtureB.GetShape();
                var xfA = bodyA.GetTransform();
                var xfB = bodyB.GetTransform();
                touching = b2Shape.TestOverlap(shapeA, xfA, shapeB, xfB);
            }
            this.m_manifold.m_pointCount = 0;
        }
        else {
            if (bodyA.GetType() != b2Body.b2_dynamicBody || bodyA.IsBullet() || bodyB.GetType() != b2Body.b2_dynamicBody || bodyB.IsBullet()) {
                this.m_flags |= b2Contact.e_continuousFlag;
            }
            else {
                this.m_flags &= ~b2Contact.e_continuousFlag;
            }
            if (aabbOverlap) {
                this.Evaluate();
                touching = this.m_manifold.m_pointCount > 0;
                for (var i = 0; i < this.m_manifold.m_pointCount; ++i) {
                    var mp2 = this.m_manifold.m_points[i];
                    mp2.m_normalImpulse = 0.0;
                    mp2.m_tangentImpulse = 0.0;
                    var id2 = mp2.m_id;
                    for (var j = 0; j < this.m_oldManifold.m_pointCount; ++j) {
                        var mp1 = this.m_oldManifold.m_points[j];
                        if (mp1.m_id.key == id2.key) {
                            mp2.m_normalImpulse = mp1.m_normalImpulse;
                            mp2.m_tangentImpulse = mp1.m_tangentImpulse;
                            break;
                        }
                    }
                }
            }
            else {
                this.m_manifold.m_pointCount = 0;
            }
            if (touching != wasTouching) {
                bodyA.SetAwake(true);
                bodyB.SetAwake(true);
            }
        }
        if (touching) {
            this.m_flags |= b2Contact.e_touchingFlag;
        }
        else {
            this.m_flags &= ~b2Contact.e_touchingFlag;
        }
        if (wasTouching == false && touching == true) {
            listener.BeginContact(this);
        }
        if (wasTouching == true && touching == false) {
            listener.EndContact(this);
        }
        if ((this.m_flags & b2Contact.e_sensorFlag) == 0) {
            listener.PreSolve(this, this.m_oldManifold);
        }
    }
    b2Contact.prototype.Evaluate = function () {}
    b2Contact.prototype.ComputeTOI = function (sweepA, sweepB) {
        b2Contact.s_input.proxyA.Set(this.m_fixtureA.GetShape());
        b2Contact.s_input.proxyB.Set(this.m_fixtureB.GetShape());
        b2Contact.s_input.sweepA = sweepA;
        b2Contact.s_input.sweepB = sweepB;
        b2Contact.s_input.tolerance = b2Settings.b2_linearSlop;
        return b2TimeOfImpact.TimeOfImpact(b2Contact.s_input);
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.Contacts.b2Contact.e_sensorFlag = 0x0001;
        Box2D.Dynamics.Contacts.b2Contact.e_continuousFlag = 0x0002;
        Box2D.Dynamics.Contacts.b2Contact.e_islandFlag = 0x0004;
        Box2D.Dynamics.Contacts.b2Contact.e_toiFlag = 0x0008;
        Box2D.Dynamics.Contacts.b2Contact.e_touchingFlag = 0x0010;
        Box2D.Dynamics.Contacts.b2Contact.e_enabledFlag = 0x0020;
        Box2D.Dynamics.Contacts.b2Contact.e_filterFlag = 0x0040;
        Box2D.Dynamics.Contacts.b2Contact.s_input = new b2TOIInput();
    });
    b2ContactConstraint.b2ContactConstraint = function () {
        this.localPlaneNormal = new b2Vec2();
        this.localPoint = new b2Vec2();
        this.normal = new b2Vec2();
        this.normalMass = new b2Mat22();
        this.K = new b2Mat22();
    };
    b2ContactConstraint.prototype.b2ContactConstraint = function () {
        this.points = new Vector(b2Settings.b2_maxManifoldPoints);
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++) {
            this.points[i] = new b2ContactConstraintPoint();
        }
    }
    b2ContactConstraintPoint.b2ContactConstraintPoint = function () {
        this.localPoint = new b2Vec2();
        this.rA = new b2Vec2();
        this.rB = new b2Vec2();
    };
    b2ContactEdge.b2ContactEdge = function () {};
    b2ContactFactory.b2ContactFactory = function () {};
    b2ContactFactory.prototype.b2ContactFactory = function (allocator) {
        this.m_allocator = allocator;
        this.InitializeRegisters();
    }
    b2ContactFactory.prototype.AddType = function (createFcn, destroyFcn, type1, type2) {
        if (type1 === undefined) type1 = 0;
        if (type2 === undefined) type2 = 0;
        this.m_registers[type1][type2].createFcn = createFcn;
        this.m_registers[type1][type2].destroyFcn = destroyFcn;
        this.m_registers[type1][type2].primary = true;
        if (type1 != type2) {
            this.m_registers[type2][type1].createFcn = createFcn;
            this.m_registers[type2][type1].destroyFcn = destroyFcn;
            this.m_registers[type2][type1].primary = false;
        }
    }
    b2ContactFactory.prototype.InitializeRegisters = function () {
        this.m_registers = new Vector(b2Shape.e_shapeTypeCount);
        for (var i = 0; i < b2Shape.e_shapeTypeCount; i++) {
            this.m_registers[i] = new Vector(b2Shape.e_shapeTypeCount);
            for (var j = 0; j < b2Shape.e_shapeTypeCount; j++) {
                this.m_registers[i][j] = new b2ContactRegister();
            }
        }
        this.AddType(b2CircleContact.Create, b2CircleContact.Destroy, b2Shape.e_circleShape, b2Shape.e_circleShape);
        this.AddType(b2PolyAndCircleContact.Create, b2PolyAndCircleContact.Destroy, b2Shape.e_polygonShape, b2Shape.e_circleShape);
        this.AddType(b2PolygonContact.Create, b2PolygonContact.Destroy, b2Shape.e_polygonShape, b2Shape.e_polygonShape);
        this.AddType(b2EdgeAndCircleContact.Create, b2EdgeAndCircleContact.Destroy, b2Shape.e_edgeShape, b2Shape.e_circleShape);
        this.AddType(b2PolyAndEdgeContact.Create, b2PolyAndEdgeContact.Destroy, b2Shape.e_polygonShape, b2Shape.e_edgeShape);
    }
    b2ContactFactory.prototype.Create = function (fixtureA, fixtureB) {
        var type1 = parseInt(fixtureA.GetType());
        var type2 = parseInt(fixtureB.GetType());
        var reg = this.m_registers[type1][type2];
        var c;
        if (reg.pool) {
            c = reg.pool;
            reg.pool = c.m_next;
            reg.poolCount--;
            c.Reset(fixtureA, fixtureB);
            return c;
        }
        var createFcn = reg.createFcn;
        if (createFcn != null) {
            if (reg.primary) {
                c = createFcn(this.m_allocator);
                c.Reset(fixtureA, fixtureB);
                return c;
            }
            else {
                c = createFcn(this.m_allocator);
                c.Reset(fixtureB, fixtureA);
                return c;
            }
        }
        else {
            return null;
        }
    }
    b2ContactFactory.prototype.Destroy = function (contact) {
        if (contact.m_manifold.m_pointCount > 0) {
            contact.m_fixtureA.m_body.SetAwake(true);
            contact.m_fixtureB.m_body.SetAwake(true);
        }
        var type1 = parseInt(contact.m_fixtureA.GetType());
        var type2 = parseInt(contact.m_fixtureB.GetType());
        var reg = this.m_registers[type1][type2];
        if (true) {
            reg.poolCount++;
            contact.m_next = reg.pool;
            reg.pool = contact;
        }
        var destroyFcn = reg.destroyFcn;
        destroyFcn(contact, this.m_allocator);
    }
    b2ContactRegister.b2ContactRegister = function () {};
    b2ContactResult.b2ContactResult = function () {
        this.position = new b2Vec2();
        this.normal = new b2Vec2();
        this.id = new b2ContactID();
    };
    b2ContactSolver.b2ContactSolver = function () {
        this.m_step = new b2TimeStep();
        this.m_constraints = new Vector();
    };
    b2ContactSolver.prototype.b2ContactSolver = function () {}
    b2ContactSolver.prototype.Initialize = function (step, contacts, contactCount, allocator) {
        if (contactCount === undefined) contactCount = 0;
        var contact;
        this.m_step.Set(step);
        this.m_allocator = allocator;
        var i = 0;
        var tVec;
        var tMat;
        this.m_constraintCount = contactCount;
        while (this.m_constraints.length < this.m_constraintCount) {
            this.m_constraints[this.m_constraints.length] = new b2ContactConstraint();
        }
        for (i = 0;
             i < contactCount; ++i) {
            contact = contacts[i];
            var fixtureA = contact.m_fixtureA;
            var fixtureB = contact.m_fixtureB;
            var shapeA = fixtureA.m_shape;
            var shapeB = fixtureB.m_shape;
            var radiusA = shapeA.m_radius;
            var radiusB = shapeB.m_radius;
            var bodyA = fixtureA.m_body;
            var bodyB = fixtureB.m_body;
            var manifold = contact.GetManifold();
            var friction = b2Settings.b2MixFriction(fixtureA.GetFriction(), fixtureB.GetFriction());
            var restitution = b2Settings.b2MixRestitution(fixtureA.GetRestitution(), fixtureB.GetRestitution());
            var vAX = bodyA.m_linearVelocity.x;
            var vAY = bodyA.m_linearVelocity.y;
            var vBX = bodyB.m_linearVelocity.x;
            var vBY = bodyB.m_linearVelocity.y;
            var wA = bodyA.m_angularVelocity;
            var wB = bodyB.m_angularVelocity;
            b2Settings.b2Assert(manifold.m_pointCount > 0);
            b2ContactSolver.s_worldManifold.Initialize(manifold, bodyA.m_xf, radiusA, bodyB.m_xf, radiusB);
            var normalX = b2ContactSolver.s_worldManifold.m_normal.x;
            var normalY = b2ContactSolver.s_worldManifold.m_normal.y;
            var cc = this.m_constraints[i];
            cc.bodyA = bodyA;
            cc.bodyB = bodyB;
            cc.manifold = manifold;
            cc.normal.x = normalX;
            cc.normal.y = normalY;
            cc.pointCount = manifold.m_pointCount;
            cc.friction = friction;
            cc.restitution = restitution;
            cc.localPlaneNormal.x = manifold.m_localPlaneNormal.x;
            cc.localPlaneNormal.y = manifold.m_localPlaneNormal.y;
            cc.localPoint.x = manifold.m_localPoint.x;
            cc.localPoint.y = manifold.m_localPoint.y;
            cc.radius = radiusA + radiusB;
            cc.type = manifold.m_type;
            for (var k = 0; k < cc.pointCount; ++k) {
                var cp = manifold.m_points[k];
                var ccp = cc.points[k];
                ccp.normalImpulse = cp.m_normalImpulse;
                ccp.tangentImpulse = cp.m_tangentImpulse;
                ccp.localPoint.SetV(cp.m_localPoint);
                var rAX = ccp.rA.x = b2ContactSolver.s_worldManifold.m_points[k].x - bodyA.m_sweep.c.x;
                var rAY = ccp.rA.y = b2ContactSolver.s_worldManifold.m_points[k].y - bodyA.m_sweep.c.y;
                var rBX = ccp.rB.x = b2ContactSolver.s_worldManifold.m_points[k].x - bodyB.m_sweep.c.x;
                var rBY = ccp.rB.y = b2ContactSolver.s_worldManifold.m_points[k].y - bodyB.m_sweep.c.y;
                var rnA = rAX * normalY - rAY * normalX;
                var rnB = rBX * normalY - rBY * normalX;
                rnA *= rnA;
                rnB *= rnB;
                var kNormal = bodyA.m_invMass + bodyB.m_invMass + bodyA.m_invI * rnA + bodyB.m_invI * rnB;
                ccp.normalMass = 1.0 / kNormal;
                var kEqualized = bodyA.m_mass * bodyA.m_invMass + bodyB.m_mass * bodyB.m_invMass;
                kEqualized += bodyA.m_mass * bodyA.m_invI * rnA + bodyB.m_mass * bodyB.m_invI * rnB;
                ccp.equalizedMass = 1.0 / kEqualized;
                var tangentX = normalY;
                var tangentY = (-normalX);
                var rtA = rAX * tangentY - rAY * tangentX;
                var rtB = rBX * tangentY - rBY * tangentX;
                rtA *= rtA;
                rtB *= rtB;
                var kTangent = bodyA.m_invMass + bodyB.m_invMass + bodyA.m_invI * rtA + bodyB.m_invI * rtB;
                ccp.tangentMass = 1.0 / kTangent;
                ccp.velocityBias = 0.0;
                var tX = vBX + ((-wB * rBY)) - vAX - ((-wA * rAY));
                var tY = vBY + (wB * rBX) - vAY - (wA * rAX);
                var vRel = cc.normal.x * tX + cc.normal.y * tY;
                if (vRel < (-b2Settings.b2_velocityThreshold)) {
                    ccp.velocityBias += (-cc.restitution * vRel);
                }
            }
            if (cc.pointCount == 2) {
                var ccp1 = cc.points[0];
                var ccp2 = cc.points[1];
                var invMassA = bodyA.m_invMass;
                var invIA = bodyA.m_invI;
                var invMassB = bodyB.m_invMass;
                var invIB = bodyB.m_invI;
                var rn1A = ccp1.rA.x * normalY - ccp1.rA.y * normalX;
                var rn1B = ccp1.rB.x * normalY - ccp1.rB.y * normalX;
                var rn2A = ccp2.rA.x * normalY - ccp2.rA.y * normalX;
                var rn2B = ccp2.rB.x * normalY - ccp2.rB.y * normalX;
                var k11 = invMassA + invMassB + invIA * rn1A * rn1A + invIB * rn1B * rn1B;
                var k22 = invMassA + invMassB + invIA * rn2A * rn2A + invIB * rn2B * rn2B;
                var k12 = invMassA + invMassB + invIA * rn1A * rn2A + invIB * rn1B * rn2B;
                var k_maxConditionNumber = 100.0;
                if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) {
                    cc.K.col1.Set(k11, k12);
                    cc.K.col2.Set(k12, k22);
                    cc.K.GetInverse(cc.normalMass);
                }
                else {
                    cc.pointCount = 1;
                }
            }
        }
    }
    b2ContactSolver.prototype.InitVelocityConstraints = function (step) {
        var tVec;
        var tVec2;
        var tMat;
        for (var i = 0; i < this.m_constraintCount; ++i) {
            var c = this.m_constraints[i];
            var bodyA = c.bodyA;
            var bodyB = c.bodyB;
            var invMassA = bodyA.m_invMass;
            var invIA = bodyA.m_invI;
            var invMassB = bodyB.m_invMass;
            var invIB = bodyB.m_invI;
            var normalX = c.normal.x;
            var normalY = c.normal.y;
            var tangentX = normalY;
            var tangentY = (-normalX);
            var tX = 0;
            var j = 0;
            var tCount = 0;
            if (step.warmStarting) {
                tCount = c.pointCount;
                for (j = 0;
                     j < tCount; ++j) {
                    var ccp = c.points[j];
                    ccp.normalImpulse *= step.dtRatio;
                    ccp.tangentImpulse *= step.dtRatio;
                    var PX = ccp.normalImpulse * normalX + ccp.tangentImpulse * tangentX;
                    var PY = ccp.normalImpulse * normalY + ccp.tangentImpulse * tangentY;
                    bodyA.m_angularVelocity -= invIA * (ccp.rA.x * PY - ccp.rA.y * PX);
                    bodyA.m_linearVelocity.x -= invMassA * PX;
                    bodyA.m_linearVelocity.y -= invMassA * PY;
                    bodyB.m_angularVelocity += invIB * (ccp.rB.x * PY - ccp.rB.y * PX);
                    bodyB.m_linearVelocity.x += invMassB * PX;
                    bodyB.m_linearVelocity.y += invMassB * PY;
                }
            }
            else {
                tCount = c.pointCount;
                for (j = 0;
                     j < tCount; ++j) {
                    var ccp2 = c.points[j];
                    ccp2.normalImpulse = 0.0;
                    ccp2.tangentImpulse = 0.0;
                }
            }
        }
    }
    b2ContactSolver.prototype.SolveVelocityConstraints = function () {
        var j = 0;
        var ccp;
        var rAX = 0;
        var rAY = 0;
        var rBX = 0;
        var rBY = 0;
        var dvX = 0;
        var dvY = 0;
        var vn = 0;
        var vt = 0;
        var lambda = 0;
        var maxFriction = 0;
        var newImpulse = 0;
        var PX = 0;
        var PY = 0;
        var dX = 0;
        var dY = 0;
        var P1X = 0;
        var P1Y = 0;
        var P2X = 0;
        var P2Y = 0;
        var tMat;
        var tVec;
        for (var i = 0; i < this.m_constraintCount; ++i) {
            var c = this.m_constraints[i];
            var bodyA = c.bodyA;
            var bodyB = c.bodyB;
            var wA = bodyA.m_angularVelocity;
            var wB = bodyB.m_angularVelocity;
            var vA = bodyA.m_linearVelocity;
            var vB = bodyB.m_linearVelocity;
            var invMassA = bodyA.m_invMass;
            var invIA = bodyA.m_invI;
            var invMassB = bodyB.m_invMass;
            var invIB = bodyB.m_invI;
            var normalX = c.normal.x;
            var normalY = c.normal.y;
            var tangentX = normalY;
            var tangentY = (-normalX);
            var friction = c.friction;
            var tX = 0;
            for (j = 0;
                 j < c.pointCount; j++) {
                ccp = c.points[j];
                dvX = vB.x - wB * ccp.rB.y - vA.x + wA * ccp.rA.y;
                dvY = vB.y + wB * ccp.rB.x - vA.y - wA * ccp.rA.x;
                vt = dvX * tangentX + dvY * tangentY;
                lambda = ccp.tangentMass * (-vt);
                maxFriction = friction * ccp.normalImpulse;
                newImpulse = b2Math.Clamp(ccp.tangentImpulse + lambda, (-maxFriction), maxFriction);
                lambda = newImpulse - ccp.tangentImpulse;
                PX = lambda * tangentX;
                PY = lambda * tangentY;
                vA.x -= invMassA * PX;
                vA.y -= invMassA * PY;
                wA -= invIA * (ccp.rA.x * PY - ccp.rA.y * PX);
                vB.x += invMassB * PX;
                vB.y += invMassB * PY;
                wB += invIB * (ccp.rB.x * PY - ccp.rB.y * PX);
                ccp.tangentImpulse = newImpulse;
            }
            var tCount = parseInt(c.pointCount);
            if (c.pointCount == 1) {
                ccp = c.points[0];
                dvX = vB.x + ((-wB * ccp.rB.y)) - vA.x - ((-wA * ccp.rA.y));
                dvY = vB.y + (wB * ccp.rB.x) - vA.y - (wA * ccp.rA.x);
                vn = dvX * normalX + dvY * normalY;
                lambda = (-ccp.normalMass * (vn - ccp.velocityBias));
                newImpulse = ccp.normalImpulse + lambda;
                newImpulse = newImpulse > 0 ? newImpulse : 0.0;
                lambda = newImpulse - ccp.normalImpulse;
                PX = lambda * normalX;
                PY = lambda * normalY;
                vA.x -= invMassA * PX;
                vA.y -= invMassA * PY;
                wA -= invIA * (ccp.rA.x * PY - ccp.rA.y * PX);
                vB.x += invMassB * PX;
                vB.y += invMassB * PY;
                wB += invIB * (ccp.rB.x * PY - ccp.rB.y * PX);
                ccp.normalImpulse = newImpulse;
            }
            else {
                var cp1 = c.points[0];
                var cp2 = c.points[1];
                var aX = cp1.normalImpulse;
                var aY = cp2.normalImpulse;
                var dv1X = vB.x - wB * cp1.rB.y - vA.x + wA * cp1.rA.y;
                var dv1Y = vB.y + wB * cp1.rB.x - vA.y - wA * cp1.rA.x;
                var dv2X = vB.x - wB * cp2.rB.y - vA.x + wA * cp2.rA.y;
                var dv2Y = vB.y + wB * cp2.rB.x - vA.y - wA * cp2.rA.x;
                var vn1 = dv1X * normalX + dv1Y * normalY;
                var vn2 = dv2X * normalX + dv2Y * normalY;
                var bX = vn1 - cp1.velocityBias;
                var bY = vn2 - cp2.velocityBias;
                tMat = c.K;
                bX -= tMat.col1.x * aX + tMat.col2.x * aY;
                bY -= tMat.col1.y * aX + tMat.col2.y * aY;
                var k_errorTol = 0.001;
                for (;;) {
                    tMat = c.normalMass;
                    var xX = (-(tMat.col1.x * bX + tMat.col2.x * bY));
                    var xY = (-(tMat.col1.y * bX + tMat.col2.y * bY));
                    if (xX >= 0.0 && xY >= 0.0) {
                        dX = xX - aX;
                        dY = xY - aY;
                        P1X = dX * normalX;
                        P1Y = dX * normalY;
                        P2X = dY * normalX;
                        P2Y = dY * normalY;
                        vA.x -= invMassA * (P1X + P2X);
                        vA.y -= invMassA * (P1Y + P2Y);
                        wA -= invIA * (cp1.rA.x * P1Y - cp1.rA.y * P1X + cp2.rA.x * P2Y - cp2.rA.y * P2X);
                        vB.x += invMassB * (P1X + P2X);
                        vB.y += invMassB * (P1Y + P2Y);
                        wB += invIB * (cp1.rB.x * P1Y - cp1.rB.y * P1X + cp2.rB.x * P2Y - cp2.rB.y * P2X);
                        cp1.normalImpulse = xX;
                        cp2.normalImpulse = xY;
                        break;
                    }
                    xX = (-cp1.normalMass * bX);
                    xY = 0.0;
                    vn1 = 0.0;
                    vn2 = c.K.col1.y * xX + bY;
                    if (xX >= 0.0 && vn2 >= 0.0) {
                        dX = xX - aX;
                        dY = xY - aY;
                        P1X = dX * normalX;
                        P1Y = dX * normalY;
                        P2X = dY * normalX;
                        P2Y = dY * normalY;
                        vA.x -= invMassA * (P1X + P2X);
                        vA.y -= invMassA * (P1Y + P2Y);
                        wA -= invIA * (cp1.rA.x * P1Y - cp1.rA.y * P1X + cp2.rA.x * P2Y - cp2.rA.y * P2X);
                        vB.x += invMassB * (P1X + P2X);
                        vB.y += invMassB * (P1Y + P2Y);
                        wB += invIB * (cp1.rB.x * P1Y - cp1.rB.y * P1X + cp2.rB.x * P2Y - cp2.rB.y * P2X);
                        cp1.normalImpulse = xX;
                        cp2.normalImpulse = xY;
                        break;
                    }
                    xX = 0.0;
                    xY = (-cp2.normalMass * bY);
                    vn1 = c.K.col2.x * xY + bX;
                    vn2 = 0.0;
                    if (xY >= 0.0 && vn1 >= 0.0) {
                        dX = xX - aX;
                        dY = xY - aY;
                        P1X = dX * normalX;
                        P1Y = dX * normalY;
                        P2X = dY * normalX;
                        P2Y = dY * normalY;
                        vA.x -= invMassA * (P1X + P2X);
                        vA.y -= invMassA * (P1Y + P2Y);
                        wA -= invIA * (cp1.rA.x * P1Y - cp1.rA.y * P1X + cp2.rA.x * P2Y - cp2.rA.y * P2X);
                        vB.x += invMassB * (P1X + P2X);
                        vB.y += invMassB * (P1Y + P2Y);
                        wB += invIB * (cp1.rB.x * P1Y - cp1.rB.y * P1X + cp2.rB.x * P2Y - cp2.rB.y * P2X);
                        cp1.normalImpulse = xX;
                        cp2.normalImpulse = xY;
                        break;
                    }
                    xX = 0.0;
                    xY = 0.0;
                    vn1 = bX;
                    vn2 = bY;
                    if (vn1 >= 0.0 && vn2 >= 0.0) {
                        dX = xX - aX;
                        dY = xY - aY;
                        P1X = dX * normalX;
                        P1Y = dX * normalY;
                        P2X = dY * normalX;
                        P2Y = dY * normalY;
                        vA.x -= invMassA * (P1X + P2X);
                        vA.y -= invMassA * (P1Y + P2Y);
                        wA -= invIA * (cp1.rA.x * P1Y - cp1.rA.y * P1X + cp2.rA.x * P2Y - cp2.rA.y * P2X);
                        vB.x += invMassB * (P1X + P2X);
                        vB.y += invMassB * (P1Y + P2Y);
                        wB += invIB * (cp1.rB.x * P1Y - cp1.rB.y * P1X + cp2.rB.x * P2Y - cp2.rB.y * P2X);
                        cp1.normalImpulse = xX;
                        cp2.normalImpulse = xY;
                        break;
                    }
                    break;
                }
            }
            bodyA.m_angularVelocity = wA;
            bodyB.m_angularVelocity = wB;
        }
    }
    b2ContactSolver.prototype.FinalizeVelocityConstraints = function () {
        for (var i = 0; i < this.m_constraintCount; ++i) {
            var c = this.m_constraints[i];
            var m = c.manifold;
            for (var j = 0; j < c.pointCount; ++j) {
                var point1 = m.m_points[j];
                var point2 = c.points[j];
                point1.m_normalImpulse = point2.normalImpulse;
                point1.m_tangentImpulse = point2.tangentImpulse;
            }
        }
    }
    b2ContactSolver.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var minSeparation = 0.0;
        for (var i = 0; i < this.m_constraintCount; i++) {
            var c = this.m_constraints[i];
            var bodyA = c.bodyA;
            var bodyB = c.bodyB;
            var invMassA = bodyA.m_mass * bodyA.m_invMass;
            var invIA = bodyA.m_mass * bodyA.m_invI;
            var invMassB = bodyB.m_mass * bodyB.m_invMass;
            var invIB = bodyB.m_mass * bodyB.m_invI;
            b2ContactSolver.s_psm.Initialize(c);
            var normal = b2ContactSolver.s_psm.m_normal;
            for (var j = 0; j < c.pointCount; j++) {
                var ccp = c.points[j];
                var point = b2ContactSolver.s_psm.m_points[j];
                var separation = b2ContactSolver.s_psm.m_separations[j];
                var rAX = point.x - bodyA.m_sweep.c.x;
                var rAY = point.y - bodyA.m_sweep.c.y;
                var rBX = point.x - bodyB.m_sweep.c.x;
                var rBY = point.y - bodyB.m_sweep.c.y;
                minSeparation = minSeparation < separation ? minSeparation : separation;
                var C = b2Math.Clamp(baumgarte * (separation + b2Settings.b2_linearSlop), (-b2Settings.b2_maxLinearCorrection), 0.0);
                var impulse = (-ccp.equalizedMass * C);
                var PX = impulse * normal.x;
                var PY = impulse * normal.y;bodyA.m_sweep.c.x -= invMassA * PX;
                bodyA.m_sweep.c.y -= invMassA * PY;
                bodyA.m_sweep.a -= invIA * (rAX * PY - rAY * PX);
                bodyA.SynchronizeTransform();
                bodyB.m_sweep.c.x += invMassB * PX;
                bodyB.m_sweep.c.y += invMassB * PY;
                bodyB.m_sweep.a += invIB * (rBX * PY - rBY * PX);
                bodyB.SynchronizeTransform();
            }
        }
        return minSeparation > (-1.5 * b2Settings.b2_linearSlop);
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.Contacts.b2ContactSolver.s_worldManifold = new b2WorldManifold();
        Box2D.Dynamics.Contacts.b2ContactSolver.s_psm = new b2PositionSolverManifold();
    });
    Box2D.inherit(b2EdgeAndCircleContact, Box2D.Dynamics.Contacts.b2Contact);
    b2EdgeAndCircleContact.prototype.__super = Box2D.Dynamics.Contacts.b2Contact.prototype;
    b2EdgeAndCircleContact.b2EdgeAndCircleContact = function () {
        Box2D.Dynamics.Contacts.b2Contact.b2Contact.apply(this, arguments);
    };
    b2EdgeAndCircleContact.Create = function (allocator) {
        return new b2EdgeAndCircleContact();
    }
    b2EdgeAndCircleContact.Destroy = function (contact, allocator) {}
    b2EdgeAndCircleContact.prototype.Reset = function (fixtureA, fixtureB) {
        this.__super.Reset.call(this, fixtureA, fixtureB);
    }
    b2EdgeAndCircleContact.prototype.Evaluate = function () {
        var bA = this.m_fixtureA.GetBody();
        var bB = this.m_fixtureB.GetBody();
        this.b2CollideEdgeAndCircle(this.m_manifold, (this.m_fixtureA.GetShape() instanceof b2EdgeShape ? this.m_fixtureA.GetShape() : null), bA.m_xf, (this.m_fixtureB.GetShape() instanceof b2CircleShape ? this.m_fixtureB.GetShape() : null), bB.m_xf);
    }
    b2EdgeAndCircleContact.prototype.b2CollideEdgeAndCircle = function (manifold, edge, xf1, circle, xf2) {}
    Box2D.inherit(b2NullContact, Box2D.Dynamics.Contacts.b2Contact);
    b2NullContact.prototype.__super = Box2D.Dynamics.Contacts.b2Contact.prototype;
    b2NullContact.b2NullContact = function () {
        Box2D.Dynamics.Contacts.b2Contact.b2Contact.apply(this, arguments);
    };
    b2NullContact.prototype.b2NullContact = function () {
        this.__super.b2Contact.call(this);
    }
    b2NullContact.prototype.Evaluate = function () {}
    Box2D.inherit(b2PolyAndCircleContact, Box2D.Dynamics.Contacts.b2Contact);
    b2PolyAndCircleContact.prototype.__super = Box2D.Dynamics.Contacts.b2Contact.prototype;
    b2PolyAndCircleContact.b2PolyAndCircleContact = function () {
        Box2D.Dynamics.Contacts.b2Contact.b2Contact.apply(this, arguments);
    };
    b2PolyAndCircleContact.Create = function (allocator) {
        return new b2PolyAndCircleContact();
    }
    b2PolyAndCircleContact.Destroy = function (contact, allocator) {}
    b2PolyAndCircleContact.prototype.Reset = function (fixtureA, fixtureB) {
        this.__super.Reset.call(this, fixtureA, fixtureB);
        b2Settings.b2Assert(fixtureA.GetType() == b2Shape.e_polygonShape);
        b2Settings.b2Assert(fixtureB.GetType() == b2Shape.e_circleShape);
    }
    b2PolyAndCircleContact.prototype.Evaluate = function () {
        var bA = this.m_fixtureA.m_body;
        var bB = this.m_fixtureB.m_body;
        b2Collision.CollidePolygonAndCircle(this.m_manifold, (this.m_fixtureA.GetShape() instanceof b2PolygonShape ? this.m_fixtureA.GetShape() : null), bA.m_xf, (this.m_fixtureB.GetShape() instanceof b2CircleShape ? this.m_fixtureB.GetShape() : null), bB.m_xf);
    }
    Box2D.inherit(b2PolyAndEdgeContact, Box2D.Dynamics.Contacts.b2Contact);
    b2PolyAndEdgeContact.prototype.__super = Box2D.Dynamics.Contacts.b2Contact.prototype;
    b2PolyAndEdgeContact.b2PolyAndEdgeContact = function () {
        Box2D.Dynamics.Contacts.b2Contact.b2Contact.apply(this, arguments);
    };
    b2PolyAndEdgeContact.Create = function (allocator) {
        return new b2PolyAndEdgeContact();
    }
    b2PolyAndEdgeContact.Destroy = function (contact, allocator) {}
    b2PolyAndEdgeContact.prototype.Reset = function (fixtureA, fixtureB) {
        this.__super.Reset.call(this, fixtureA, fixtureB);
        b2Settings.b2Assert(fixtureA.GetType() == b2Shape.e_polygonShape);
        b2Settings.b2Assert(fixtureB.GetType() == b2Shape.e_edgeShape);
    }
    b2PolyAndEdgeContact.prototype.Evaluate = function () {
        var bA = this.m_fixtureA.GetBody();
        var bB = this.m_fixtureB.GetBody();
        this.b2CollidePolyAndEdge(this.m_manifold, (this.m_fixtureA.GetShape() instanceof b2PolygonShape ? this.m_fixtureA.GetShape() : null), bA.m_xf, (this.m_fixtureB.GetShape() instanceof b2EdgeShape ? this.m_fixtureB.GetShape() : null), bB.m_xf);
    }
    b2PolyAndEdgeContact.prototype.b2CollidePolyAndEdge = function (manifold, polygon, xf1, edge, xf2) {}
    Box2D.inherit(b2PolygonContact, Box2D.Dynamics.Contacts.b2Contact);
    b2PolygonContact.prototype.__super = Box2D.Dynamics.Contacts.b2Contact.prototype;
    b2PolygonContact.b2PolygonContact = function () {
        Box2D.Dynamics.Contacts.b2Contact.b2Contact.apply(this, arguments);
    };
    b2PolygonContact.Create = function (allocator) {
        return new b2PolygonContact();
    }
    b2PolygonContact.Destroy = function (contact, allocator) {}
    b2PolygonContact.prototype.Reset = function (fixtureA, fixtureB) {
        this.__super.Reset.call(this, fixtureA, fixtureB);
    }
    b2PolygonContact.prototype.Evaluate = function () {
        var bA = this.m_fixtureA.GetBody();
        var bB = this.m_fixtureB.GetBody();
        b2Collision.CollidePolygons(this.m_manifold, (this.m_fixtureA.GetShape() instanceof b2PolygonShape ? this.m_fixtureA.GetShape() : null), bA.m_xf, (this.m_fixtureB.GetShape() instanceof b2PolygonShape ? this.m_fixtureB.GetShape() : null), bB.m_xf);
    }
    b2PositionSolverManifold.b2PositionSolverManifold = function () {};
    b2PositionSolverManifold.prototype.b2PositionSolverManifold = function () {
        this.m_normal = new b2Vec2();
        this.m_separations = new Vector_a2j_Number(b2Settings.b2_maxManifoldPoints);
        this.m_points = new Vector(b2Settings.b2_maxManifoldPoints);
        for (var i = 0; i < b2Settings.b2_maxManifoldPoints; i++) {
            this.m_points[i] = new b2Vec2();
        }
    }
    b2PositionSolverManifold.prototype.Initialize = function (cc) {
        b2Settings.b2Assert(cc.pointCount > 0);
        var i = 0;
        var clipPointX = 0;
        var clipPointY = 0;
        var tMat;
        var tVec;
        var planePointX = 0;
        var planePointY = 0;
        switch (cc.type) {
            case b2Manifold.e_circles:
            {
                tMat = cc.bodyA.m_xf.R;
                tVec = cc.localPoint;
                var pointAX = cc.bodyA.m_xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                var pointAY = cc.bodyA.m_xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                tMat = cc.bodyB.m_xf.R;
                tVec = cc.points[0].localPoint;
                var pointBX = cc.bodyB.m_xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                var pointBY = cc.bodyB.m_xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                var dX = pointBX - pointAX;
                var dY = pointBY - pointAY;
                var d2 = dX * dX + dY * dY;
                if (d2 > Number.MIN_VALUE * Number.MIN_VALUE) {
                    var d = Math.sqrt(d2);
                    this.m_normal.x = dX / d;
                    this.m_normal.y = dY / d;
                }
                else {
                    this.m_normal.x = 1.0;
                    this.m_normal.y = 0.0;
                }
                this.m_points[0].x = 0.5 * (pointAX + pointBX);
                this.m_points[0].y = 0.5 * (pointAY + pointBY);
                this.m_separations[0] = dX * this.m_normal.x + dY * this.m_normal.y - cc.radius;
            }
                break;
            case b2Manifold.e_faceA:
            {
                tMat = cc.bodyA.m_xf.R;
                tVec = cc.localPlaneNormal;
                this.m_normal.x = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                this.m_normal.y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tMat = cc.bodyA.m_xf.R;
                tVec = cc.localPoint;
                planePointX = cc.bodyA.m_xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                planePointY = cc.bodyA.m_xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                tMat = cc.bodyB.m_xf.R;
                for (i = 0;
                     i < cc.pointCount; ++i) {
                    tVec = cc.points[i].localPoint;
                    clipPointX = cc.bodyB.m_xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                    clipPointY = cc.bodyB.m_xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                    this.m_separations[i] = (clipPointX - planePointX) * this.m_normal.x + (clipPointY - planePointY) * this.m_normal.y - cc.radius;
                    this.m_points[i].x = clipPointX;
                    this.m_points[i].y = clipPointY;
                }
            }
                break;
            case b2Manifold.e_faceB:
            {
                tMat = cc.bodyB.m_xf.R;
                tVec = cc.localPlaneNormal;
                this.m_normal.x = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
                this.m_normal.y = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
                tMat = cc.bodyB.m_xf.R;
                tVec = cc.localPoint;
                planePointX = cc.bodyB.m_xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                planePointY = cc.bodyB.m_xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                tMat = cc.bodyA.m_xf.R;
                for (i = 0;
                     i < cc.pointCount; ++i) {
                    tVec = cc.points[i].localPoint;
                    clipPointX = cc.bodyA.m_xf.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
                    clipPointY = cc.bodyA.m_xf.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
                    this.m_separations[i] = (clipPointX - planePointX) * this.m_normal.x + (clipPointY - planePointY) * this.m_normal.y - cc.radius;
                    this.m_points[i].Set(clipPointX, clipPointY);
                }
                this.m_normal.x *= (-1);
                this.m_normal.y *= (-1);
            }
                break;
        }
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.Contacts.b2PositionSolverManifold.circlePointA = new b2Vec2();
        Box2D.Dynamics.Contacts.b2PositionSolverManifold.circlePointB = new b2Vec2();
    });
})();
(function () {
    var b2Body = Box2D.Dynamics.b2Body,
        b2BodyDef = Box2D.Dynamics.b2BodyDef,
        b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
        b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
        b2ContactListener = Box2D.Dynamics.b2ContactListener,
        b2ContactManager = Box2D.Dynamics.b2ContactManager,
        b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
        b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
        b2FilterData = Box2D.Dynamics.b2FilterData,
        b2Fixture = Box2D.Dynamics.b2Fixture,
        b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
        b2Island = Box2D.Dynamics.b2Island,
        b2TimeStep = Box2D.Dynamics.b2TimeStep,
        b2World = Box2D.Dynamics.b2World,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3,
        b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
        b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
        b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
        b2MassData = Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
        b2Shape = Box2D.Collision.Shapes.b2Shape,
        b2BuoyancyController = Box2D.Dynamics.Controllers.b2BuoyancyController,
        b2ConstantAccelController = Box2D.Dynamics.Controllers.b2ConstantAccelController,
        b2ConstantForceController = Box2D.Dynamics.Controllers.b2ConstantForceController,
        b2Controller = Box2D.Dynamics.Controllers.b2Controller,
        b2ControllerEdge = Box2D.Dynamics.Controllers.b2ControllerEdge,
        b2GravityController = Box2D.Dynamics.Controllers.b2GravityController,
        b2TensorDampingController = Box2D.Dynamics.Controllers.b2TensorDampingController;
    Box2D.inherit(b2BuoyancyController, Box2D.Dynamics.Controllers.b2Controller);
    b2BuoyancyController.prototype.__super = Box2D.Dynamics.Controllers.b2Controller.prototype;
    b2BuoyancyController.b2BuoyancyController = function () {
        Box2D.Dynamics.Controllers.b2Controller.b2Controller.apply(this, arguments);
        this.normal = new b2Vec2(0, (-1));
        this.offset = 0;
        this.density = 0;
        this.velocity = new b2Vec2(0, 0);
        this.linearDrag = 2;
        this.angularDrag = 1;
        this.useDensity = false;
        this.useWorldGravity = true;
        this.gravity = null;
    };
    b2BuoyancyController.prototype.Step = function (step) {
        if (!this.m_bodyList) return;
        if (this.useWorldGravity) {
            this.gravity = this.GetWorld().GetGravity().Copy();
        }
        for (var i = this.m_bodyList; i; i = i.nextBody) {
            var body = i.body;
            if (body.IsAwake() == false) {
                continue;
            }
            var areac = new b2Vec2();
            var massc = new b2Vec2();
            var area = 0.0;
            var mass = 0.0;
            for (var fixture = body.GetFixtureList(); fixture; fixture = fixture.GetNext()) {
                var sc = new b2Vec2();
                var sarea = fixture.GetShape().ComputeSubmergedArea(this.normal, this.offset, body.GetTransform(), sc);
                area += sarea;
                areac.x += sarea * sc.x;
                areac.y += sarea * sc.y;
                var shapeDensity = 0;
                if (this.useDensity) {
                    shapeDensity = 1;
                }
                else {
                    shapeDensity = 1;
                }
                mass += sarea * shapeDensity;
                massc.x += sarea * sc.x * shapeDensity;
                massc.y += sarea * sc.y * shapeDensity;
            }
            areac.x /= area;
            areac.y /= area;
            massc.x /= mass;
            massc.y /= mass;
            if (area < Number.MIN_VALUE) continue;
            var buoyancyForce = this.gravity.GetNegative();
            buoyancyForce.Multiply(this.density * area);
            body.ApplyForce(buoyancyForce, massc);
            var dragForce = body.GetLinearVelocityFromWorldPoint(areac);
            dragForce.Subtract(this.velocity);
            dragForce.Multiply((-this.linearDrag * area));
            body.ApplyForce(dragForce, areac);
            body.ApplyTorque((-body.GetInertia() / body.GetMass() * area * body.GetAngularVelocity() * this.angularDrag));
        }
    }
    b2BuoyancyController.prototype.Draw = function (debugDraw) {
        var r = 1000;
        var p1 = new b2Vec2();
        var p2 = new b2Vec2();
        p1.x = this.normal.x * this.offset + this.normal.y * r;
        p1.y = this.normal.y * this.offset - this.normal.x * r;
        p2.x = this.normal.x * this.offset - this.normal.y * r;
        p2.y = this.normal.y * this.offset + this.normal.x * r;
        var color = new b2Color(0, 0, 1);
        debugDraw.DrawSegment(p1, p2, color);
    }
    Box2D.inherit(b2ConstantAccelController, Box2D.Dynamics.Controllers.b2Controller);
    b2ConstantAccelController.prototype.__super = Box2D.Dynamics.Controllers.b2Controller.prototype;
    b2ConstantAccelController.b2ConstantAccelController = function () {
        Box2D.Dynamics.Controllers.b2Controller.b2Controller.apply(this, arguments);
        this.A = new b2Vec2(0, 0);
    };
    b2ConstantAccelController.prototype.Step = function (step) {
        var smallA = new b2Vec2(this.A.x * step.dt, this.A.y * step.dt);
        for (var i = this.m_bodyList; i; i = i.nextBody) {
            var body = i.body;
            if (!body.IsAwake()) continue;
            body.SetLinearVelocity(new b2Vec2(body.GetLinearVelocity().x + smallA.x, body.GetLinearVelocity().y + smallA.y));
        }
    }
    Box2D.inherit(b2ConstantForceController, Box2D.Dynamics.Controllers.b2Controller);
    b2ConstantForceController.prototype.__super = Box2D.Dynamics.Controllers.b2Controller.prototype;
    b2ConstantForceController.b2ConstantForceController = function () {
        Box2D.Dynamics.Controllers.b2Controller.b2Controller.apply(this, arguments);
        this.F = new b2Vec2(0, 0);
    };
    b2ConstantForceController.prototype.Step = function (step) {
        for (var i = this.m_bodyList; i; i = i.nextBody) {
            var body = i.body;
            if (!body.IsAwake()) continue;
            body.ApplyForce(this.F, body.GetWorldCenter());
        }
    }
    b2Controller.b2Controller = function () {};
    b2Controller.prototype.Step = function (step) {}
    b2Controller.prototype.Draw = function (debugDraw) {}
    b2Controller.prototype.AddBody = function (body) {
        var edge = new b2ControllerEdge();
        edge.controller = this;
        edge.body = body;
        edge.nextBody = this.m_bodyList;
        edge.prevBody = null;
        this.m_bodyList = edge;
        if (edge.nextBody) edge.nextBody.prevBody = edge;
        this.m_bodyCount++;
        edge.nextController = body.m_controllerList;
        edge.prevController = null;
        body.m_controllerList = edge;
        if (edge.nextController) edge.nextController.prevController = edge;
        body.m_controllerCount++;
    }
    b2Controller.prototype.RemoveBody = function (body) {
        var edge = body.m_controllerList;
        while (edge && edge.controller != this)
            edge = edge.nextController;
        if (edge.prevBody) edge.prevBody.nextBody = edge.nextBody;
        if (edge.nextBody) edge.nextBody.prevBody = edge.prevBody;
        if (edge.nextController) edge.nextController.prevController = edge.prevController;
        if (edge.prevController) edge.prevController.nextController = edge.nextController;
        if (this.m_bodyList == edge) this.m_bodyList = edge.nextBody;
        if (body.m_controllerList == edge) body.m_controllerList = edge.nextController;
        body.m_controllerCount--;
        this.m_bodyCount--;
    }
    b2Controller.prototype.Clear = function () {
        while (this.m_bodyList)
            this.RemoveBody(this.m_bodyList.body);
    }
    b2Controller.prototype.GetNext = function () {
        return this.m_next;
    }
    b2Controller.prototype.GetWorld = function () {
        return this.m_world;
    }
    b2Controller.prototype.GetBodyList = function () {
        return this.m_bodyList;
    }
    b2ControllerEdge.b2ControllerEdge = function () {};
    Box2D.inherit(b2GravityController, Box2D.Dynamics.Controllers.b2Controller);
    b2GravityController.prototype.__super = Box2D.Dynamics.Controllers.b2Controller.prototype;
    b2GravityController.b2GravityController = function () {
        Box2D.Dynamics.Controllers.b2Controller.b2Controller.apply(this, arguments);
        this.G = 1;
        this.invSqr = true;
    };
    b2GravityController.prototype.Step = function (step) {
        var i = null;
        var body1 = null;
        var p1 = null;
        var mass1 = 0;
        var j = null;
        var body2 = null;
        var p2 = null;
        var dx = 0;
        var dy = 0;
        var r2 = 0;
        var f = null;
        if (this.invSqr) {
            for (i = this.m_bodyList;
                 i; i = i.nextBody) {
                body1 = i.body;
                p1 = body1.GetWorldCenter();
                mass1 = body1.GetMass();
                for (j = this.m_bodyList;
                     j != i; j = j.nextBody) {
                    body2 = j.body;
                    p2 = body2.GetWorldCenter();
                    dx = p2.x - p1.x;
                    dy = p2.y - p1.y;
                    r2 = dx * dx + dy * dy;
                    if (r2 < Number.MIN_VALUE) continue;
                    f = new b2Vec2(dx, dy);
                    f.Multiply(this.G / r2 / Math.sqrt(r2) * mass1 * body2.GetMass());
                    if (body1.IsAwake()) body1.ApplyForce(f, p1);
                    f.Multiply((-1));
                    if (body2.IsAwake()) body2.ApplyForce(f, p2);
                }
            }
        }
        else {
            for (i = this.m_bodyList;
                 i; i = i.nextBody) {
                body1 = i.body;
                p1 = body1.GetWorldCenter();
                mass1 = body1.GetMass();
                for (j = this.m_bodyList;
                     j != i; j = j.nextBody) {
                    body2 = j.body;
                    p2 = body2.GetWorldCenter();
                    dx = p2.x - p1.x;
                    dy = p2.y - p1.y;
                    r2 = dx * dx + dy * dy;
                    if (r2 < Number.MIN_VALUE) continue;
                    f = new b2Vec2(dx, dy);
                    f.Multiply(this.G / r2 * mass1 * body2.GetMass());
                    if (body1.IsAwake()) body1.ApplyForce(f, p1);
                    f.Multiply((-1));
                    if (body2.IsAwake()) body2.ApplyForce(f, p2);
                }
            }
        }
    }
    Box2D.inherit(b2TensorDampingController, Box2D.Dynamics.Controllers.b2Controller);
    b2TensorDampingController.prototype.__super = Box2D.Dynamics.Controllers.b2Controller.prototype;
    b2TensorDampingController.b2TensorDampingController = function () {
        Box2D.Dynamics.Controllers.b2Controller.b2Controller.apply(this, arguments);
        this.T = new b2Mat22();
        this.maxTimestep = 0;
    };
    b2TensorDampingController.prototype.SetAxisAligned = function (xDamping, yDamping) {
        if (xDamping === undefined) xDamping = 0;
        if (yDamping === undefined) yDamping = 0;
        this.T.col1.x = (-xDamping);
        this.T.col1.y = 0;
        this.T.col2.x = 0;
        this.T.col2.y = (-yDamping);
        if (xDamping > 0 || yDamping > 0) {
            this.maxTimestep = 1 / Math.max(xDamping, yDamping);
        }
        else {
            this.maxTimestep = 0;
        }
    }
    b2TensorDampingController.prototype.Step = function (step) {
        var timestep = step.dt;
        if (timestep <= Number.MIN_VALUE) return;
        if (timestep > this.maxTimestep && this.maxTimestep > 0) timestep = this.maxTimestep;
        for (var i = this.m_bodyList; i; i = i.nextBody) {
            var body = i.body;
            if (!body.IsAwake()) {
                continue;
            }
            var damping = body.GetWorldVector(b2Math.MulMV(this.T, body.GetLocalVector(body.GetLinearVelocity())));
            body.SetLinearVelocity(new b2Vec2(body.GetLinearVelocity().x + damping.x * timestep, body.GetLinearVelocity().y + damping.y * timestep));
        }
    }
})();
(function () {
    var b2Color = Box2D.Common.b2Color,
        b2internal = Box2D.Common.b2internal,
        b2Settings = Box2D.Common.b2Settings,
        b2Mat22 = Box2D.Common.Math.b2Mat22,
        b2Mat33 = Box2D.Common.Math.b2Mat33,
        b2Math = Box2D.Common.Math.b2Math,
        b2Sweep = Box2D.Common.Math.b2Sweep,
        b2Transform = Box2D.Common.Math.b2Transform,
        b2Vec2 = Box2D.Common.Math.b2Vec2,
        b2Vec3 = Box2D.Common.Math.b2Vec3,
        b2DistanceJoint = Box2D.Dynamics.Joints.b2DistanceJoint,
        b2DistanceJointDef = Box2D.Dynamics.Joints.b2DistanceJointDef,
        b2FrictionJoint = Box2D.Dynamics.Joints.b2FrictionJoint,
        b2FrictionJointDef = Box2D.Dynamics.Joints.b2FrictionJointDef,
        b2GearJoint = Box2D.Dynamics.Joints.b2GearJoint,
        b2GearJointDef = Box2D.Dynamics.Joints.b2GearJointDef,
        b2Jacobian = Box2D.Dynamics.Joints.b2Jacobian,
        b2Joint = Box2D.Dynamics.Joints.b2Joint,
        b2JointDef = Box2D.Dynamics.Joints.b2JointDef,
        b2JointEdge = Box2D.Dynamics.Joints.b2JointEdge,
        b2LineJoint = Box2D.Dynamics.Joints.b2LineJoint,
        b2LineJointDef = Box2D.Dynamics.Joints.b2LineJointDef,
        b2MouseJoint = Box2D.Dynamics.Joints.b2MouseJoint,
        b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef,
        b2PrismaticJoint = Box2D.Dynamics.Joints.b2PrismaticJoint,
        b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef,
        b2PulleyJoint = Box2D.Dynamics.Joints.b2PulleyJoint,
        b2PulleyJointDef = Box2D.Dynamics.Joints.b2PulleyJointDef,
        b2RevoluteJoint = Box2D.Dynamics.Joints.b2RevoluteJoint,
        b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef,
        b2WeldJoint = Box2D.Dynamics.Joints.b2WeldJoint,
        b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef,
        b2Body = Box2D.Dynamics.b2Body,
        b2BodyDef = Box2D.Dynamics.b2BodyDef,
        b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
        b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
        b2ContactListener = Box2D.Dynamics.b2ContactListener,
        b2ContactManager = Box2D.Dynamics.b2ContactManager,
        b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
        b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
        b2FilterData = Box2D.Dynamics.b2FilterData,
        b2Fixture = Box2D.Dynamics.b2Fixture,
        b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
        b2Island = Box2D.Dynamics.b2Island,
        b2TimeStep = Box2D.Dynamics.b2TimeStep,
        b2World = Box2D.Dynamics.b2World;
    Box2D.inherit(b2DistanceJoint, Box2D.Dynamics.Joints.b2Joint);
    b2DistanceJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2DistanceJoint.b2DistanceJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_localAnchor1 = new b2Vec2();
        this.m_localAnchor2 = new b2Vec2();
        this.m_u = new b2Vec2();
    };
    b2DistanceJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
    }
    b2DistanceJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
    }
    b2DistanceJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_impulse * this.m_u.x, inv_dt * this.m_impulse * this.m_u.y);
    }
    b2DistanceJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return 0.0;
    }
    b2DistanceJoint.prototype.GetLength = function () {
        return this.m_length;
    }
    b2DistanceJoint.prototype.SetLength = function (length) {
        if (length === undefined) length = 0;
        this.m_length = length;
    }
    b2DistanceJoint.prototype.GetFrequency = function () {
        return this.m_frequencyHz;
    }
    b2DistanceJoint.prototype.SetFrequency = function (hz) {
        if (hz === undefined) hz = 0;
        this.m_frequencyHz = hz;
    }
    b2DistanceJoint.prototype.GetDampingRatio = function () {
        return this.m_dampingRatio;
    }
    b2DistanceJoint.prototype.SetDampingRatio = function (ratio) {
        if (ratio === undefined) ratio = 0;
        this.m_dampingRatio = ratio;
    }
    b2DistanceJoint.prototype.b2DistanceJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        var tMat;
        var tX = 0;
        var tY = 0;
        this.m_localAnchor1.SetV(def.localAnchorA);
        this.m_localAnchor2.SetV(def.localAnchorB);
        this.m_length = def.length;
        this.m_frequencyHz = def.frequencyHz;
        this.m_dampingRatio = def.dampingRatio;
        this.m_impulse = 0.0;
        this.m_gamma = 0.0;
        this.m_bias = 0.0;
    }
    b2DistanceJoint.prototype.InitVelocityConstraints = function (step) {
        var tMat;
        var tX = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        this.m_u.x = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
        this.m_u.y = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
        var length = Math.sqrt(this.m_u.x * this.m_u.x + this.m_u.y * this.m_u.y);
        if (length > b2Settings.b2_linearSlop) {
            this.m_u.Multiply(1.0 / length);
        }
        else {
            this.m_u.SetZero();
        }
        var cr1u = (r1X * this.m_u.y - r1Y * this.m_u.x);
        var cr2u = (r2X * this.m_u.y - r2Y * this.m_u.x);
        var invMass = bA.m_invMass + bA.m_invI * cr1u * cr1u + bB.m_invMass + bB.m_invI * cr2u * cr2u;
        this.m_mass = invMass != 0.0 ? 1.0 / invMass : 0.0;
        if (this.m_frequencyHz > 0.0) {
            var C = length - this.m_length;
            var omega = 2.0 * Math.PI * this.m_frequencyHz;
            var d = 2.0 * this.m_mass * this.m_dampingRatio * omega;
            var k = this.m_mass * omega * omega;
            this.m_gamma = step.dt * (d + step.dt * k);
            this.m_gamma = this.m_gamma != 0.0 ? 1 / this.m_gamma : 0.0;
            this.m_bias = C * step.dt * k * this.m_gamma;
            this.m_mass = invMass + this.m_gamma;
            this.m_mass = this.m_mass != 0.0 ? 1.0 / this.m_mass : 0.0;
        }
        if (step.warmStarting) {
            this.m_impulse *= step.dtRatio;
            var PX = this.m_impulse * this.m_u.x;
            var PY = this.m_impulse * this.m_u.y;
            bA.m_linearVelocity.x -= bA.m_invMass * PX;
            bA.m_linearVelocity.y -= bA.m_invMass * PY;
            bA.m_angularVelocity -= bA.m_invI * (r1X * PY - r1Y * PX);
            bB.m_linearVelocity.x += bB.m_invMass * PX;
            bB.m_linearVelocity.y += bB.m_invMass * PY;
            bB.m_angularVelocity += bB.m_invI * (r2X * PY - r2Y * PX);
        }
        else {
            this.m_impulse = 0.0;
        }
    }
    b2DistanceJoint.prototype.SolveVelocityConstraints = function (step) {
        var tMat;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var v1X = bA.m_linearVelocity.x + ((-bA.m_angularVelocity * r1Y));
        var v1Y = bA.m_linearVelocity.y + (bA.m_angularVelocity * r1X);
        var v2X = bB.m_linearVelocity.x + ((-bB.m_angularVelocity * r2Y));
        var v2Y = bB.m_linearVelocity.y + (bB.m_angularVelocity * r2X);
        var Cdot = (this.m_u.x * (v2X - v1X) + this.m_u.y * (v2Y - v1Y));
        var impulse = (-this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse));
        this.m_impulse += impulse;
        var PX = impulse * this.m_u.x;
        var PY = impulse * this.m_u.y;
        bA.m_linearVelocity.x -= bA.m_invMass * PX;
        bA.m_linearVelocity.y -= bA.m_invMass * PY;
        bA.m_angularVelocity -= bA.m_invI * (r1X * PY - r1Y * PX);
        bB.m_linearVelocity.x += bB.m_invMass * PX;
        bB.m_linearVelocity.y += bB.m_invMass * PY;
        bB.m_angularVelocity += bB.m_invI * (r2X * PY - r2Y * PX);
    }
    b2DistanceJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var tMat;
        if (this.m_frequencyHz > 0.0) {
            return true;
        }
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var dX = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
        var dY = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
        var length = Math.sqrt(dX * dX + dY * dY);
        dX /= length;
        dY /= length;
        var C = length - this.m_length;
        C = b2Math.Clamp(C, (-b2Settings.b2_maxLinearCorrection), b2Settings.b2_maxLinearCorrection);
        var impulse = (-this.m_mass * C);
        this.m_u.Set(dX, dY);
        var PX = impulse * this.m_u.x;
        var PY = impulse * this.m_u.y;
        bA.m_sweep.c.x -= bA.m_invMass * PX;
        bA.m_sweep.c.y -= bA.m_invMass * PY;
        bA.m_sweep.a -= bA.m_invI * (r1X * PY - r1Y * PX);
        bB.m_sweep.c.x += bB.m_invMass * PX;
        bB.m_sweep.c.y += bB.m_invMass * PY;
        bB.m_sweep.a += bB.m_invI * (r2X * PY - r2Y * PX);
        bA.SynchronizeTransform();
        bB.SynchronizeTransform();
        return b2Math.Abs(C) < b2Settings.b2_linearSlop;
    }
    Box2D.inherit(b2DistanceJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2DistanceJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2DistanceJointDef.b2DistanceJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
    };
    b2DistanceJointDef.prototype.b2DistanceJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_distanceJoint;
        this.length = 1.0;
        this.frequencyHz = 0.0;
        this.dampingRatio = 0.0;
    }
    b2DistanceJointDef.prototype.Initialize = function (bA, bB, anchorA, anchorB) {
        this.bodyA = bA;
        this.bodyB = bB;
        this.localAnchorA.SetV(this.bodyA.GetLocalPoint(anchorA));
        this.localAnchorB.SetV(this.bodyB.GetLocalPoint(anchorB));
        var dX = anchorB.x - anchorA.x;
        var dY = anchorB.y - anchorA.y;
        this.length = Math.sqrt(dX * dX + dY * dY);
        this.frequencyHz = 0.0;
        this.dampingRatio = 0.0;
    }
    Box2D.inherit(b2FrictionJoint, Box2D.Dynamics.Joints.b2Joint);
    b2FrictionJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2FrictionJoint.b2FrictionJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_localAnchorA = new b2Vec2();
        this.m_localAnchorB = new b2Vec2();
        this.m_linearMass = new b2Mat22();
        this.m_linearImpulse = new b2Vec2();
    };
    b2FrictionJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchorA);
    }
    b2FrictionJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchorB);
    }
    b2FrictionJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_linearImpulse.x, inv_dt * this.m_linearImpulse.y);
    }
    b2FrictionJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return inv_dt * this.m_angularImpulse;
    }
    b2FrictionJoint.prototype.SetMaxForce = function (force) {
        if (force === undefined) force = 0;
        this.m_maxForce = force;
    }
    b2FrictionJoint.prototype.GetMaxForce = function () {
        return this.m_maxForce;
    }
    b2FrictionJoint.prototype.SetMaxTorque = function (torque) {
        if (torque === undefined) torque = 0;
        this.m_maxTorque = torque;
    }
    b2FrictionJoint.prototype.GetMaxTorque = function () {
        return this.m_maxTorque;
    }
    b2FrictionJoint.prototype.b2FrictionJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        this.m_localAnchorA.SetV(def.localAnchorA);
        this.m_localAnchorB.SetV(def.localAnchorB);
        this.m_linearMass.SetZero();
        this.m_angularMass = 0.0;
        this.m_linearImpulse.SetZero();
        this.m_angularImpulse = 0.0;
        this.m_maxForce = def.maxForce;
        this.m_maxTorque = def.maxTorque;
    }
    b2FrictionJoint.prototype.InitVelocityConstraints = function (step) {
        var tMat;
        var tX = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        tMat = bA.m_xf.R;
        var rAX = this.m_localAnchorA.x - bA.m_sweep.localCenter.x;
        var rAY = this.m_localAnchorA.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rAX + tMat.col2.x * rAY);
        rAY = (tMat.col1.y * rAX + tMat.col2.y * rAY);
        rAX = tX;
        tMat = bB.m_xf.R;
        var rBX = this.m_localAnchorB.x - bB.m_sweep.localCenter.x;
        var rBY = this.m_localAnchorB.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rBX + tMat.col2.x * rBY);
        rBY = (tMat.col1.y * rBX + tMat.col2.y * rBY);
        rBX = tX;
        var mA = bA.m_invMass;
        var mB = bB.m_invMass;
        var iA = bA.m_invI;
        var iB = bB.m_invI;
        var K = new b2Mat22();
        K.col1.x = mA + mB;
        K.col2.x = 0.0;
        K.col1.y = 0.0;
        K.col2.y = mA + mB;
        K.col1.x += iA * rAY * rAY;
        K.col2.x += (-iA * rAX * rAY);
        K.col1.y += (-iA * rAX * rAY);
        K.col2.y += iA * rAX * rAX;
        K.col1.x += iB * rBY * rBY;
        K.col2.x += (-iB * rBX * rBY);
        K.col1.y += (-iB * rBX * rBY);
        K.col2.y += iB * rBX * rBX;
        K.GetInverse(this.m_linearMass);
        this.m_angularMass = iA + iB;
        if (this.m_angularMass > 0.0) {
            this.m_angularMass = 1.0 / this.m_angularMass;
        }
        if (step.warmStarting) {
            this.m_linearImpulse.x *= step.dtRatio;
            this.m_linearImpulse.y *= step.dtRatio;
            this.m_angularImpulse *= step.dtRatio;
            var P = this.m_linearImpulse;
            bA.m_linearVelocity.x -= mA * P.x;
            bA.m_linearVelocity.y -= mA * P.y;
            bA.m_angularVelocity -= iA * (rAX * P.y - rAY * P.x + this.m_angularImpulse);
            bB.m_linearVelocity.x += mB * P.x;
            bB.m_linearVelocity.y += mB * P.y;
            bB.m_angularVelocity += iB * (rBX * P.y - rBY * P.x + this.m_angularImpulse);
        }
        else {
            this.m_linearImpulse.SetZero();
            this.m_angularImpulse = 0.0;
        }
    }
    b2FrictionJoint.prototype.SolveVelocityConstraints = function (step) {
        var tMat;
        var tX = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var vA = bA.m_linearVelocity;
        var wA = bA.m_angularVelocity;
        var vB = bB.m_linearVelocity;
        var wB = bB.m_angularVelocity;
        var mA = bA.m_invMass;
        var mB = bB.m_invMass;
        var iA = bA.m_invI;
        var iB = bB.m_invI;
        tMat = bA.m_xf.R;
        var rAX = this.m_localAnchorA.x - bA.m_sweep.localCenter.x;
        var rAY = this.m_localAnchorA.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rAX + tMat.col2.x * rAY);
        rAY = (tMat.col1.y * rAX + tMat.col2.y * rAY);
        rAX = tX;
        tMat = bB.m_xf.R;
        var rBX = this.m_localAnchorB.x - bB.m_sweep.localCenter.x;
        var rBY = this.m_localAnchorB.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rBX + tMat.col2.x * rBY);
        rBY = (tMat.col1.y * rBX + tMat.col2.y * rBY);
        rBX = tX;
        var maxImpulse = 0; {
            var Cdot = wB - wA;
            var impulse = (-this.m_angularMass * Cdot);
            var oldImpulse = this.m_angularImpulse;
            maxImpulse = step.dt * this.m_maxTorque;
            this.m_angularImpulse = b2Math.Clamp(this.m_angularImpulse + impulse, (-maxImpulse), maxImpulse);
            impulse = this.m_angularImpulse - oldImpulse;
            wA -= iA * impulse;
            wB += iB * impulse;
        } {
            var CdotX = vB.x - wB * rBY - vA.x + wA * rAY;
            var CdotY = vB.y + wB * rBX - vA.y - wA * rAX;
            var impulseV = b2Math.MulMV(this.m_linearMass, new b2Vec2((-CdotX), (-CdotY)));
            var oldImpulseV = this.m_linearImpulse.Copy();
            this.m_linearImpulse.Add(impulseV);
            maxImpulse = step.dt * this.m_maxForce;
            if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) {
                this.m_linearImpulse.Normalize();
                this.m_linearImpulse.Multiply(maxImpulse);
            }
            impulseV = b2Math.SubtractVV(this.m_linearImpulse, oldImpulseV);
            vA.x -= mA * impulseV.x;
            vA.y -= mA * impulseV.y;
            wA -= iA * (rAX * impulseV.y - rAY * impulseV.x);
            vB.x += mB * impulseV.x;
            vB.y += mB * impulseV.y;
            wB += iB * (rBX * impulseV.y - rBY * impulseV.x);
        }
        bA.m_angularVelocity = wA;
        bB.m_angularVelocity = wB;
    }
    b2FrictionJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        return true;
    }
    Box2D.inherit(b2FrictionJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2FrictionJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2FrictionJointDef.b2FrictionJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
    };
    b2FrictionJointDef.prototype.b2FrictionJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_frictionJoint;
        this.maxForce = 0.0;
        this.maxTorque = 0.0;
    }
    b2FrictionJointDef.prototype.Initialize = function (bA, bB, anchor) {
        this.bodyA = bA;
        this.bodyB = bB;
        this.localAnchorA.SetV(this.bodyA.GetLocalPoint(anchor));
        this.localAnchorB.SetV(this.bodyB.GetLocalPoint(anchor));
    }
    Box2D.inherit(b2GearJoint, Box2D.Dynamics.Joints.b2Joint);
    b2GearJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2GearJoint.b2GearJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_groundAnchor1 = new b2Vec2();
        this.m_groundAnchor2 = new b2Vec2();
        this.m_localAnchor1 = new b2Vec2();
        this.m_localAnchor2 = new b2Vec2();
        this.m_J = new b2Jacobian();
    };
    b2GearJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
    }
    b2GearJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
    }
    b2GearJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_impulse * this.m_J.linearB.x, inv_dt * this.m_impulse * this.m_J.linearB.y);
    }
    b2GearJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        var tMat = this.m_bodyB.m_xf.R;
        var rX = this.m_localAnchor1.x - this.m_bodyB.m_sweep.localCenter.x;
        var rY = this.m_localAnchor1.y - this.m_bodyB.m_sweep.localCenter.y;
        var tX = tMat.col1.x * rX + tMat.col2.x * rY;
        rY = tMat.col1.y * rX + tMat.col2.y * rY;
        rX = tX;
        var PX = this.m_impulse * this.m_J.linearB.x;
        var PY = this.m_impulse * this.m_J.linearB.y;
        return inv_dt * (this.m_impulse * this.m_J.angularB - rX * PY + rY * PX);
    }
    b2GearJoint.prototype.GetRatio = function () {
        return this.m_ratio;
    }
    b2GearJoint.prototype.SetRatio = function (ratio) {
        if (ratio === undefined) ratio = 0;
        this.m_ratio = ratio;
    }
    b2GearJoint.prototype.b2GearJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        var type1 = parseInt(def.joint1.m_type);
        var type2 = parseInt(def.joint2.m_type);
        this.m_revolute1 = null;
        this.m_prismatic1 = null;
        this.m_revolute2 = null;
        this.m_prismatic2 = null;
        var coordinate1 = 0;
        var coordinate2 = 0;
        this.m_ground1 = def.joint1.GetBodyA();
        this.m_bodyA = def.joint1.GetBodyB();
        if (type1 == b2Joint.e_revoluteJoint) {
            this.m_revolute1 = (def.joint1 instanceof b2RevoluteJoint ? def.joint1 : null);
            this.m_groundAnchor1.SetV(this.m_revolute1.m_localAnchor1);
            this.m_localAnchor1.SetV(this.m_revolute1.m_localAnchor2);
            coordinate1 = this.m_revolute1.GetJointAngle();
        }
        else {
            this.m_prismatic1 = (def.joint1 instanceof b2PrismaticJoint ? def.joint1 : null);
            this.m_groundAnchor1.SetV(this.m_prismatic1.m_localAnchor1);
            this.m_localAnchor1.SetV(this.m_prismatic1.m_localAnchor2);
            coordinate1 = this.m_prismatic1.GetJointTranslation();
        }
        this.m_ground2 = def.joint2.GetBodyA();
        this.m_bodyB = def.joint2.GetBodyB();
        if (type2 == b2Joint.e_revoluteJoint) {
            this.m_revolute2 = (def.joint2 instanceof b2RevoluteJoint ? def.joint2 : null);
            this.m_groundAnchor2.SetV(this.m_revolute2.m_localAnchor1);
            this.m_localAnchor2.SetV(this.m_revolute2.m_localAnchor2);
            coordinate2 = this.m_revolute2.GetJointAngle();
        }
        else {
            this.m_prismatic2 = (def.joint2 instanceof b2PrismaticJoint ? def.joint2 : null);
            this.m_groundAnchor2.SetV(this.m_prismatic2.m_localAnchor1);
            this.m_localAnchor2.SetV(this.m_prismatic2.m_localAnchor2);
            coordinate2 = this.m_prismatic2.GetJointTranslation();
        }
        this.m_ratio = def.ratio;
        this.m_constant = coordinate1 + this.m_ratio * coordinate2;
        this.m_impulse = 0.0;
    }
    b2GearJoint.prototype.InitVelocityConstraints = function (step) {
        var g1 = this.m_ground1;
        var g2 = this.m_ground2;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var ugX = 0;
        var ugY = 0;
        var rX = 0;
        var rY = 0;
        var tMat;
        var tVec;
        var crug = 0;
        var tX = 0;
        var K = 0.0;
        this.m_J.SetZero();
        if (this.m_revolute1) {
            this.m_J.angularA = (-1.0);
            K += bA.m_invI;
        }
        else {
            tMat = g1.m_xf.R;
            tVec = this.m_prismatic1.m_localXAxis1;
            ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
            ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
            tMat = bA.m_xf.R;
            rX = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
            rY = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
            tX = tMat.col1.x * rX + tMat.col2.x * rY;
            rY = tMat.col1.y * rX + tMat.col2.y * rY;
            rX = tX;
            crug = rX * ugY - rY * ugX;
            this.m_J.linearA.Set((-ugX), (-ugY));
            this.m_J.angularA = (-crug);
            K += bA.m_invMass + bA.m_invI * crug * crug;
        }
        if (this.m_revolute2) {
            this.m_J.angularB = (-this.m_ratio);
            K += this.m_ratio * this.m_ratio * bB.m_invI;
        }
        else {
            tMat = g2.m_xf.R;
            tVec = this.m_prismatic2.m_localXAxis1;
            ugX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
            ugY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
            tMat = bB.m_xf.R;
            rX = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
            rY = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
            tX = tMat.col1.x * rX + tMat.col2.x * rY;
            rY = tMat.col1.y * rX + tMat.col2.y * rY;
            rX = tX;
            crug = rX * ugY - rY * ugX;
            this.m_J.linearB.Set((-this.m_ratio * ugX), (-this.m_ratio * ugY));
            this.m_J.angularB = (-this.m_ratio * crug);
            K += this.m_ratio * this.m_ratio * (bB.m_invMass + bB.m_invI * crug * crug);
        }
        this.m_mass = K > 0.0 ? 1.0 / K : 0.0;
        if (step.warmStarting) {
            bA.m_linearVelocity.x += bA.m_invMass * this.m_impulse * this.m_J.linearA.x;
            bA.m_linearVelocity.y += bA.m_invMass * this.m_impulse * this.m_J.linearA.y;
            bA.m_angularVelocity += bA.m_invI * this.m_impulse * this.m_J.angularA;
            bB.m_linearVelocity.x += bB.m_invMass * this.m_impulse * this.m_J.linearB.x;
            bB.m_linearVelocity.y += bB.m_invMass * this.m_impulse * this.m_J.linearB.y;
            bB.m_angularVelocity += bB.m_invI * this.m_impulse * this.m_J.angularB;
        }
        else {
            this.m_impulse = 0.0;
        }
    }
    b2GearJoint.prototype.SolveVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var Cdot = this.m_J.Compute(bA.m_linearVelocity, bA.m_angularVelocity, bB.m_linearVelocity, bB.m_angularVelocity);
        var impulse = (-this.m_mass * Cdot);
        this.m_impulse += impulse;
        bA.m_linearVelocity.x += bA.m_invMass * impulse * this.m_J.linearA.x;
        bA.m_linearVelocity.y += bA.m_invMass * impulse * this.m_J.linearA.y;
        bA.m_angularVelocity += bA.m_invI * impulse * this.m_J.angularA;
        bB.m_linearVelocity.x += bB.m_invMass * impulse * this.m_J.linearB.x;
        bB.m_linearVelocity.y += bB.m_invMass * impulse * this.m_J.linearB.y;
        bB.m_angularVelocity += bB.m_invI * impulse * this.m_J.angularB;
    }
    b2GearJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var linearError = 0.0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var coordinate1 = 0;
        var coordinate2 = 0;
        if (this.m_revolute1) {
            coordinate1 = this.m_revolute1.GetJointAngle();
        }
        else {
            coordinate1 = this.m_prismatic1.GetJointTranslation();
        }
        if (this.m_revolute2) {
            coordinate2 = this.m_revolute2.GetJointAngle();
        }
        else {
            coordinate2 = this.m_prismatic2.GetJointTranslation();
        }
        var C = this.m_constant - (coordinate1 + this.m_ratio * coordinate2);
        var impulse = (-this.m_mass * C);
        bA.m_sweep.c.x += bA.m_invMass * impulse * this.m_J.linearA.x;
        bA.m_sweep.c.y += bA.m_invMass * impulse * this.m_J.linearA.y;
        bA.m_sweep.a += bA.m_invI * impulse * this.m_J.angularA;
        bB.m_sweep.c.x += bB.m_invMass * impulse * this.m_J.linearB.x;
        bB.m_sweep.c.y += bB.m_invMass * impulse * this.m_J.linearB.y;
        bB.m_sweep.a += bB.m_invI * impulse * this.m_J.angularB;
        bA.SynchronizeTransform();
        bB.SynchronizeTransform();
        return linearError < b2Settings.b2_linearSlop;
    }
    Box2D.inherit(b2GearJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2GearJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2GearJointDef.b2GearJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
    };
    b2GearJointDef.prototype.b2GearJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_gearJoint;
        this.joint1 = null;
        this.joint2 = null;
        this.ratio = 1.0;
    }
    b2Jacobian.b2Jacobian = function () {
        this.linearA = new b2Vec2();
        this.linearB = new b2Vec2();
    };
    b2Jacobian.prototype.SetZero = function () {
        this.linearA.SetZero();
        this.angularA = 0.0;
        this.linearB.SetZero();
        this.angularB = 0.0;
    }
    b2Jacobian.prototype.Set = function (x1, a1, x2, a2) {
        if (a1 === undefined) a1 = 0;
        if (a2 === undefined) a2 = 0;
        this.linearA.SetV(x1);
        this.angularA = a1;
        this.linearB.SetV(x2);
        this.angularB = a2;
    }
    b2Jacobian.prototype.Compute = function (x1, a1, x2, a2) {
        if (a1 === undefined) a1 = 0;
        if (a2 === undefined) a2 = 0;
        return (this.linearA.x * x1.x + this.linearA.y * x1.y) + this.angularA * a1 + (this.linearB.x * x2.x + this.linearB.y * x2.y) + this.angularB * a2;
    }
    b2Joint.b2Joint = function () {
        this.m_edgeA = new b2JointEdge();
        this.m_edgeB = new b2JointEdge();
        this.m_localCenterA = new b2Vec2();
        this.m_localCenterB = new b2Vec2();
    };
    b2Joint.prototype.GetType = function () {
        return this.m_type;
    }
    b2Joint.prototype.GetAnchorA = function () {
        return null;
    }
    b2Joint.prototype.GetAnchorB = function () {
        return null;
    }
    b2Joint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return null;
    }
    b2Joint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return 0.0;
    }
    b2Joint.prototype.GetBodyA = function () {
        return this.m_bodyA;
    }
    b2Joint.prototype.GetBodyB = function () {
        return this.m_bodyB;
    }
    b2Joint.prototype.GetNext = function () {
        return this.m_next;
    }
    b2Joint.prototype.GetUserData = function () {
        return this.m_userData;
    }
    b2Joint.prototype.SetUserData = function (data) {
        this.m_userData = data;
    }
    b2Joint.prototype.IsActive = function () {
        return this.m_bodyA.IsActive() && this.m_bodyB.IsActive();
    }
    b2Joint.Create = function (def, allocator) {
        var joint = null;
        switch (def.type) {
            case b2Joint.e_distanceJoint:
            {
                joint = new b2DistanceJoint((def instanceof b2DistanceJointDef ? def : null));
            }
                break;
            case b2Joint.e_mouseJoint:
            {
                joint = new b2MouseJoint((def instanceof b2MouseJointDef ? def : null));
            }
                break;
            case b2Joint.e_prismaticJoint:
            {
                joint = new b2PrismaticJoint((def instanceof b2PrismaticJointDef ? def : null));
            }
                break;
            case b2Joint.e_revoluteJoint:
            {
                joint = new b2RevoluteJoint((def instanceof b2RevoluteJointDef ? def : null));
            }
                break;
            case b2Joint.e_pulleyJoint:
            {
                joint = new b2PulleyJoint((def instanceof b2PulleyJointDef ? def : null));
            }
                break;
            case b2Joint.e_gearJoint:
            {
                joint = new b2GearJoint((def instanceof b2GearJointDef ? def : null));
            }
                break;
            case b2Joint.e_lineJoint:
            {
                joint = new b2LineJoint((def instanceof b2LineJointDef ? def : null));
            }
                break;
            case b2Joint.e_weldJoint:
            {
                joint = new b2WeldJoint((def instanceof b2WeldJointDef ? def : null));
            }
                break;
            case b2Joint.e_frictionJoint:
            {
                joint = new b2FrictionJoint((def instanceof b2FrictionJointDef ? def : null));
            }
                break;
            default:
                break;
        }
        return joint;
    }
    b2Joint.Destroy = function (joint, allocator) {}
    b2Joint.prototype.b2Joint = function (def) {
        b2Settings.b2Assert(def.bodyA != def.bodyB);
        this.m_type = def.type;
        this.m_prev = null;
        this.m_next = null;
        this.m_bodyA = def.bodyA;
        this.m_bodyB = def.bodyB;
        this.m_collideConnected = def.collideConnected;
        this.m_islandFlag = false;
        this.m_userData = def.userData;
    }
    b2Joint.prototype.InitVelocityConstraints = function (step) {}
    b2Joint.prototype.SolveVelocityConstraints = function (step) {}
    b2Joint.prototype.FinalizeVelocityConstraints = function () {}
    b2Joint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        return false;
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.Joints.b2Joint.e_unknownJoint = 0;
        Box2D.Dynamics.Joints.b2Joint.e_revoluteJoint = 1;
        Box2D.Dynamics.Joints.b2Joint.e_prismaticJoint = 2;
        Box2D.Dynamics.Joints.b2Joint.e_distanceJoint = 3;
        Box2D.Dynamics.Joints.b2Joint.e_pulleyJoint = 4;
        Box2D.Dynamics.Joints.b2Joint.e_mouseJoint = 5;
        Box2D.Dynamics.Joints.b2Joint.e_gearJoint = 6;
        Box2D.Dynamics.Joints.b2Joint.e_lineJoint = 7;
        Box2D.Dynamics.Joints.b2Joint.e_weldJoint = 8;
        Box2D.Dynamics.Joints.b2Joint.e_frictionJoint = 9;
        Box2D.Dynamics.Joints.b2Joint.e_inactiveLimit = 0;
        Box2D.Dynamics.Joints.b2Joint.e_atLowerLimit = 1;
        Box2D.Dynamics.Joints.b2Joint.e_atUpperLimit = 2;
        Box2D.Dynamics.Joints.b2Joint.e_equalLimits = 3;
    });
    b2JointDef.b2JointDef = function () {};
    b2JointDef.prototype.b2JointDef = function () {
        this.type = b2Joint.e_unknownJoint;
        this.userData = null;
        this.bodyA = null;
        this.bodyB = null;
        this.collideConnected = false;
    }
    b2JointEdge.b2JointEdge = function () {};
    Box2D.inherit(b2LineJoint, Box2D.Dynamics.Joints.b2Joint);
    b2LineJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2LineJoint.b2LineJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_localAnchor1 = new b2Vec2();
        this.m_localAnchor2 = new b2Vec2();
        this.m_localXAxis1 = new b2Vec2();
        this.m_localYAxis1 = new b2Vec2();
        this.m_axis = new b2Vec2();
        this.m_perp = new b2Vec2();
        this.m_K = new b2Mat22();
        this.m_impulse = new b2Vec2();
    };
    b2LineJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
    }
    b2LineJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
    }
    b2LineJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * (this.m_impulse.x * this.m_perp.x + (this.m_motorImpulse + this.m_impulse.y) * this.m_axis.x), inv_dt * (this.m_impulse.x * this.m_perp.y + (this.m_motorImpulse + this.m_impulse.y) * this.m_axis.y));
    }
    b2LineJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return inv_dt * this.m_impulse.y;
    }
    b2LineJoint.prototype.GetJointTranslation = function () {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var p1 = bA.GetWorldPoint(this.m_localAnchor1);
        var p2 = bB.GetWorldPoint(this.m_localAnchor2);
        var dX = p2.x - p1.x;
        var dY = p2.y - p1.y;
        var axis = bA.GetWorldVector(this.m_localXAxis1);
        var translation = axis.x * dX + axis.y * dY;
        return translation;
    }
    b2LineJoint.prototype.GetJointSpeed = function () {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var p1X = bA.m_sweep.c.x + r1X;
        var p1Y = bA.m_sweep.c.y + r1Y;
        var p2X = bB.m_sweep.c.x + r2X;
        var p2Y = bB.m_sweep.c.y + r2Y;
        var dX = p2X - p1X;
        var dY = p2Y - p1Y;
        var axis = bA.GetWorldVector(this.m_localXAxis1);
        var v1 = bA.m_linearVelocity;
        var v2 = bB.m_linearVelocity;
        var w1 = bA.m_angularVelocity;
        var w2 = bB.m_angularVelocity;
        var speed = (dX * ((-w1 * axis.y)) + dY * (w1 * axis.x)) + (axis.x * (((v2.x + ((-w2 * r2Y))) - v1.x) - ((-w1 * r1Y))) + axis.y * (((v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
        return speed;
    }
    b2LineJoint.prototype.IsLimitEnabled = function () {
        return this.m_enableLimit;
    }
    b2LineJoint.prototype.EnableLimit = function (flag) {
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_enableLimit = flag;
    }
    b2LineJoint.prototype.GetLowerLimit = function () {
        return this.m_lowerTranslation;
    }
    b2LineJoint.prototype.GetUpperLimit = function () {
        return this.m_upperTranslation;
    }
    b2LineJoint.prototype.SetLimits = function (lower, upper) {
        if (lower === undefined) lower = 0;
        if (upper === undefined) upper = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_lowerTranslation = lower;
        this.m_upperTranslation = upper;
    }
    b2LineJoint.prototype.IsMotorEnabled = function () {
        return this.m_enableMotor;
    }
    b2LineJoint.prototype.EnableMotor = function (flag) {
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_enableMotor = flag;
    }
    b2LineJoint.prototype.SetMotorSpeed = function (speed) {
        if (speed === undefined) speed = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_motorSpeed = speed;
    }
    b2LineJoint.prototype.GetMotorSpeed = function () {
        return this.m_motorSpeed;
    }
    b2LineJoint.prototype.SetMaxMotorForce = function (force) {
        if (force === undefined) force = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_maxMotorForce = force;
    }
    b2LineJoint.prototype.GetMaxMotorForce = function () {
        return this.m_maxMotorForce;
    }
    b2LineJoint.prototype.GetMotorForce = function () {
        return this.m_motorImpulse;
    }
    b2LineJoint.prototype.b2LineJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        var tMat;
        var tX = 0;
        var tY = 0;
        this.m_localAnchor1.SetV(def.localAnchorA);
        this.m_localAnchor2.SetV(def.localAnchorB);
        this.m_localXAxis1.SetV(def.localAxisA);
        this.m_localYAxis1.x = (-this.m_localXAxis1.y);
        this.m_localYAxis1.y = this.m_localXAxis1.x;
        this.m_impulse.SetZero();
        this.m_motorMass = 0.0;
        this.m_motorImpulse = 0.0;
        this.m_lowerTranslation = def.lowerTranslation;
        this.m_upperTranslation = def.upperTranslation;
        this.m_maxMotorForce = def.maxMotorForce;
        this.m_motorSpeed = def.motorSpeed;
        this.m_enableLimit = def.enableLimit;
        this.m_enableMotor = def.enableMotor;
        this.m_limitState = b2Joint.e_inactiveLimit;
        this.m_axis.SetZero();
        this.m_perp.SetZero();
    }
    b2LineJoint.prototype.InitVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var tX = 0;
        this.m_localCenterA.SetV(bA.GetLocalCenter());
        this.m_localCenterB.SetV(bB.GetLocalCenter());
        var xf1 = bA.GetTransform();
        var xf2 = bB.GetTransform();
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - this.m_localCenterA.x;
        var r1Y = this.m_localAnchor1.y - this.m_localCenterA.y;
        tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - this.m_localCenterB.x;
        var r2Y = this.m_localAnchor2.y - this.m_localCenterB.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var dX = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
        var dY = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
        this.m_invMassA = bA.m_invMass;
        this.m_invMassB = bB.m_invMass;
        this.m_invIA = bA.m_invI;
        this.m_invIB = bB.m_invI; {
            this.m_axis.SetV(b2Math.MulMV(xf1.R, this.m_localXAxis1));
            this.m_a1 = (dX + r1X) * this.m_axis.y - (dY + r1Y) * this.m_axis.x;
            this.m_a2 = r2X * this.m_axis.y - r2Y * this.m_axis.x;
            this.m_motorMass = this.m_invMassA + this.m_invMassB + this.m_invIA * this.m_a1 * this.m_a1 + this.m_invIB * this.m_a2 * this.m_a2;
            this.m_motorMass = this.m_motorMass > Number.MIN_VALUE ? 1.0 / this.m_motorMass : 0.0;
        } {
            this.m_perp.SetV(b2Math.MulMV(xf1.R, this.m_localYAxis1));
            this.m_s1 = (dX + r1X) * this.m_perp.y - (dY + r1Y) * this.m_perp.x;
            this.m_s2 = r2X * this.m_perp.y - r2Y * this.m_perp.x;
            var m1 = this.m_invMassA;
            var m2 = this.m_invMassB;
            var i1 = this.m_invIA;
            var i2 = this.m_invIB;
            this.m_K.col1.x = m1 + m2 + i1 * this.m_s1 * this.m_s1 + i2 * this.m_s2 * this.m_s2;
            this.m_K.col1.y = i1 * this.m_s1 * this.m_a1 + i2 * this.m_s2 * this.m_a2;
            this.m_K.col2.x = this.m_K.col1.y;
            this.m_K.col2.y = m1 + m2 + i1 * this.m_a1 * this.m_a1 + i2 * this.m_a2 * this.m_a2;
        }
        if (this.m_enableLimit) {
            var jointTransition = this.m_axis.x * dX + this.m_axis.y * dY;
            if (b2Math.Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop) {
                this.m_limitState = b2Joint.e_equalLimits;
            }
            else if (jointTransition <= this.m_lowerTranslation) {
                if (this.m_limitState != b2Joint.e_atLowerLimit) {
                    this.m_limitState = b2Joint.e_atLowerLimit;
                    this.m_impulse.y = 0.0;
                }
            }
            else if (jointTransition >= this.m_upperTranslation) {
                if (this.m_limitState != b2Joint.e_atUpperLimit) {
                    this.m_limitState = b2Joint.e_atUpperLimit;
                    this.m_impulse.y = 0.0;
                }
            }
            else {
                this.m_limitState = b2Joint.e_inactiveLimit;
                this.m_impulse.y = 0.0;
            }
        }
        else {
            this.m_limitState = b2Joint.e_inactiveLimit;
        }
        if (this.m_enableMotor == false) {
            this.m_motorImpulse = 0.0;
        }
        if (step.warmStarting) {
            this.m_impulse.x *= step.dtRatio;
            this.m_impulse.y *= step.dtRatio;
            this.m_motorImpulse *= step.dtRatio;
            var PX = this.m_impulse.x * this.m_perp.x + (this.m_motorImpulse + this.m_impulse.y) * this.m_axis.x;
            var PY = this.m_impulse.x * this.m_perp.y + (this.m_motorImpulse + this.m_impulse.y) * this.m_axis.y;
            var L1 = this.m_impulse.x * this.m_s1 + (this.m_motorImpulse + this.m_impulse.y) * this.m_a1;
            var L2 = this.m_impulse.x * this.m_s2 + (this.m_motorImpulse + this.m_impulse.y) * this.m_a2;
            bA.m_linearVelocity.x -= this.m_invMassA * PX;
            bA.m_linearVelocity.y -= this.m_invMassA * PY;
            bA.m_angularVelocity -= this.m_invIA * L1;
            bB.m_linearVelocity.x += this.m_invMassB * PX;
            bB.m_linearVelocity.y += this.m_invMassB * PY;
            bB.m_angularVelocity += this.m_invIB * L2;
        }
        else {
            this.m_impulse.SetZero();
            this.m_motorImpulse = 0.0;
        }
    }
    b2LineJoint.prototype.SolveVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var v1 = bA.m_linearVelocity;
        var w1 = bA.m_angularVelocity;
        var v2 = bB.m_linearVelocity;
        var w2 = bB.m_angularVelocity;
        var PX = 0;
        var PY = 0;
        var L1 = 0;
        var L2 = 0;
        if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) {
            var Cdot = this.m_axis.x * (v2.x - v1.x) + this.m_axis.y * (v2.y - v1.y) + this.m_a2 * w2 - this.m_a1 * w1;
            var impulse = this.m_motorMass * (this.m_motorSpeed - Cdot);
            var oldImpulse = this.m_motorImpulse;
            var maxImpulse = step.dt * this.m_maxMotorForce;
            this.m_motorImpulse = b2Math.Clamp(this.m_motorImpulse + impulse, (-maxImpulse), maxImpulse);
            impulse = this.m_motorImpulse - oldImpulse;
            PX = impulse * this.m_axis.x;
            PY = impulse * this.m_axis.y;
            L1 = impulse * this.m_a1;
            L2 = impulse * this.m_a2;
            v1.x -= this.m_invMassA * PX;
            v1.y -= this.m_invMassA * PY;
            w1 -= this.m_invIA * L1;
            v2.x += this.m_invMassB * PX;
            v2.y += this.m_invMassB * PY;
            w2 += this.m_invIB * L2;
        }
        var Cdot1 = this.m_perp.x * (v2.x - v1.x) + this.m_perp.y * (v2.y - v1.y) + this.m_s2 * w2 - this.m_s1 * w1;
        if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) {
            var Cdot2 = this.m_axis.x * (v2.x - v1.x) + this.m_axis.y * (v2.y - v1.y) + this.m_a2 * w2 - this.m_a1 * w1;
            var f1 = this.m_impulse.Copy();
            var df = this.m_K.Solve(new b2Vec2(), (-Cdot1), (-Cdot2));
            this.m_impulse.Add(df);
            if (this.m_limitState == b2Joint.e_atLowerLimit) {
                this.m_impulse.y = b2Math.Max(this.m_impulse.y, 0.0);
            }
            else if (this.m_limitState == b2Joint.e_atUpperLimit) {
                this.m_impulse.y = b2Math.Min(this.m_impulse.y, 0.0);
            }
            var b = (-Cdot1) - (this.m_impulse.y - f1.y) * this.m_K.col2.x;
            var f2r = 0;
            if (this.m_K.col1.x != 0.0) {
                f2r = b / this.m_K.col1.x + f1.x;
            }
            else {
                f2r = f1.x;
            }
            this.m_impulse.x = f2r;
            df.x = this.m_impulse.x - f1.x;
            df.y = this.m_impulse.y - f1.y;
            PX = df.x * this.m_perp.x + df.y * this.m_axis.x;
            PY = df.x * this.m_perp.y + df.y * this.m_axis.y;
            L1 = df.x * this.m_s1 + df.y * this.m_a1;
            L2 = df.x * this.m_s2 + df.y * this.m_a2;
            v1.x -= this.m_invMassA * PX;
            v1.y -= this.m_invMassA * PY;
            w1 -= this.m_invIA * L1;
            v2.x += this.m_invMassB * PX;
            v2.y += this.m_invMassB * PY;
            w2 += this.m_invIB * L2;
        }
        else {
            var df2 = 0;
            if (this.m_K.col1.x != 0.0) {
                df2 = ((-Cdot1)) / this.m_K.col1.x;
            }
            else {
                df2 = 0.0;
            }
            this.m_impulse.x += df2;
            PX = df2 * this.m_perp.x;
            PY = df2 * this.m_perp.y;
            L1 = df2 * this.m_s1;
            L2 = df2 * this.m_s2;
            v1.x -= this.m_invMassA * PX;
            v1.y -= this.m_invMassA * PY;
            w1 -= this.m_invIA * L1;
            v2.x += this.m_invMassB * PX;
            v2.y += this.m_invMassB * PY;
            w2 += this.m_invIB * L2;
        }
        bA.m_linearVelocity.SetV(v1);
        bA.m_angularVelocity = w1;
        bB.m_linearVelocity.SetV(v2);
        bB.m_angularVelocity = w2;
    }
    b2LineJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var limitC = 0;
        var oldLimitImpulse = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var c1 = bA.m_sweep.c;
        var a1 = bA.m_sweep.a;
        var c2 = bB.m_sweep.c;
        var a2 = bB.m_sweep.a;
        var tMat;
        var tX = 0;
        var m1 = 0;
        var m2 = 0;
        var i1 = 0;
        var i2 = 0;
        var linearError = 0.0;
        var angularError = 0.0;
        var active = false;
        var C2 = 0.0;
        var R1 = b2Mat22.FromAngle(a1);
        var R2 = b2Mat22.FromAngle(a2);
        tMat = R1;
        var r1X = this.m_localAnchor1.x - this.m_localCenterA.x;
        var r1Y = this.m_localAnchor1.y - this.m_localCenterA.y;
        tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = R2;
        var r2X = this.m_localAnchor2.x - this.m_localCenterB.x;
        var r2Y = this.m_localAnchor2.y - this.m_localCenterB.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var dX = c2.x + r2X - c1.x - r1X;
        var dY = c2.y + r2Y - c1.y - r1Y;
        if (this.m_enableLimit) {
            this.m_axis = b2Math.MulMV(R1, this.m_localXAxis1);
            this.m_a1 = (dX + r1X) * this.m_axis.y - (dY + r1Y) * this.m_axis.x;
            this.m_a2 = r2X * this.m_axis.y - r2Y * this.m_axis.x;
            var translation = this.m_axis.x * dX + this.m_axis.y * dY;
            if (b2Math.Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop) {
                C2 = b2Math.Clamp(translation, (-b2Settings.b2_maxLinearCorrection), b2Settings.b2_maxLinearCorrection);
                linearError = b2Math.Abs(translation);
                active = true;
            }
            else if (translation <= this.m_lowerTranslation) {
                C2 = b2Math.Clamp(translation - this.m_lowerTranslation + b2Settings.b2_linearSlop, (-b2Settings.b2_maxLinearCorrection), 0.0);
                linearError = this.m_lowerTranslation - translation;
                active = true;
            }
            else if (translation >= this.m_upperTranslation) {
                C2 = b2Math.Clamp(translation - this.m_upperTranslation + b2Settings.b2_linearSlop, 0.0, b2Settings.b2_maxLinearCorrection);
                linearError = translation - this.m_upperTranslation;
                active = true;
            }
        }
        this.m_perp = b2Math.MulMV(R1, this.m_localYAxis1);
        this.m_s1 = (dX + r1X) * this.m_perp.y - (dY + r1Y) * this.m_perp.x;
        this.m_s2 = r2X * this.m_perp.y - r2Y * this.m_perp.x;
        var impulse = new b2Vec2();
        var C1 = this.m_perp.x * dX + this.m_perp.y * dY;
        linearError = b2Math.Max(linearError, b2Math.Abs(C1));
        angularError = 0.0;
        if (active) {
            m1 = this.m_invMassA;
            m2 = this.m_invMassB;
            i1 = this.m_invIA;
            i2 = this.m_invIB;
            this.m_K.col1.x = m1 + m2 + i1 * this.m_s1 * this.m_s1 + i2 * this.m_s2 * this.m_s2;
            this.m_K.col1.y = i1 * this.m_s1 * this.m_a1 + i2 * this.m_s2 * this.m_a2;
            this.m_K.col2.x = this.m_K.col1.y;
            this.m_K.col2.y = m1 + m2 + i1 * this.m_a1 * this.m_a1 + i2 * this.m_a2 * this.m_a2;
            this.m_K.Solve(impulse, (-C1), (-C2));
        }
        else {
            m1 = this.m_invMassA;
            m2 = this.m_invMassB;
            i1 = this.m_invIA;
            i2 = this.m_invIB;
            var k11 = m1 + m2 + i1 * this.m_s1 * this.m_s1 + i2 * this.m_s2 * this.m_s2;
            var impulse1 = 0;
            if (k11 != 0.0) {
                impulse1 = ((-C1)) / k11;
            }
            else {
                impulse1 = 0.0;
            }
            impulse.x = impulse1;
            impulse.y = 0.0;
        }
        var PX = impulse.x * this.m_perp.x + impulse.y * this.m_axis.x;
        var PY = impulse.x * this.m_perp.y + impulse.y * this.m_axis.y;
        var L1 = impulse.x * this.m_s1 + impulse.y * this.m_a1;
        var L2 = impulse.x * this.m_s2 + impulse.y * this.m_a2;
        c1.x -= this.m_invMassA * PX;
        c1.y -= this.m_invMassA * PY;
        a1 -= this.m_invIA * L1;
        c2.x += this.m_invMassB * PX;
        c2.y += this.m_invMassB * PY;
        a2 += this.m_invIB * L2;
        bA.m_sweep.a = a1;
        bB.m_sweep.a = a2;
        bA.SynchronizeTransform();
        bB.SynchronizeTransform();
        return linearError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
    }
    Box2D.inherit(b2LineJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2LineJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2LineJointDef.b2LineJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
        this.localAxisA = new b2Vec2();
    };
    b2LineJointDef.prototype.b2LineJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_lineJoint;
        this.localAxisA.Set(1.0, 0.0);
        this.enableLimit = false;
        this.lowerTranslation = 0.0;
        this.upperTranslation = 0.0;
        this.enableMotor = false;
        this.maxMotorForce = 0.0;
        this.motorSpeed = 0.0;
    }
    b2LineJointDef.prototype.Initialize = function (bA, bB, anchor, axis) {
        this.bodyA = bA;
        this.bodyB = bB;
        this.localAnchorA = this.bodyA.GetLocalPoint(anchor);
        this.localAnchorB = this.bodyB.GetLocalPoint(anchor);
        this.localAxisA = this.bodyA.GetLocalVector(axis);
    }
    Box2D.inherit(b2MouseJoint, Box2D.Dynamics.Joints.b2Joint);
    b2MouseJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2MouseJoint.b2MouseJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.K = new b2Mat22();
        this.K1 = new b2Mat22();
        this.K2 = new b2Mat22();
        this.m_localAnchor = new b2Vec2();
        this.m_target = new b2Vec2();
        this.m_impulse = new b2Vec2();
        this.m_mass = new b2Mat22();
        this.m_C = new b2Vec2();
    };
    b2MouseJoint.prototype.GetAnchorA = function () {
        return this.m_target;
    }
    b2MouseJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor);
    }
    b2MouseJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_impulse.x, inv_dt * this.m_impulse.y);
    }
    b2MouseJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return 0.0;
    }
    b2MouseJoint.prototype.GetTarget = function () {
        return this.m_target;
    }
    b2MouseJoint.prototype.SetTarget = function (target) {
        if (this.m_bodyB.IsAwake() == false) {
            this.m_bodyB.SetAwake(true);
        }
        this.m_target = target;
    }
    b2MouseJoint.prototype.GetMaxForce = function () {
        return this.m_maxForce;
    }
    b2MouseJoint.prototype.SetMaxForce = function (maxForce) {
        if (maxForce === undefined) maxForce = 0;
        this.m_maxForce = maxForce;
    }
    b2MouseJoint.prototype.GetFrequency = function () {
        return this.m_frequencyHz;
    }
    b2MouseJoint.prototype.SetFrequency = function (hz) {
        if (hz === undefined) hz = 0;
        this.m_frequencyHz = hz;
    }
    b2MouseJoint.prototype.GetDampingRatio = function () {
        return this.m_dampingRatio;
    }
    b2MouseJoint.prototype.SetDampingRatio = function (ratio) {
        if (ratio === undefined) ratio = 0;
        this.m_dampingRatio = ratio;
    }
    b2MouseJoint.prototype.b2MouseJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        this.m_target.SetV(def.target);
        var tX = this.m_target.x - this.m_bodyB.m_xf.position.x;
        var tY = this.m_target.y - this.m_bodyB.m_xf.position.y;
        var tMat = this.m_bodyB.m_xf.R;
        this.m_localAnchor.x = (tX * tMat.col1.x + tY * tMat.col1.y);
        this.m_localAnchor.y = (tX * tMat.col2.x + tY * tMat.col2.y);
        this.m_maxForce = def.maxForce;
        this.m_impulse.SetZero();
        this.m_frequencyHz = def.frequencyHz;
        this.m_dampingRatio = def.dampingRatio;
        this.m_beta = 0.0;
        this.m_gamma = 0.0;
    }
    b2MouseJoint.prototype.InitVelocityConstraints = function (step) {
        var b = this.m_bodyB;
        var mass = b.GetMass();
        var omega = 2.0 * Math.PI * this.m_frequencyHz;
        var d = 2.0 * mass * this.m_dampingRatio * omega;
        var k = mass * omega * omega;
        this.m_gamma = step.dt * (d + step.dt * k);
        this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0.0;
        this.m_beta = step.dt * k * this.m_gamma;
        var tMat;tMat = b.m_xf.R;
        var rX = this.m_localAnchor.x - b.m_sweep.localCenter.x;
        var rY = this.m_localAnchor.y - b.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * rX + tMat.col2.x * rY);rY = (tMat.col1.y * rX + tMat.col2.y * rY);
        rX = tX;
        var invMass = b.m_invMass;
        var invI = b.m_invI;this.K1.col1.x = invMass;
        this.K1.col2.x = 0.0;
        this.K1.col1.y = 0.0;
        this.K1.col2.y = invMass;
        this.K2.col1.x = invI * rY * rY;
        this.K2.col2.x = (-invI * rX * rY);
        this.K2.col1.y = (-invI * rX * rY);
        this.K2.col2.y = invI * rX * rX;
        this.K.SetM(this.K1);
        this.K.AddM(this.K2);
        this.K.col1.x += this.m_gamma;
        this.K.col2.y += this.m_gamma;
        this.K.GetInverse(this.m_mass);
        this.m_C.x = b.m_sweep.c.x + rX - this.m_target.x;
        this.m_C.y = b.m_sweep.c.y + rY - this.m_target.y;
        b.m_angularVelocity *= 0.98;
        this.m_impulse.x *= step.dtRatio;
        this.m_impulse.y *= step.dtRatio;
        b.m_linearVelocity.x += invMass * this.m_impulse.x;
        b.m_linearVelocity.y += invMass * this.m_impulse.y;
        b.m_angularVelocity += invI * (rX * this.m_impulse.y - rY * this.m_impulse.x);
    }
    b2MouseJoint.prototype.SolveVelocityConstraints = function (step) {
        var b = this.m_bodyB;
        var tMat;
        var tX = 0;
        var tY = 0;
        tMat = b.m_xf.R;
        var rX = this.m_localAnchor.x - b.m_sweep.localCenter.x;
        var rY = this.m_localAnchor.y - b.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rX + tMat.col2.x * rY);
        rY = (tMat.col1.y * rX + tMat.col2.y * rY);
        rX = tX;
        var CdotX = b.m_linearVelocity.x + ((-b.m_angularVelocity * rY));
        var CdotY = b.m_linearVelocity.y + (b.m_angularVelocity * rX);
        tMat = this.m_mass;
        tX = CdotX + this.m_beta * this.m_C.x + this.m_gamma * this.m_impulse.x;
        tY = CdotY + this.m_beta * this.m_C.y + this.m_gamma * this.m_impulse.y;
        var impulseX = (-(tMat.col1.x * tX + tMat.col2.x * tY));
        var impulseY = (-(tMat.col1.y * tX + tMat.col2.y * tY));
        var oldImpulseX = this.m_impulse.x;
        var oldImpulseY = this.m_impulse.y;
        this.m_impulse.x += impulseX;
        this.m_impulse.y += impulseY;
        var maxImpulse = step.dt * this.m_maxForce;
        if (this.m_impulse.LengthSquared() > maxImpulse * maxImpulse) {
            this.m_impulse.Multiply(maxImpulse / this.m_impulse.Length());
        }
        impulseX = this.m_impulse.x - oldImpulseX;
        impulseY = this.m_impulse.y - oldImpulseY;
        b.m_linearVelocity.x += b.m_invMass * impulseX;
        b.m_linearVelocity.y += b.m_invMass * impulseY;
        b.m_angularVelocity += b.m_invI * (rX * impulseY - rY * impulseX);
    }
    b2MouseJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        return true;
    }
    Box2D.inherit(b2MouseJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2MouseJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2MouseJointDef.b2MouseJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.target = new b2Vec2();
    };
    b2MouseJointDef.prototype.b2MouseJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_mouseJoint;
        this.maxForce = 0.0;
        this.frequencyHz = 5.0;
        this.dampingRatio = 0.7;
    }
    Box2D.inherit(b2PrismaticJoint, Box2D.Dynamics.Joints.b2Joint);
    b2PrismaticJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2PrismaticJoint.b2PrismaticJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_localAnchor1 = new b2Vec2();
        this.m_localAnchor2 = new b2Vec2();
        this.m_localXAxis1 = new b2Vec2();
        this.m_localYAxis1 = new b2Vec2();
        this.m_axis = new b2Vec2();
        this.m_perp = new b2Vec2();
        this.m_K = new b2Mat33();
        this.m_impulse = new b2Vec3();
    };
    b2PrismaticJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
    }
    b2PrismaticJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
    }
    b2PrismaticJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * (this.m_impulse.x * this.m_perp.x + (this.m_motorImpulse + this.m_impulse.z) * this.m_axis.x), inv_dt * (this.m_impulse.x * this.m_perp.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_axis.y));
    }
    b2PrismaticJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return inv_dt * this.m_impulse.y;
    }
    b2PrismaticJoint.prototype.GetJointTranslation = function () {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var p1 = bA.GetWorldPoint(this.m_localAnchor1);
        var p2 = bB.GetWorldPoint(this.m_localAnchor2);
        var dX = p2.x - p1.x;
        var dY = p2.y - p1.y;
        var axis = bA.GetWorldVector(this.m_localXAxis1);
        var translation = axis.x * dX + axis.y * dY;
        return translation;
    }
    b2PrismaticJoint.prototype.GetJointSpeed = function () {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var p1X = bA.m_sweep.c.x + r1X;
        var p1Y = bA.m_sweep.c.y + r1Y;
        var p2X = bB.m_sweep.c.x + r2X;
        var p2Y = bB.m_sweep.c.y + r2Y;
        var dX = p2X - p1X;
        var dY = p2Y - p1Y;
        var axis = bA.GetWorldVector(this.m_localXAxis1);
        var v1 = bA.m_linearVelocity;
        var v2 = bB.m_linearVelocity;
        var w1 = bA.m_angularVelocity;
        var w2 = bB.m_angularVelocity;
        var speed = (dX * ((-w1 * axis.y)) + dY * (w1 * axis.x)) + (axis.x * (((v2.x + ((-w2 * r2Y))) - v1.x) - ((-w1 * r1Y))) + axis.y * (((v2.y + (w2 * r2X)) - v1.y) - (w1 * r1X)));
        return speed;
    }
    b2PrismaticJoint.prototype.IsLimitEnabled = function () {
        return this.m_enableLimit;
    }
    b2PrismaticJoint.prototype.EnableLimit = function (flag) {
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_enableLimit = flag;
    }
    b2PrismaticJoint.prototype.GetLowerLimit = function () {
        return this.m_lowerTranslation;
    }
    b2PrismaticJoint.prototype.GetUpperLimit = function () {
        return this.m_upperTranslation;
    }
    b2PrismaticJoint.prototype.SetLimits = function (lower, upper) {
        if (lower === undefined) lower = 0;
        if (upper === undefined) upper = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_lowerTranslation = lower;
        this.m_upperTranslation = upper;
    }
    b2PrismaticJoint.prototype.IsMotorEnabled = function () {
        return this.m_enableMotor;
    }
    b2PrismaticJoint.prototype.EnableMotor = function (flag) {
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_enableMotor = flag;
    }
    b2PrismaticJoint.prototype.SetMotorSpeed = function (speed) {
        if (speed === undefined) speed = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_motorSpeed = speed;
    }
    b2PrismaticJoint.prototype.GetMotorSpeed = function () {
        return this.m_motorSpeed;
    }
    b2PrismaticJoint.prototype.SetMaxMotorForce = function (force) {
        if (force === undefined) force = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_maxMotorForce = force;
    }
    b2PrismaticJoint.prototype.GetMotorForce = function () {
        return this.m_motorImpulse;
    }
    b2PrismaticJoint.prototype.b2PrismaticJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        var tMat;
        var tX = 0;
        var tY = 0;
        this.m_localAnchor1.SetV(def.localAnchorA);
        this.m_localAnchor2.SetV(def.localAnchorB);
        this.m_localXAxis1.SetV(def.localAxisA);
        this.m_localYAxis1.x = (-this.m_localXAxis1.y);
        this.m_localYAxis1.y = this.m_localXAxis1.x;
        this.m_refAngle = def.referenceAngle;
        this.m_impulse.SetZero();
        this.m_motorMass = 0.0;
        this.m_motorImpulse = 0.0;
        this.m_lowerTranslation = def.lowerTranslation;
        this.m_upperTranslation = def.upperTranslation;
        this.m_maxMotorForce = def.maxMotorForce;
        this.m_motorSpeed = def.motorSpeed;
        this.m_enableLimit = def.enableLimit;
        this.m_enableMotor = def.enableMotor;
        this.m_limitState = b2Joint.e_inactiveLimit;
        this.m_axis.SetZero();
        this.m_perp.SetZero();
    }
    b2PrismaticJoint.prototype.InitVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var tX = 0;
        this.m_localCenterA.SetV(bA.GetLocalCenter());
        this.m_localCenterB.SetV(bB.GetLocalCenter());
        var xf1 = bA.GetTransform();
        var xf2 = bB.GetTransform();
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - this.m_localCenterA.x;
        var r1Y = this.m_localAnchor1.y - this.m_localCenterA.y;
        tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - this.m_localCenterB.x;
        var r2Y = this.m_localAnchor2.y - this.m_localCenterB.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var dX = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
        var dY = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
        this.m_invMassA = bA.m_invMass;
        this.m_invMassB = bB.m_invMass;
        this.m_invIA = bA.m_invI;
        this.m_invIB = bB.m_invI; {
            this.m_axis.SetV(b2Math.MulMV(xf1.R, this.m_localXAxis1));
            this.m_a1 = (dX + r1X) * this.m_axis.y - (dY + r1Y) * this.m_axis.x;
            this.m_a2 = r2X * this.m_axis.y - r2Y * this.m_axis.x;
            this.m_motorMass = this.m_invMassA + this.m_invMassB + this.m_invIA * this.m_a1 * this.m_a1 + this.m_invIB * this.m_a2 * this.m_a2;
            if (this.m_motorMass > Number.MIN_VALUE) this.m_motorMass = 1.0 / this.m_motorMass;
        } {
            this.m_perp.SetV(b2Math.MulMV(xf1.R, this.m_localYAxis1));
            this.m_s1 = (dX + r1X) * this.m_perp.y - (dY + r1Y) * this.m_perp.x;
            this.m_s2 = r2X * this.m_perp.y - r2Y * this.m_perp.x;
            var m1 = this.m_invMassA;
            var m2 = this.m_invMassB;
            var i1 = this.m_invIA;
            var i2 = this.m_invIB;
            this.m_K.col1.x = m1 + m2 + i1 * this.m_s1 * this.m_s1 + i2 * this.m_s2 * this.m_s2;
            this.m_K.col1.y = i1 * this.m_s1 + i2 * this.m_s2;
            this.m_K.col1.z = i1 * this.m_s1 * this.m_a1 + i2 * this.m_s2 * this.m_a2;
            this.m_K.col2.x = this.m_K.col1.y;
            this.m_K.col2.y = i1 + i2;
            this.m_K.col2.z = i1 * this.m_a1 + i2 * this.m_a2;
            this.m_K.col3.x = this.m_K.col1.z;
            this.m_K.col3.y = this.m_K.col2.z;
            this.m_K.col3.z = m1 + m2 + i1 * this.m_a1 * this.m_a1 + i2 * this.m_a2 * this.m_a2;
        }
        if (this.m_enableLimit) {
            var jointTransition = this.m_axis.x * dX + this.m_axis.y * dY;
            if (b2Math.Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop) {
                this.m_limitState = b2Joint.e_equalLimits;
            }
            else if (jointTransition <= this.m_lowerTranslation) {
                if (this.m_limitState != b2Joint.e_atLowerLimit) {
                    this.m_limitState = b2Joint.e_atLowerLimit;
                    this.m_impulse.z = 0.0;
                }
            }
            else if (jointTransition >= this.m_upperTranslation) {
                if (this.m_limitState != b2Joint.e_atUpperLimit) {
                    this.m_limitState = b2Joint.e_atUpperLimit;
                    this.m_impulse.z = 0.0;
                }
            }
            else {
                this.m_limitState = b2Joint.e_inactiveLimit;
                this.m_impulse.z = 0.0;
            }
        }
        else {
            this.m_limitState = b2Joint.e_inactiveLimit;
        }
        if (this.m_enableMotor == false) {
            this.m_motorImpulse = 0.0;
        }
        if (step.warmStarting) {
            this.m_impulse.x *= step.dtRatio;
            this.m_impulse.y *= step.dtRatio;
            this.m_motorImpulse *= step.dtRatio;
            var PX = this.m_impulse.x * this.m_perp.x + (this.m_motorImpulse + this.m_impulse.z) * this.m_axis.x;
            var PY = this.m_impulse.x * this.m_perp.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_axis.y;
            var L1 = this.m_impulse.x * this.m_s1 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a1;
            var L2 = this.m_impulse.x * this.m_s2 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a2;
            bA.m_linearVelocity.x -= this.m_invMassA * PX;
            bA.m_linearVelocity.y -= this.m_invMassA * PY;
            bA.m_angularVelocity -= this.m_invIA * L1;
            bB.m_linearVelocity.x += this.m_invMassB * PX;
            bB.m_linearVelocity.y += this.m_invMassB * PY;
            bB.m_angularVelocity += this.m_invIB * L2;
        }
        else {
            this.m_impulse.SetZero();
            this.m_motorImpulse = 0.0;
        }
    }
    b2PrismaticJoint.prototype.SolveVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var v1 = bA.m_linearVelocity;
        var w1 = bA.m_angularVelocity;
        var v2 = bB.m_linearVelocity;
        var w2 = bB.m_angularVelocity;
        var PX = 0;
        var PY = 0;
        var L1 = 0;
        var L2 = 0;
        if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) {
            var Cdot = this.m_axis.x * (v2.x - v1.x) + this.m_axis.y * (v2.y - v1.y) + this.m_a2 * w2 - this.m_a1 * w1;
            var impulse = this.m_motorMass * (this.m_motorSpeed - Cdot);
            var oldImpulse = this.m_motorImpulse;
            var maxImpulse = step.dt * this.m_maxMotorForce;
            this.m_motorImpulse = b2Math.Clamp(this.m_motorImpulse + impulse, (-maxImpulse), maxImpulse);
            impulse = this.m_motorImpulse - oldImpulse;
            PX = impulse * this.m_axis.x;
            PY = impulse * this.m_axis.y;
            L1 = impulse * this.m_a1;
            L2 = impulse * this.m_a2;
            v1.x -= this.m_invMassA * PX;
            v1.y -= this.m_invMassA * PY;
            w1 -= this.m_invIA * L1;
            v2.x += this.m_invMassB * PX;
            v2.y += this.m_invMassB * PY;
            w2 += this.m_invIB * L2;
        }
        var Cdot1X = this.m_perp.x * (v2.x - v1.x) + this.m_perp.y * (v2.y - v1.y) + this.m_s2 * w2 - this.m_s1 * w1;
        var Cdot1Y = w2 - w1;
        if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) {
            var Cdot2 = this.m_axis.x * (v2.x - v1.x) + this.m_axis.y * (v2.y - v1.y) + this.m_a2 * w2 - this.m_a1 * w1;
            var f1 = this.m_impulse.Copy();
            var df = this.m_K.Solve33(new b2Vec3(), (-Cdot1X), (-Cdot1Y), (-Cdot2));
            this.m_impulse.Add(df);
            if (this.m_limitState == b2Joint.e_atLowerLimit) {
                this.m_impulse.z = b2Math.Max(this.m_impulse.z, 0.0);
            }
            else if (this.m_limitState == b2Joint.e_atUpperLimit) {
                this.m_impulse.z = b2Math.Min(this.m_impulse.z, 0.0);
            }
            var bX = (-Cdot1X) - (this.m_impulse.z - f1.z) * this.m_K.col3.x;
            var bY = (-Cdot1Y) - (this.m_impulse.z - f1.z) * this.m_K.col3.y;
            var f2r = this.m_K.Solve22(new b2Vec2(), bX, bY);
            f2r.x += f1.x;
            f2r.y += f1.y;
            this.m_impulse.x = f2r.x;
            this.m_impulse.y = f2r.y;
            df.x = this.m_impulse.x - f1.x;
            df.y = this.m_impulse.y - f1.y;
            df.z = this.m_impulse.z - f1.z;
            PX = df.x * this.m_perp.x + df.z * this.m_axis.x;
            PY = df.x * this.m_perp.y + df.z * this.m_axis.y;
            L1 = df.x * this.m_s1 + df.y + df.z * this.m_a1;
            L2 = df.x * this.m_s2 + df.y + df.z * this.m_a2;
            v1.x -= this.m_invMassA * PX;
            v1.y -= this.m_invMassA * PY;
            w1 -= this.m_invIA * L1;
            v2.x += this.m_invMassB * PX;
            v2.y += this.m_invMassB * PY;
            w2 += this.m_invIB * L2;
        }
        else {
            var df2 = this.m_K.Solve22(new b2Vec2(), (-Cdot1X), (-Cdot1Y));
            this.m_impulse.x += df2.x;
            this.m_impulse.y += df2.y;
            PX = df2.x * this.m_perp.x;
            PY = df2.x * this.m_perp.y;
            L1 = df2.x * this.m_s1 + df2.y;
            L2 = df2.x * this.m_s2 + df2.y;
            v1.x -= this.m_invMassA * PX;
            v1.y -= this.m_invMassA * PY;
            w1 -= this.m_invIA * L1;
            v2.x += this.m_invMassB * PX;
            v2.y += this.m_invMassB * PY;
            w2 += this.m_invIB * L2;
        }
        bA.m_linearVelocity.SetV(v1);
        bA.m_angularVelocity = w1;
        bB.m_linearVelocity.SetV(v2);
        bB.m_angularVelocity = w2;
    }
    b2PrismaticJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var limitC = 0;
        var oldLimitImpulse = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var c1 = bA.m_sweep.c;
        var a1 = bA.m_sweep.a;
        var c2 = bB.m_sweep.c;
        var a2 = bB.m_sweep.a;
        var tMat;
        var tX = 0;
        var m1 = 0;
        var m2 = 0;
        var i1 = 0;
        var i2 = 0;
        var linearError = 0.0;
        var angularError = 0.0;
        var active = false;
        var C2 = 0.0;
        var R1 = b2Mat22.FromAngle(a1);
        var R2 = b2Mat22.FromAngle(a2);
        tMat = R1;
        var r1X = this.m_localAnchor1.x - this.m_localCenterA.x;
        var r1Y = this.m_localAnchor1.y - this.m_localCenterA.y;
        tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = R2;
        var r2X = this.m_localAnchor2.x - this.m_localCenterB.x;
        var r2Y = this.m_localAnchor2.y - this.m_localCenterB.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var dX = c2.x + r2X - c1.x - r1X;
        var dY = c2.y + r2Y - c1.y - r1Y;
        if (this.m_enableLimit) {
            this.m_axis = b2Math.MulMV(R1, this.m_localXAxis1);
            this.m_a1 = (dX + r1X) * this.m_axis.y - (dY + r1Y) * this.m_axis.x;
            this.m_a2 = r2X * this.m_axis.y - r2Y * this.m_axis.x;
            var translation = this.m_axis.x * dX + this.m_axis.y * dY;
            if (b2Math.Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * b2Settings.b2_linearSlop) {
                C2 = b2Math.Clamp(translation, (-b2Settings.b2_maxLinearCorrection), b2Settings.b2_maxLinearCorrection);
                linearError = b2Math.Abs(translation);
                active = true;
            }
            else if (translation <= this.m_lowerTranslation) {
                C2 = b2Math.Clamp(translation - this.m_lowerTranslation + b2Settings.b2_linearSlop, (-b2Settings.b2_maxLinearCorrection), 0.0);
                linearError = this.m_lowerTranslation - translation;
                active = true;
            }
            else if (translation >= this.m_upperTranslation) {
                C2 = b2Math.Clamp(translation - this.m_upperTranslation + b2Settings.b2_linearSlop, 0.0, b2Settings.b2_maxLinearCorrection);
                linearError = translation - this.m_upperTranslation;
                active = true;
            }
        }
        this.m_perp = b2Math.MulMV(R1, this.m_localYAxis1);
        this.m_s1 = (dX + r1X) * this.m_perp.y - (dY + r1Y) * this.m_perp.x;
        this.m_s2 = r2X * this.m_perp.y - r2Y * this.m_perp.x;
        var impulse = new b2Vec3();
        var C1X = this.m_perp.x * dX + this.m_perp.y * dY;
        var C1Y = a2 - a1 - this.m_refAngle;
        linearError = b2Math.Max(linearError, b2Math.Abs(C1X));
        angularError = b2Math.Abs(C1Y);
        if (active) {
            m1 = this.m_invMassA;
            m2 = this.m_invMassB;
            i1 = this.m_invIA;
            i2 = this.m_invIB;
            this.m_K.col1.x = m1 + m2 + i1 * this.m_s1 * this.m_s1 + i2 * this.m_s2 * this.m_s2;
            this.m_K.col1.y = i1 * this.m_s1 + i2 * this.m_s2;
            this.m_K.col1.z = i1 * this.m_s1 * this.m_a1 + i2 * this.m_s2 * this.m_a2;
            this.m_K.col2.x = this.m_K.col1.y;
            this.m_K.col2.y = i1 + i2;
            this.m_K.col2.z = i1 * this.m_a1 + i2 * this.m_a2;
            this.m_K.col3.x = this.m_K.col1.z;
            this.m_K.col3.y = this.m_K.col2.z;
            this.m_K.col3.z = m1 + m2 + i1 * this.m_a1 * this.m_a1 + i2 * this.m_a2 * this.m_a2;
            this.m_K.Solve33(impulse, (-C1X), (-C1Y), (-C2));
        }
        else {
            m1 = this.m_invMassA;
            m2 = this.m_invMassB;
            i1 = this.m_invIA;
            i2 = this.m_invIB;
            var k11 = m1 + m2 + i1 * this.m_s1 * this.m_s1 + i2 * this.m_s2 * this.m_s2;
            var k12 = i1 * this.m_s1 + i2 * this.m_s2;
            var k22 = i1 + i2;
            this.m_K.col1.Set(k11, k12, 0.0);
            this.m_K.col2.Set(k12, k22, 0.0);
            var impulse1 = this.m_K.Solve22(new b2Vec2(), (-C1X), (-C1Y));
            impulse.x = impulse1.x;
            impulse.y = impulse1.y;
            impulse.z = 0.0;
        }
        var PX = impulse.x * this.m_perp.x + impulse.z * this.m_axis.x;
        var PY = impulse.x * this.m_perp.y + impulse.z * this.m_axis.y;
        var L1 = impulse.x * this.m_s1 + impulse.y + impulse.z * this.m_a1;
        var L2 = impulse.x * this.m_s2 + impulse.y + impulse.z * this.m_a2;
        c1.x -= this.m_invMassA * PX;
        c1.y -= this.m_invMassA * PY;
        a1 -= this.m_invIA * L1;
        c2.x += this.m_invMassB * PX;
        c2.y += this.m_invMassB * PY;
        a2 += this.m_invIB * L2;
        bA.m_sweep.a = a1;
        bB.m_sweep.a = a2;
        bA.SynchronizeTransform();
        bB.SynchronizeTransform();
        return linearError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
    }
    Box2D.inherit(b2PrismaticJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2PrismaticJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2PrismaticJointDef.b2PrismaticJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
        this.localAxisA = new b2Vec2();
    };
    b2PrismaticJointDef.prototype.b2PrismaticJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_prismaticJoint;
        this.localAxisA.Set(1.0, 0.0);
        this.referenceAngle = 0.0;
        this.enableLimit = false;
        this.lowerTranslation = 0.0;
        this.upperTranslation = 0.0;
        this.enableMotor = false;
        this.maxMotorForce = 0.0;
        this.motorSpeed = 0.0;
    }
    b2PrismaticJointDef.prototype.Initialize = function (bA, bB, anchor, axis) {
        this.bodyA = bA;
        this.bodyB = bB;
        this.localAnchorA = this.bodyA.GetLocalPoint(anchor);
        this.localAnchorB = this.bodyB.GetLocalPoint(anchor);
        this.localAxisA = this.bodyA.GetLocalVector(axis);
        this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle();
    }
    Box2D.inherit(b2PulleyJoint, Box2D.Dynamics.Joints.b2Joint);
    b2PulleyJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2PulleyJoint.b2PulleyJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_groundAnchor1 = new b2Vec2();
        this.m_groundAnchor2 = new b2Vec2();
        this.m_localAnchor1 = new b2Vec2();
        this.m_localAnchor2 = new b2Vec2();
        this.m_u1 = new b2Vec2();
        this.m_u2 = new b2Vec2();
    };
    b2PulleyJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
    }
    b2PulleyJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
    }
    b2PulleyJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_impulse * this.m_u2.x, inv_dt * this.m_impulse * this.m_u2.y);
    }
    b2PulleyJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return 0.0;
    }
    b2PulleyJoint.prototype.GetGroundAnchorA = function () {
        var a = this.m_ground.m_xf.position.Copy();
        a.Add(this.m_groundAnchor1);
        return a;
    }
    b2PulleyJoint.prototype.GetGroundAnchorB = function () {
        var a = this.m_ground.m_xf.position.Copy();
        a.Add(this.m_groundAnchor2);
        return a;
    }
    b2PulleyJoint.prototype.GetLength1 = function () {
        var p = this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
        var sX = this.m_ground.m_xf.position.x + this.m_groundAnchor1.x;
        var sY = this.m_ground.m_xf.position.y + this.m_groundAnchor1.y;
        var dX = p.x - sX;
        var dY = p.y - sY;
        return Math.sqrt(dX * dX + dY * dY);
    }
    b2PulleyJoint.prototype.GetLength2 = function () {
        var p = this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
        var sX = this.m_ground.m_xf.position.x + this.m_groundAnchor2.x;
        var sY = this.m_ground.m_xf.position.y + this.m_groundAnchor2.y;
        var dX = p.x - sX;
        var dY = p.y - sY;
        return Math.sqrt(dX * dX + dY * dY);
    }
    b2PulleyJoint.prototype.GetRatio = function () {
        return this.m_ratio;
    }
    b2PulleyJoint.prototype.b2PulleyJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        var tMat;
        var tX = 0;
        var tY = 0;
        this.m_ground = this.m_bodyA.m_world.m_groundBody;
        this.m_groundAnchor1.x = def.groundAnchorA.x - this.m_ground.m_xf.position.x;
        this.m_groundAnchor1.y = def.groundAnchorA.y - this.m_ground.m_xf.position.y;
        this.m_groundAnchor2.x = def.groundAnchorB.x - this.m_ground.m_xf.position.x;
        this.m_groundAnchor2.y = def.groundAnchorB.y - this.m_ground.m_xf.position.y;
        this.m_localAnchor1.SetV(def.localAnchorA);
        this.m_localAnchor2.SetV(def.localAnchorB);
        this.m_ratio = def.ratio;
        this.m_constant = def.lengthA + this.m_ratio * def.lengthB;
        this.m_maxLength1 = b2Math.Min(def.maxLengthA, this.m_constant - this.m_ratio * b2PulleyJoint.b2_minPulleyLength);
        this.m_maxLength2 = b2Math.Min(def.maxLengthB, (this.m_constant - b2PulleyJoint.b2_minPulleyLength) / this.m_ratio);
        this.m_impulse = 0.0;
        this.m_limitImpulse1 = 0.0;
        this.m_limitImpulse2 = 0.0;
    }
    b2PulleyJoint.prototype.InitVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var p1X = bA.m_sweep.c.x + r1X;
        var p1Y = bA.m_sweep.c.y + r1Y;
        var p2X = bB.m_sweep.c.x + r2X;
        var p2Y = bB.m_sweep.c.y + r2Y;
        var s1X = this.m_ground.m_xf.position.x + this.m_groundAnchor1.x;
        var s1Y = this.m_ground.m_xf.position.y + this.m_groundAnchor1.y;
        var s2X = this.m_ground.m_xf.position.x + this.m_groundAnchor2.x;
        var s2Y = this.m_ground.m_xf.position.y + this.m_groundAnchor2.y;
        this.m_u1.Set(p1X - s1X, p1Y - s1Y);
        this.m_u2.Set(p2X - s2X, p2Y - s2Y);
        var length1 = this.m_u1.Length();
        var length2 = this.m_u2.Length();
        if (length1 > b2Settings.b2_linearSlop) {
            this.m_u1.Multiply(1.0 / length1);
        }
        else {
            this.m_u1.SetZero();
        }
        if (length2 > b2Settings.b2_linearSlop) {
            this.m_u2.Multiply(1.0 / length2);
        }
        else {
            this.m_u2.SetZero();
        }
        var C = this.m_constant - length1 - this.m_ratio * length2;
        if (C > 0.0) {
            this.m_state = b2Joint.e_inactiveLimit;
            this.m_impulse = 0.0;
        }
        else {
            this.m_state = b2Joint.e_atUpperLimit;
        }
        if (length1 < this.m_maxLength1) {
            this.m_limitState1 = b2Joint.e_inactiveLimit;
            this.m_limitImpulse1 = 0.0;
        }
        else {
            this.m_limitState1 = b2Joint.e_atUpperLimit;
        }
        if (length2 < this.m_maxLength2) {
            this.m_limitState2 = b2Joint.e_inactiveLimit;
            this.m_limitImpulse2 = 0.0;
        }
        else {
            this.m_limitState2 = b2Joint.e_atUpperLimit;
        }
        var cr1u1 = r1X * this.m_u1.y - r1Y * this.m_u1.x;
        var cr2u2 = r2X * this.m_u2.y - r2Y * this.m_u2.x;
        this.m_limitMass1 = bA.m_invMass + bA.m_invI * cr1u1 * cr1u1;
        this.m_limitMass2 = bB.m_invMass + bB.m_invI * cr2u2 * cr2u2;
        this.m_pulleyMass = this.m_limitMass1 + this.m_ratio * this.m_ratio * this.m_limitMass2;
        this.m_limitMass1 = 1.0 / this.m_limitMass1;
        this.m_limitMass2 = 1.0 / this.m_limitMass2;
        this.m_pulleyMass = 1.0 / this.m_pulleyMass;
        if (step.warmStarting) {
            this.m_impulse *= step.dtRatio;
            this.m_limitImpulse1 *= step.dtRatio;
            this.m_limitImpulse2 *= step.dtRatio;
            var P1X = ((-this.m_impulse) - this.m_limitImpulse1) * this.m_u1.x;
            var P1Y = ((-this.m_impulse) - this.m_limitImpulse1) * this.m_u1.y;
            var P2X = ((-this.m_ratio * this.m_impulse) - this.m_limitImpulse2) * this.m_u2.x;
            var P2Y = ((-this.m_ratio * this.m_impulse) - this.m_limitImpulse2) * this.m_u2.y;
            bA.m_linearVelocity.x += bA.m_invMass * P1X;
            bA.m_linearVelocity.y += bA.m_invMass * P1Y;
            bA.m_angularVelocity += bA.m_invI * (r1X * P1Y - r1Y * P1X);
            bB.m_linearVelocity.x += bB.m_invMass * P2X;
            bB.m_linearVelocity.y += bB.m_invMass * P2Y;
            bB.m_angularVelocity += bB.m_invI * (r2X * P2Y - r2Y * P2X);
        }
        else {
            this.m_impulse = 0.0;
            this.m_limitImpulse1 = 0.0;
            this.m_limitImpulse2 = 0.0;
        }
    }
    b2PulleyJoint.prototype.SolveVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        var tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var v1X = 0;
        var v1Y = 0;
        var v2X = 0;
        var v2Y = 0;
        var P1X = 0;
        var P1Y = 0;
        var P2X = 0;
        var P2Y = 0;
        var Cdot = 0;
        var impulse = 0;
        var oldImpulse = 0;
        if (this.m_state == b2Joint.e_atUpperLimit) {
            v1X = bA.m_linearVelocity.x + ((-bA.m_angularVelocity * r1Y));
            v1Y = bA.m_linearVelocity.y + (bA.m_angularVelocity * r1X);
            v2X = bB.m_linearVelocity.x + ((-bB.m_angularVelocity * r2Y));
            v2Y = bB.m_linearVelocity.y + (bB.m_angularVelocity * r2X);
            Cdot = (-(this.m_u1.x * v1X + this.m_u1.y * v1Y)) - this.m_ratio * (this.m_u2.x * v2X + this.m_u2.y * v2Y);
            impulse = this.m_pulleyMass * ((-Cdot));
            oldImpulse = this.m_impulse;
            this.m_impulse = b2Math.Max(0.0, this.m_impulse + impulse);
            impulse = this.m_impulse - oldImpulse;
            P1X = (-impulse * this.m_u1.x);
            P1Y = (-impulse * this.m_u1.y);
            P2X = (-this.m_ratio * impulse * this.m_u2.x);
            P2Y = (-this.m_ratio * impulse * this.m_u2.y);
            bA.m_linearVelocity.x += bA.m_invMass * P1X;
            bA.m_linearVelocity.y += bA.m_invMass * P1Y;
            bA.m_angularVelocity += bA.m_invI * (r1X * P1Y - r1Y * P1X);
            bB.m_linearVelocity.x += bB.m_invMass * P2X;
            bB.m_linearVelocity.y += bB.m_invMass * P2Y;
            bB.m_angularVelocity += bB.m_invI * (r2X * P2Y - r2Y * P2X);
        }
        if (this.m_limitState1 == b2Joint.e_atUpperLimit) {
            v1X = bA.m_linearVelocity.x + ((-bA.m_angularVelocity * r1Y));
            v1Y = bA.m_linearVelocity.y + (bA.m_angularVelocity * r1X);
            Cdot = (-(this.m_u1.x * v1X + this.m_u1.y * v1Y));
            impulse = (-this.m_limitMass1 * Cdot);
            oldImpulse = this.m_limitImpulse1;
            this.m_limitImpulse1 = b2Math.Max(0.0, this.m_limitImpulse1 + impulse);
            impulse = this.m_limitImpulse1 - oldImpulse;
            P1X = (-impulse * this.m_u1.x);
            P1Y = (-impulse * this.m_u1.y);
            bA.m_linearVelocity.x += bA.m_invMass * P1X;
            bA.m_linearVelocity.y += bA.m_invMass * P1Y;
            bA.m_angularVelocity += bA.m_invI * (r1X * P1Y - r1Y * P1X);
        }
        if (this.m_limitState2 == b2Joint.e_atUpperLimit) {
            v2X = bB.m_linearVelocity.x + ((-bB.m_angularVelocity * r2Y));
            v2Y = bB.m_linearVelocity.y + (bB.m_angularVelocity * r2X);
            Cdot = (-(this.m_u2.x * v2X + this.m_u2.y * v2Y));
            impulse = (-this.m_limitMass2 * Cdot);
            oldImpulse = this.m_limitImpulse2;
            this.m_limitImpulse2 = b2Math.Max(0.0, this.m_limitImpulse2 + impulse);
            impulse = this.m_limitImpulse2 - oldImpulse;
            P2X = (-impulse * this.m_u2.x);
            P2Y = (-impulse * this.m_u2.y);
            bB.m_linearVelocity.x += bB.m_invMass * P2X;
            bB.m_linearVelocity.y += bB.m_invMass * P2Y;
            bB.m_angularVelocity += bB.m_invI * (r2X * P2Y - r2Y * P2X);
        }
    }
    b2PulleyJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var s1X = this.m_ground.m_xf.position.x + this.m_groundAnchor1.x;
        var s1Y = this.m_ground.m_xf.position.y + this.m_groundAnchor1.y;
        var s2X = this.m_ground.m_xf.position.x + this.m_groundAnchor2.x;
        var s2Y = this.m_ground.m_xf.position.y + this.m_groundAnchor2.y;
        var r1X = 0;
        var r1Y = 0;
        var r2X = 0;
        var r2Y = 0;
        var p1X = 0;
        var p1Y = 0;
        var p2X = 0;
        var p2Y = 0;
        var length1 = 0;
        var length2 = 0;
        var C = 0;
        var impulse = 0;
        var oldImpulse = 0;
        var oldLimitPositionImpulse = 0;
        var tX = 0;
        var linearError = 0.0;
        if (this.m_state == b2Joint.e_atUpperLimit) {
            tMat = bA.m_xf.R;
            r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
            r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
            r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
            r1X = tX;
            tMat = bB.m_xf.R;
            r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
            r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
            r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
            r2X = tX;
            p1X = bA.m_sweep.c.x + r1X;
            p1Y = bA.m_sweep.c.y + r1Y;
            p2X = bB.m_sweep.c.x + r2X;
            p2Y = bB.m_sweep.c.y + r2Y;
            this.m_u1.Set(p1X - s1X, p1Y - s1Y);
            this.m_u2.Set(p2X - s2X, p2Y - s2Y);
            length1 = this.m_u1.Length();
            length2 = this.m_u2.Length();
            if (length1 > b2Settings.b2_linearSlop) {
                this.m_u1.Multiply(1.0 / length1);
            }
            else {
                this.m_u1.SetZero();
            }
            if (length2 > b2Settings.b2_linearSlop) {
                this.m_u2.Multiply(1.0 / length2);
            }
            else {
                this.m_u2.SetZero();
            }
            C = this.m_constant - length1 - this.m_ratio * length2;
            linearError = b2Math.Max(linearError, (-C));
            C = b2Math.Clamp(C + b2Settings.b2_linearSlop, (-b2Settings.b2_maxLinearCorrection), 0.0);
            impulse = (-this.m_pulleyMass * C);
            p1X = (-impulse * this.m_u1.x);
            p1Y = (-impulse * this.m_u1.y);
            p2X = (-this.m_ratio * impulse * this.m_u2.x);
            p2Y = (-this.m_ratio * impulse * this.m_u2.y);
            bA.m_sweep.c.x += bA.m_invMass * p1X;
            bA.m_sweep.c.y += bA.m_invMass * p1Y;
            bA.m_sweep.a += bA.m_invI * (r1X * p1Y - r1Y * p1X);
            bB.m_sweep.c.x += bB.m_invMass * p2X;
            bB.m_sweep.c.y += bB.m_invMass * p2Y;
            bB.m_sweep.a += bB.m_invI * (r2X * p2Y - r2Y * p2X);
            bA.SynchronizeTransform();
            bB.SynchronizeTransform();
        }
        if (this.m_limitState1 == b2Joint.e_atUpperLimit) {
            tMat = bA.m_xf.R;
            r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
            r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
            r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
            r1X = tX;
            p1X = bA.m_sweep.c.x + r1X;
            p1Y = bA.m_sweep.c.y + r1Y;
            this.m_u1.Set(p1X - s1X, p1Y - s1Y);
            length1 = this.m_u1.Length();
            if (length1 > b2Settings.b2_linearSlop) {
                this.m_u1.x *= 1.0 / length1;
                this.m_u1.y *= 1.0 / length1;
            }
            else {
                this.m_u1.SetZero();
            }
            C = this.m_maxLength1 - length1;
            linearError = b2Math.Max(linearError, (-C));
            C = b2Math.Clamp(C + b2Settings.b2_linearSlop, (-b2Settings.b2_maxLinearCorrection), 0.0);
            impulse = (-this.m_limitMass1 * C);
            p1X = (-impulse * this.m_u1.x);
            p1Y = (-impulse * this.m_u1.y);
            bA.m_sweep.c.x += bA.m_invMass * p1X;
            bA.m_sweep.c.y += bA.m_invMass * p1Y;
            bA.m_sweep.a += bA.m_invI * (r1X * p1Y - r1Y * p1X);
            bA.SynchronizeTransform();
        }
        if (this.m_limitState2 == b2Joint.e_atUpperLimit) {
            tMat = bB.m_xf.R;
            r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
            r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
            r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
            r2X = tX;
            p2X = bB.m_sweep.c.x + r2X;
            p2Y = bB.m_sweep.c.y + r2Y;
            this.m_u2.Set(p2X - s2X, p2Y - s2Y);
            length2 = this.m_u2.Length();
            if (length2 > b2Settings.b2_linearSlop) {
                this.m_u2.x *= 1.0 / length2;
                this.m_u2.y *= 1.0 / length2;
            }
            else {
                this.m_u2.SetZero();
            }
            C = this.m_maxLength2 - length2;
            linearError = b2Math.Max(linearError, (-C));
            C = b2Math.Clamp(C + b2Settings.b2_linearSlop, (-b2Settings.b2_maxLinearCorrection), 0.0);
            impulse = (-this.m_limitMass2 * C);
            p2X = (-impulse * this.m_u2.x);
            p2Y = (-impulse * this.m_u2.y);
            bB.m_sweep.c.x += bB.m_invMass * p2X;
            bB.m_sweep.c.y += bB.m_invMass * p2Y;
            bB.m_sweep.a += bB.m_invI * (r2X * p2Y - r2Y * p2X);
            bB.SynchronizeTransform();
        }
        return linearError < b2Settings.b2_linearSlop;
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.Joints.b2PulleyJoint.b2_minPulleyLength = 2.0;
    });
    Box2D.inherit(b2PulleyJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2PulleyJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2PulleyJointDef.b2PulleyJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.groundAnchorA = new b2Vec2();
        this.groundAnchorB = new b2Vec2();
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
    };
    b2PulleyJointDef.prototype.b2PulleyJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_pulleyJoint;
        this.groundAnchorA.Set((-1.0), 1.0);
        this.groundAnchorB.Set(1.0, 1.0);
        this.localAnchorA.Set((-1.0), 0.0);
        this.localAnchorB.Set(1.0, 0.0);
        this.lengthA = 0.0;
        this.maxLengthA = 0.0;
        this.lengthB = 0.0;
        this.maxLengthB = 0.0;
        this.ratio = 1.0;
        this.collideConnected = true;
    }
    b2PulleyJointDef.prototype.Initialize = function (bA, bB, gaA, gaB, anchorA, anchorB, r) {
        if (r === undefined) r = 0;
        this.bodyA = bA;
        this.bodyB = bB;
        this.groundAnchorA.SetV(gaA);
        this.groundAnchorB.SetV(gaB);
        this.localAnchorA = this.bodyA.GetLocalPoint(anchorA);
        this.localAnchorB = this.bodyB.GetLocalPoint(anchorB);
        var d1X = anchorA.x - gaA.x;
        var d1Y = anchorA.y - gaA.y;
        this.lengthA = Math.sqrt(d1X * d1X + d1Y * d1Y);
        var d2X = anchorB.x - gaB.x;
        var d2Y = anchorB.y - gaB.y;
        this.lengthB = Math.sqrt(d2X * d2X + d2Y * d2Y);
        this.ratio = r;
        var C = this.lengthA + this.ratio * this.lengthB;
        this.maxLengthA = C - this.ratio * b2PulleyJoint.b2_minPulleyLength;
        this.maxLengthB = (C - b2PulleyJoint.b2_minPulleyLength) / this.ratio;
    }
    Box2D.inherit(b2RevoluteJoint, Box2D.Dynamics.Joints.b2Joint);
    b2RevoluteJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2RevoluteJoint.b2RevoluteJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.K = new b2Mat22();
        this.K1 = new b2Mat22();
        this.K2 = new b2Mat22();
        this.K3 = new b2Mat22();
        this.impulse3 = new b2Vec3();
        this.impulse2 = new b2Vec2();
        this.reduced = new b2Vec2();
        this.m_localAnchor1 = new b2Vec2();
        this.m_localAnchor2 = new b2Vec2();
        this.m_impulse = new b2Vec3();
        this.m_mass = new b2Mat33();
    };
    b2RevoluteJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchor1);
    }
    b2RevoluteJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchor2);
    }
    b2RevoluteJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_impulse.x, inv_dt * this.m_impulse.y);
    }
    b2RevoluteJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return inv_dt * this.m_impulse.z;
    }
    b2RevoluteJoint.prototype.GetJointAngle = function () {
        return this.m_bodyB.m_sweep.a - this.m_bodyA.m_sweep.a - this.m_referenceAngle;
    }
    b2RevoluteJoint.prototype.GetJointSpeed = function () {
        return this.m_bodyB.m_angularVelocity - this.m_bodyA.m_angularVelocity;
    }
    b2RevoluteJoint.prototype.IsLimitEnabled = function () {
        return this.m_enableLimit;
    }
    b2RevoluteJoint.prototype.EnableLimit = function (flag) {
        this.m_enableLimit = flag;
    }
    b2RevoluteJoint.prototype.GetLowerLimit = function () {
        return this.m_lowerAngle;
    }
    b2RevoluteJoint.prototype.GetUpperLimit = function () {
        return this.m_upperAngle;
    }
    b2RevoluteJoint.prototype.SetLimits = function (lower, upper) {
        if (lower === undefined) lower = 0;
        if (upper === undefined) upper = 0;
        this.m_lowerAngle = lower;
        this.m_upperAngle = upper;
    }
    b2RevoluteJoint.prototype.IsMotorEnabled = function () {
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        return this.m_enableMotor;
    }
    b2RevoluteJoint.prototype.EnableMotor = function (flag) {
        this.m_enableMotor = flag;
    }
    b2RevoluteJoint.prototype.SetMotorSpeed = function (speed) {
        if (speed === undefined) speed = 0;
        this.m_bodyA.SetAwake(true);
        this.m_bodyB.SetAwake(true);
        this.m_motorSpeed = speed;
    }
    b2RevoluteJoint.prototype.GetMotorSpeed = function () {
        return this.m_motorSpeed;
    }
    b2RevoluteJoint.prototype.SetMaxMotorTorque = function (torque) {
        if (torque === undefined) torque = 0;
        this.m_maxMotorTorque = torque;
    }
    b2RevoluteJoint.prototype.GetMotorTorque = function () {
        return this.m_maxMotorTorque;
    }
    b2RevoluteJoint.prototype.b2RevoluteJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        this.m_localAnchor1.SetV(def.localAnchorA);
        this.m_localAnchor2.SetV(def.localAnchorB);
        this.m_referenceAngle = def.referenceAngle;
        this.m_impulse.SetZero();
        this.m_motorImpulse = 0.0;
        this.m_lowerAngle = def.lowerAngle;
        this.m_upperAngle = def.upperAngle;
        this.m_maxMotorTorque = def.maxMotorTorque;
        this.m_motorSpeed = def.motorSpeed;
        this.m_enableLimit = def.enableLimit;
        this.m_enableMotor = def.enableMotor;
        this.m_limitState = b2Joint.e_inactiveLimit;
    }
    b2RevoluteJoint.prototype.InitVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var tX = 0;
        if (this.m_enableMotor || this.m_enableLimit) {}
        tMat = bA.m_xf.R;
        var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
        var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
        r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
        r1X = tX;
        tMat = bB.m_xf.R;
        var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
        var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
        r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
        r2X = tX;
        var m1 = bA.m_invMass;
        var m2 = bB.m_invMass;
        var i1 = bA.m_invI;
        var i2 = bB.m_invI;
        this.m_mass.col1.x = m1 + m2 + r1Y * r1Y * i1 + r2Y * r2Y * i2;
        this.m_mass.col2.x = (-r1Y * r1X * i1) - r2Y * r2X * i2;
        this.m_mass.col3.x = (-r1Y * i1) - r2Y * i2;
        this.m_mass.col1.y = this.m_mass.col2.x;
        this.m_mass.col2.y = m1 + m2 + r1X * r1X * i1 + r2X * r2X * i2;
        this.m_mass.col3.y = r1X * i1 + r2X * i2;
        this.m_mass.col1.z = this.m_mass.col3.x;
        this.m_mass.col2.z = this.m_mass.col3.y;
        this.m_mass.col3.z = i1 + i2;
        this.m_motorMass = 1.0 / (i1 + i2);
        if (this.m_enableMotor == false) {
            this.m_motorImpulse = 0.0;
        }
        if (this.m_enableLimit) {
            var jointAngle = bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle;
            if (b2Math.Abs(this.m_upperAngle - this.m_lowerAngle) < 2.0 * b2Settings.b2_angularSlop) {
                this.m_limitState = b2Joint.e_equalLimits;
            }
            else if (jointAngle <= this.m_lowerAngle) {
                if (this.m_limitState != b2Joint.e_atLowerLimit) {
                    this.m_impulse.z = 0.0;
                }
                this.m_limitState = b2Joint.e_atLowerLimit;
            }
            else if (jointAngle >= this.m_upperAngle) {
                if (this.m_limitState != b2Joint.e_atUpperLimit) {
                    this.m_impulse.z = 0.0;
                }
                this.m_limitState = b2Joint.e_atUpperLimit;
            }
            else {
                this.m_limitState = b2Joint.e_inactiveLimit;
                this.m_impulse.z = 0.0;
            }
        }
        else {
            this.m_limitState = b2Joint.e_inactiveLimit;
        }
        if (step.warmStarting) {
            this.m_impulse.x *= step.dtRatio;
            this.m_impulse.y *= step.dtRatio;
            this.m_motorImpulse *= step.dtRatio;
            var PX = this.m_impulse.x;
            var PY = this.m_impulse.y;
            bA.m_linearVelocity.x -= m1 * PX;
            bA.m_linearVelocity.y -= m1 * PY;
            bA.m_angularVelocity -= i1 * ((r1X * PY - r1Y * PX) + this.m_motorImpulse + this.m_impulse.z);
            bB.m_linearVelocity.x += m2 * PX;
            bB.m_linearVelocity.y += m2 * PY;
            bB.m_angularVelocity += i2 * ((r2X * PY - r2Y * PX) + this.m_motorImpulse + this.m_impulse.z);
        }
        else {
            this.m_impulse.SetZero();
            this.m_motorImpulse = 0.0;
        }
    }
    b2RevoluteJoint.prototype.SolveVelocityConstraints = function (step) {
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var tMat;
        var tX = 0;
        var newImpulse = 0;
        var r1X = 0;
        var r1Y = 0;
        var r2X = 0;
        var r2Y = 0;
        var v1 = bA.m_linearVelocity;
        var w1 = bA.m_angularVelocity;
        var v2 = bB.m_linearVelocity;
        var w2 = bB.m_angularVelocity;
        var m1 = bA.m_invMass;
        var m2 = bB.m_invMass;
        var i1 = bA.m_invI;
        var i2 = bB.m_invI;
        if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) {
            var Cdot = w2 - w1 - this.m_motorSpeed;
            var impulse = this.m_motorMass * ((-Cdot));
            var oldImpulse = this.m_motorImpulse;
            var maxImpulse = step.dt * this.m_maxMotorTorque;
            this.m_motorImpulse = b2Math.Clamp(this.m_motorImpulse + impulse, (-maxImpulse), maxImpulse);
            impulse = this.m_motorImpulse - oldImpulse;
            w1 -= i1 * impulse;
            w2 += i2 * impulse;
        }
        if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) {
            tMat = bA.m_xf.R;
            r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
            r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
            r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
            r1X = tX;
            tMat = bB.m_xf.R;
            r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
            r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
            r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
            r2X = tX;
            var Cdot1X = v2.x + ((-w2 * r2Y)) - v1.x - ((-w1 * r1Y));
            var Cdot1Y = v2.y + (w2 * r2X) - v1.y - (w1 * r1X);
            var Cdot2 = w2 - w1;
            this.m_mass.Solve33(this.impulse3, (-Cdot1X), (-Cdot1Y), (-Cdot2));
            if (this.m_limitState == b2Joint.e_equalLimits) {
                this.m_impulse.Add(this.impulse3);
            }
            else if (this.m_limitState == b2Joint.e_atLowerLimit) {
                newImpulse = this.m_impulse.z + this.impulse3.z;
                if (newImpulse < 0.0) {
                    this.m_mass.Solve22(this.reduced, (-Cdot1X), (-Cdot1Y));
                    this.impulse3.x = this.reduced.x;
                    this.impulse3.y = this.reduced.y;
                    this.impulse3.z = (-this.m_impulse.z);
                    this.m_impulse.x += this.reduced.x;
                    this.m_impulse.y += this.reduced.y;
                    this.m_impulse.z = 0.0;
                }
            }
            else if (this.m_limitState == b2Joint.e_atUpperLimit) {
                newImpulse = this.m_impulse.z + this.impulse3.z;
                if (newImpulse > 0.0) {
                    this.m_mass.Solve22(this.reduced, (-Cdot1X), (-Cdot1Y));
                    this.impulse3.x = this.reduced.x;
                    this.impulse3.y = this.reduced.y;
                    this.impulse3.z = (-this.m_impulse.z);
                    this.m_impulse.x += this.reduced.x;
                    this.m_impulse.y += this.reduced.y;
                    this.m_impulse.z = 0.0;
                }
            }
            v1.x -= m1 * this.impulse3.x;
            v1.y -= m1 * this.impulse3.y;
            w1 -= i1 * (r1X * this.impulse3.y - r1Y * this.impulse3.x + this.impulse3.z);
            v2.x += m2 * this.impulse3.x;
            v2.y += m2 * this.impulse3.y;
            w2 += i2 * (r2X * this.impulse3.y - r2Y * this.impulse3.x + this.impulse3.z);
        }
        else {
            tMat = bA.m_xf.R;
            r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
            r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
            r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
            r1X = tX;
            tMat = bB.m_xf.R;
            r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
            r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
            r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
            r2X = tX;
            var CdotX = v2.x + ((-w2 * r2Y)) - v1.x - ((-w1 * r1Y));
            var CdotY = v2.y + (w2 * r2X) - v1.y - (w1 * r1X);
            this.m_mass.Solve22(this.impulse2, (-CdotX), (-CdotY));
            this.m_impulse.x += this.impulse2.x;
            this.m_impulse.y += this.impulse2.y;
            v1.x -= m1 * this.impulse2.x;
            v1.y -= m1 * this.impulse2.y;
            w1 -= i1 * (r1X * this.impulse2.y - r1Y * this.impulse2.x);
            v2.x += m2 * this.impulse2.x;
            v2.y += m2 * this.impulse2.y;
            w2 += i2 * (r2X * this.impulse2.y - r2Y * this.impulse2.x);
        }
        bA.m_linearVelocity.SetV(v1);
        bA.m_angularVelocity = w1;
        bB.m_linearVelocity.SetV(v2);
        bB.m_angularVelocity = w2;
    }
    b2RevoluteJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var oldLimitImpulse = 0;
        var C = 0;
        var tMat;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var angularError = 0.0;
        var positionError = 0.0;
        var tX = 0;
        var impulseX = 0;
        var impulseY = 0;
        if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) {
            var angle = bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle;
            var limitImpulse = 0.0;
            if (this.m_limitState == b2Joint.e_equalLimits) {
                C = b2Math.Clamp(angle - this.m_lowerAngle, (-b2Settings.b2_maxAngularCorrection), b2Settings.b2_maxAngularCorrection);
                limitImpulse = (-this.m_motorMass * C);
                angularError = b2Math.Abs(C);
            }
            else if (this.m_limitState == b2Joint.e_atLowerLimit) {
                C = angle - this.m_lowerAngle;
                angularError = (-C);
                C = b2Math.Clamp(C + b2Settings.b2_angularSlop, (-b2Settings.b2_maxAngularCorrection), 0.0);
                limitImpulse = (-this.m_motorMass * C);
            }
            else if (this.m_limitState == b2Joint.e_atUpperLimit) {
                C = angle - this.m_upperAngle;
                angularError = C;
                C = b2Math.Clamp(C - b2Settings.b2_angularSlop, 0.0, b2Settings.b2_maxAngularCorrection);
                limitImpulse = (-this.m_motorMass * C);
            }
            bA.m_sweep.a -= bA.m_invI * limitImpulse;
            bB.m_sweep.a += bB.m_invI * limitImpulse;
            bA.SynchronizeTransform();
            bB.SynchronizeTransform();
        } {
            tMat = bA.m_xf.R;
            var r1X = this.m_localAnchor1.x - bA.m_sweep.localCenter.x;
            var r1Y = this.m_localAnchor1.y - bA.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
            r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
            r1X = tX;
            tMat = bB.m_xf.R;
            var r2X = this.m_localAnchor2.x - bB.m_sweep.localCenter.x;
            var r2Y = this.m_localAnchor2.y - bB.m_sweep.localCenter.y;
            tX = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
            r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
            r2X = tX;
            var CX = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
            var CY = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
            var CLengthSquared = CX * CX + CY * CY;
            var CLength = Math.sqrt(CLengthSquared);
            positionError = CLength;
            var invMass1 = bA.m_invMass;
            var invMass2 = bB.m_invMass;
            var invI1 = bA.m_invI;
            var invI2 = bB.m_invI;
            var k_allowedStretch = 10.0 * b2Settings.b2_linearSlop;
            if (CLengthSquared > k_allowedStretch * k_allowedStretch) {
                var uX = CX / CLength;
                var uY = CY / CLength;
                var k = invMass1 + invMass2;
                var m = 1.0 / k;
                impulseX = m * ((-CX));
                impulseY = m * ((-CY));
                var k_beta = 0.5;
                bA.m_sweep.c.x -= k_beta * invMass1 * impulseX;
                bA.m_sweep.c.y -= k_beta * invMass1 * impulseY;
                bB.m_sweep.c.x += k_beta * invMass2 * impulseX;
                bB.m_sweep.c.y += k_beta * invMass2 * impulseY;
                CX = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
                CY = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
            }
            this.K1.col1.x = invMass1 + invMass2;
            this.K1.col2.x = 0.0;
            this.K1.col1.y = 0.0;
            this.K1.col2.y = invMass1 + invMass2;
            this.K2.col1.x = invI1 * r1Y * r1Y;
            this.K2.col2.x = (-invI1 * r1X * r1Y);
            this.K2.col1.y = (-invI1 * r1X * r1Y);
            this.K2.col2.y = invI1 * r1X * r1X;
            this.K3.col1.x = invI2 * r2Y * r2Y;
            this.K3.col2.x = (-invI2 * r2X * r2Y);
            this.K3.col1.y = (-invI2 * r2X * r2Y);
            this.K3.col2.y = invI2 * r2X * r2X;
            this.K.SetM(this.K1);
            this.K.AddM(this.K2);
            this.K.AddM(this.K3);
            this.K.Solve(b2RevoluteJoint.tImpulse, (-CX), (-CY));
            impulseX = b2RevoluteJoint.tImpulse.x;
            impulseY = b2RevoluteJoint.tImpulse.y;
            bA.m_sweep.c.x -= bA.m_invMass * impulseX;
            bA.m_sweep.c.y -= bA.m_invMass * impulseY;
            bA.m_sweep.a -= bA.m_invI * (r1X * impulseY - r1Y * impulseX);
            bB.m_sweep.c.x += bB.m_invMass * impulseX;
            bB.m_sweep.c.y += bB.m_invMass * impulseY;
            bB.m_sweep.a += bB.m_invI * (r2X * impulseY - r2Y * impulseX);
            bA.SynchronizeTransform();
            bB.SynchronizeTransform();
        }
        return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
    }
    Box2D.postDefs.push(function () {
        Box2D.Dynamics.Joints.b2RevoluteJoint.tImpulse = new b2Vec2();
    });
    Box2D.inherit(b2RevoluteJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2RevoluteJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2RevoluteJointDef.b2RevoluteJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
    };
    b2RevoluteJointDef.prototype.b2RevoluteJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_revoluteJoint;
        this.localAnchorA.Set(0.0, 0.0);
        this.localAnchorB.Set(0.0, 0.0);
        this.referenceAngle = 0.0;
        this.lowerAngle = 0.0;
        this.upperAngle = 0.0;
        this.maxMotorTorque = 0.0;
        this.motorSpeed = 0.0;
        this.enableLimit = false;
        this.enableMotor = false;
    }
    b2RevoluteJointDef.prototype.Initialize = function (bA, bB, anchor) {
        this.bodyA = bA;
        this.bodyB = bB;
        this.localAnchorA = this.bodyA.GetLocalPoint(anchor);
        this.localAnchorB = this.bodyB.GetLocalPoint(anchor);
        this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle();
    }
    Box2D.inherit(b2WeldJoint, Box2D.Dynamics.Joints.b2Joint);
    b2WeldJoint.prototype.__super = Box2D.Dynamics.Joints.b2Joint.prototype;
    b2WeldJoint.b2WeldJoint = function () {
        Box2D.Dynamics.Joints.b2Joint.b2Joint.apply(this, arguments);
        this.m_localAnchorA = new b2Vec2();
        this.m_localAnchorB = new b2Vec2();
        this.m_impulse = new b2Vec3();
        this.m_mass = new b2Mat33();
    };
    b2WeldJoint.prototype.GetAnchorA = function () {
        return this.m_bodyA.GetWorldPoint(this.m_localAnchorA);
    }
    b2WeldJoint.prototype.GetAnchorB = function () {
        return this.m_bodyB.GetWorldPoint(this.m_localAnchorB);
    }
    b2WeldJoint.prototype.GetReactionForce = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return new b2Vec2(inv_dt * this.m_impulse.x, inv_dt * this.m_impulse.y);
    }
    b2WeldJoint.prototype.GetReactionTorque = function (inv_dt) {
        if (inv_dt === undefined) inv_dt = 0;
        return inv_dt * this.m_impulse.z;
    }
    b2WeldJoint.prototype.b2WeldJoint = function (def) {
        this.__super.b2Joint.call(this, def);
        this.m_localAnchorA.SetV(def.localAnchorA);
        this.m_localAnchorB.SetV(def.localAnchorB);
        this.m_referenceAngle = def.referenceAngle;
        this.m_impulse.SetZero();
        this.m_mass = new b2Mat33();
    }
    b2WeldJoint.prototype.InitVelocityConstraints = function (step) {
        var tMat;
        var tX = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        tMat = bA.m_xf.R;
        var rAX = this.m_localAnchorA.x - bA.m_sweep.localCenter.x;
        var rAY = this.m_localAnchorA.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rAX + tMat.col2.x * rAY);
        rAY = (tMat.col1.y * rAX + tMat.col2.y * rAY);
        rAX = tX;
        tMat = bB.m_xf.R;
        var rBX = this.m_localAnchorB.x - bB.m_sweep.localCenter.x;
        var rBY = this.m_localAnchorB.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rBX + tMat.col2.x * rBY);
        rBY = (tMat.col1.y * rBX + tMat.col2.y * rBY);
        rBX = tX;
        var mA = bA.m_invMass;
        var mB = bB.m_invMass;
        var iA = bA.m_invI;
        var iB = bB.m_invI;
        this.m_mass.col1.x = mA + mB + rAY * rAY * iA + rBY * rBY * iB;
        this.m_mass.col2.x = (-rAY * rAX * iA) - rBY * rBX * iB;
        this.m_mass.col3.x = (-rAY * iA) - rBY * iB;
        this.m_mass.col1.y = this.m_mass.col2.x;
        this.m_mass.col2.y = mA + mB + rAX * rAX * iA + rBX * rBX * iB;
        this.m_mass.col3.y = rAX * iA + rBX * iB;
        this.m_mass.col1.z = this.m_mass.col3.x;
        this.m_mass.col2.z = this.m_mass.col3.y;
        this.m_mass.col3.z = iA + iB;
        if (step.warmStarting) {
            this.m_impulse.x *= step.dtRatio;
            this.m_impulse.y *= step.dtRatio;
            this.m_impulse.z *= step.dtRatio;
            bA.m_linearVelocity.x -= mA * this.m_impulse.x;
            bA.m_linearVelocity.y -= mA * this.m_impulse.y;
            bA.m_angularVelocity -= iA * (rAX * this.m_impulse.y - rAY * this.m_impulse.x + this.m_impulse.z);
            bB.m_linearVelocity.x += mB * this.m_impulse.x;
            bB.m_linearVelocity.y += mB * this.m_impulse.y;
            bB.m_angularVelocity += iB * (rBX * this.m_impulse.y - rBY * this.m_impulse.x + this.m_impulse.z);
        }
        else {
            this.m_impulse.SetZero();
        }
    }
    b2WeldJoint.prototype.SolveVelocityConstraints = function (step) {
        var tMat;
        var tX = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        var vA = bA.m_linearVelocity;
        var wA = bA.m_angularVelocity;
        var vB = bB.m_linearVelocity;
        var wB = bB.m_angularVelocity;
        var mA = bA.m_invMass;
        var mB = bB.m_invMass;
        var iA = bA.m_invI;
        var iB = bB.m_invI;
        tMat = bA.m_xf.R;
        var rAX = this.m_localAnchorA.x - bA.m_sweep.localCenter.x;
        var rAY = this.m_localAnchorA.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rAX + tMat.col2.x * rAY);
        rAY = (tMat.col1.y * rAX + tMat.col2.y * rAY);
        rAX = tX;
        tMat = bB.m_xf.R;
        var rBX = this.m_localAnchorB.x - bB.m_sweep.localCenter.x;
        var rBY = this.m_localAnchorB.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rBX + tMat.col2.x * rBY);
        rBY = (tMat.col1.y * rBX + tMat.col2.y * rBY);
        rBX = tX;
        var Cdot1X = vB.x - wB * rBY - vA.x + wA * rAY;
        var Cdot1Y = vB.y + wB * rBX - vA.y - wA * rAX;
        var Cdot2 = wB - wA;
        var impulse = new b2Vec3();
        this.m_mass.Solve33(impulse, (-Cdot1X), (-Cdot1Y), (-Cdot2));
        this.m_impulse.Add(impulse);
        vA.x -= mA * impulse.x;
        vA.y -= mA * impulse.y;
        wA -= iA * (rAX * impulse.y - rAY * impulse.x + impulse.z);
        vB.x += mB * impulse.x;
        vB.y += mB * impulse.y;
        wB += iB * (rBX * impulse.y - rBY * impulse.x + impulse.z);
        bA.m_angularVelocity = wA;
        bB.m_angularVelocity = wB;
    }
    b2WeldJoint.prototype.SolvePositionConstraints = function (baumgarte) {
        if (baumgarte === undefined) baumgarte = 0;
        var tMat;
        var tX = 0;
        var bA = this.m_bodyA;
        var bB = this.m_bodyB;
        tMat = bA.m_xf.R;
        var rAX = this.m_localAnchorA.x - bA.m_sweep.localCenter.x;
        var rAY = this.m_localAnchorA.y - bA.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rAX + tMat.col2.x * rAY);
        rAY = (tMat.col1.y * rAX + tMat.col2.y * rAY);
        rAX = tX;
        tMat = bB.m_xf.R;
        var rBX = this.m_localAnchorB.x - bB.m_sweep.localCenter.x;
        var rBY = this.m_localAnchorB.y - bB.m_sweep.localCenter.y;
        tX = (tMat.col1.x * rBX + tMat.col2.x * rBY);
        rBY = (tMat.col1.y * rBX + tMat.col2.y * rBY);
        rBX = tX;
        var mA = bA.m_invMass;
        var mB = bB.m_invMass;
        var iA = bA.m_invI;
        var iB = bB.m_invI;
        var C1X = bB.m_sweep.c.x + rBX - bA.m_sweep.c.x - rAX;
        var C1Y = bB.m_sweep.c.y + rBY - bA.m_sweep.c.y - rAY;
        var C2 = bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle;
        var k_allowedStretch = 10.0 * b2Settings.b2_linearSlop;
        var positionError = Math.sqrt(C1X * C1X + C1Y * C1Y);
        var angularError = b2Math.Abs(C2);
        if (positionError > k_allowedStretch) {
            iA *= 1.0;
            iB *= 1.0;
        }
        this.m_mass.col1.x = mA + mB + rAY * rAY * iA + rBY * rBY * iB;
        this.m_mass.col2.x = (-rAY * rAX * iA) - rBY * rBX * iB;
        this.m_mass.col3.x = (-rAY * iA) - rBY * iB;
        this.m_mass.col1.y = this.m_mass.col2.x;
        this.m_mass.col2.y = mA + mB + rAX * rAX * iA + rBX * rBX * iB;
        this.m_mass.col3.y = rAX * iA + rBX * iB;
        this.m_mass.col1.z = this.m_mass.col3.x;
        this.m_mass.col2.z = this.m_mass.col3.y;
        this.m_mass.col3.z = iA + iB;
        var impulse = new b2Vec3();
        this.m_mass.Solve33(impulse, (-C1X), (-C1Y), (-C2));
        bA.m_sweep.c.x -= mA * impulse.x;
        bA.m_sweep.c.y -= mA * impulse.y;
        bA.m_sweep.a -= iA * (rAX * impulse.y - rAY * impulse.x + impulse.z);
        bB.m_sweep.c.x += mB * impulse.x;
        bB.m_sweep.c.y += mB * impulse.y;
        bB.m_sweep.a += iB * (rBX * impulse.y - rBY * impulse.x + impulse.z);
        bA.SynchronizeTransform();
        bB.SynchronizeTransform();
        return positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop;
    }
    Box2D.inherit(b2WeldJointDef, Box2D.Dynamics.Joints.b2JointDef);
    b2WeldJointDef.prototype.__super = Box2D.Dynamics.Joints.b2JointDef.prototype;
    b2WeldJointDef.b2WeldJointDef = function () {
        Box2D.Dynamics.Joints.b2JointDef.b2JointDef.apply(this, arguments);
        this.localAnchorA = new b2Vec2();
        this.localAnchorB = new b2Vec2();
    };
    b2WeldJointDef.prototype.b2WeldJointDef = function () {
        this.__super.b2JointDef.call(this);
        this.type = b2Joint.e_weldJoint;
        this.referenceAngle = 0.0;
    }
    b2WeldJointDef.prototype.Initialize = function (bA, bB, anchor) {
        this.bodyA = bA;
        this.bodyB = bB;
        this.localAnchorA.SetV(this.bodyA.GetLocalPoint(anchor));
        this.localAnchorB.SetV(this.bodyB.GetLocalPoint(anchor));
        this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle();
    }
})();
(function () {
    var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;
    b2DebugDraw.b2DebugDraw = function () {
        this.m_drawScale = 1.0;
        this.m_lineThickness = 1.0;
        this.m_alpha = 1.0;
        this.m_fillAlpha = 1.0;
        this.m_xformScale = 1.0;
        var __this = this;
        this.m_sprite = {
            graphics: {
                clear: function () {
                    __this.m_ctx.clearRect(0, 0, __this.m_ctx.canvas.width, __this.m_ctx.canvas.height)
                }
            }
        };
    };
    b2DebugDraw.prototype._color = function (color, alpha) {
        return "rgba(" + ((color & 0xFF0000) >> 16) + "," + ((color & 0xFF00) >> 8) + "," + (color & 0xFF) + "," + alpha + ")";
    };
    b2DebugDraw.prototype.b2DebugDraw = function () {
        this.m_drawFlags = 0;
    };
    b2DebugDraw.prototype.SetFlags = function (flags) {
        if (flags === undefined) flags = 0;
        this.m_drawFlags = flags;
    };
    b2DebugDraw.prototype.GetFlags = function () {
        return this.m_drawFlags;
    };
    b2DebugDraw.prototype.AppendFlags = function (flags) {
        if (flags === undefined) flags = 0;
        this.m_drawFlags |= flags;
    };
    b2DebugDraw.prototype.ClearFlags = function (flags) {
        if (flags === undefined) flags = 0;
        this.m_drawFlags &= ~flags;
    };
    b2DebugDraw.prototype.SetSprite = function (sprite) {
        this.m_ctx = sprite;
    };
    b2DebugDraw.prototype.GetSprite = function () {
        return this.m_ctx;
    };
    b2DebugDraw.prototype.SetDrawScale = function (drawScale) {
        if (drawScale === undefined) drawScale = 0;
        this.m_drawScale = drawScale;
    };
    b2DebugDraw.prototype.GetDrawScale = function () {
        return this.m_drawScale;
    };
    b2DebugDraw.prototype.SetLineThickness = function (lineThickness) {
        if (lineThickness === undefined) lineThickness = 0;
        this.m_lineThickness = lineThickness;
        this.m_ctx.strokeWidth = lineThickness;
    };
    b2DebugDraw.prototype.GetLineThickness = function () {
        return this.m_lineThickness;
    };
    b2DebugDraw.prototype.SetAlpha = function (alpha) {
        if (alpha === undefined) alpha = 0;
        this.m_alpha = alpha;
    };
    b2DebugDraw.prototype.GetAlpha = function () {
        return this.m_alpha;
    };
    b2DebugDraw.prototype.SetFillAlpha = function (alpha) {
        if (alpha === undefined) alpha = 0;
        this.m_fillAlpha = alpha;
    };
    b2DebugDraw.prototype.GetFillAlpha = function () {
        return this.m_fillAlpha;
    };
    b2DebugDraw.prototype.SetXFormScale = function (xformScale) {
        if (xformScale === undefined) xformScale = 0;
        this.m_xformScale = xformScale;
    };
    b2DebugDraw.prototype.GetXFormScale = function () {
        return this.m_xformScale;
    };
    b2DebugDraw.prototype.DrawPolygon = function (vertices, vertexCount, color) {
        if (!vertexCount) return;
        var s = this.m_ctx;
        var drawScale = this.m_drawScale;
        s.beginPath();
        s.strokeStyle = this._color(color.color, this.m_alpha);
        s.moveTo(vertices[0].x * drawScale, vertices[0].y * drawScale);
        for (var i = 1; i < vertexCount; i++) {
            s.lineTo(vertices[i].x * drawScale, vertices[i].y * drawScale);
        }
        s.lineTo(vertices[0].x * drawScale, vertices[0].y * drawScale);
        s.closePath();
        s.stroke();
    };
    b2DebugDraw.prototype.DrawSolidPolygon = function (vertices, vertexCount, color) {
        if (!vertexCount) return;
        var s = this.m_ctx;
        var drawScale = this.m_drawScale;
        s.beginPath();
        s.strokeStyle = this._color(color.color, this.m_alpha);
        s.fillStyle = this._color(color.color, this.m_fillAlpha);
        s.moveTo(vertices[0].x * drawScale, vertices[0].y * drawScale);
        for (var i = 1; i < vertexCount; i++) {
            s.lineTo(vertices[i].x * drawScale, vertices[i].y * drawScale);
        }
        s.lineTo(vertices[0].x * drawScale, vertices[0].y * drawScale);
        s.closePath();
        s.fill();
        s.stroke();
    };
    b2DebugDraw.prototype.DrawCircle = function (center, radius, color) {
        if (!radius) return;
        var s = this.m_ctx;
        var drawScale = this.m_drawScale;
        s.beginPath();
        s.strokeStyle = this._color(color.color, this.m_alpha);
        s.arc(center.x * drawScale, center.y * drawScale, radius * drawScale, 0, Math.PI * 2, true);
        s.closePath();
        s.stroke();
    };
    b2DebugDraw.prototype.DrawSolidCircle = function (center, radius, axis, color) {
        if (!radius) return;
        var s = this.m_ctx,
            drawScale = this.m_drawScale,
            cx = center.x * drawScale,
            cy = center.y * drawScale;
        s.moveTo(0, 0);
        s.beginPath();
        s.strokeStyle = this._color(color.color, this.m_alpha);
        s.fillStyle = this._color(color.color, this.m_fillAlpha);
        s.arc(cx, cy, radius * drawScale, 0, Math.PI * 2, true);
        s.moveTo(cx, cy);
        s.lineTo((center.x + axis.x * radius) * drawScale, (center.y + axis.y * radius) * drawScale);
        s.closePath();
        s.fill();
        s.stroke();
    };
    b2DebugDraw.prototype.DrawSegment = function (p1, p2, color) {
        var s = this.m_ctx,
            drawScale = this.m_drawScale;
        s.strokeStyle = this._color(color.color, this.m_alpha);
        s.beginPath();
        s.moveTo(p1.x * drawScale, p1.y * drawScale);
        s.lineTo(p2.x * drawScale, p2.y * drawScale);
        s.closePath();
        s.stroke();
    };
    b2DebugDraw.prototype.DrawTransform = function (xf) {
        var s = this.m_ctx,
            drawScale = this.m_drawScale;
        s.beginPath();
        s.strokeStyle = this._color(0xff0000, this.m_alpha);
        s.moveTo(xf.position.x * drawScale, xf.position.y * drawScale);
        s.lineTo((xf.position.x + this.m_xformScale * xf.R.col1.x) * drawScale, (xf.position.y + this.m_xformScale * xf.R.col1.y) * drawScale);
        s.strokeStyle = this._color(0xff00, this.m_alpha);
        s.moveTo(xf.position.x * drawScale, xf.position.y * drawScale);
        s.lineTo((xf.position.x + this.m_xformScale * xf.R.col2.x) * drawScale, (xf.position.y + this.m_xformScale * xf.R.col2.y) * drawScale);
        s.closePath();
        s.stroke();
    };
})();
var i;
for (i = 0; i < Box2D.postDefs.length; ++i) Box2D.postDefs[i]();
delete Box2D.postDefs;
if (typeof require !== 'undefined' && typeof module !== 'undefined') {
    module.exports = Box2D;
}
(function(){
Object.create = Object.create || function(o) {
    function F() {}
    F.prototype = o;
    return new F();
};
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){
    min = Math.min;
    max = Math.max;
} else {
    min = mymin;
    max = mymax;
}
var hashPair = function(a, b)
{
    return a < b ? a + ' ' + b : b + ' ' + a;
};
var deleteObjFromList = function(arr, obj)
{
    for(var i=0; i<arr.length; i++){
        if(arr[i] === obj){
            arr[i] = arr[arr.length - 1];
            arr.length--;
            return;
        }
    }
};
var closestPointOnSegment = function(p, a, b)
{
    var delta = vsub(a, b);
    var t = clamp01(vdot(delta, vsub(p, b))/vlengthsq(delta));
    return vadd(b, vmult(delta, t));
};
var closestPointOnSegment2 = function(px, py, ax, ay, bx, by)
{
    var deltax = ax - bx;
    var deltay = ay - by;
    var t = clamp01(vdot2(deltax, deltay, px - bx, py - by)/vlengthsq2(deltax, deltay));
    return new Vect(bx + deltax * t, by + deltay * t);
};
cp.momentForCircle = function(m, r1, r2, offset)
{
    return m*(0.5*(r1*r1 + r2*r2) + vlengthsq(offset));
};
cp.areaForCircle = function(r1, r2)
{
    return Math.PI*Math.abs(r1*r1 - r2*r2);
};
cp.momentForSegment = function(m, a, b)
{
    var offset = vmult(vadd(a, b), 0.5);
    return m*(vdistsq(b, a)/12 + vlengthsq(offset));
};
cp.areaForSegment = function(a, b, r)
{
    return r*(Math.PI*r + 2*vdist(a, b));
};
cp.momentForPoly = function(m, verts, offset)
{
    var sum1 = 0;
    var sum2 = 0;
    var len = verts.length;
    for(var i=0; i<len; i+=2){
        var v1x = verts[i] + offset.x;
         var v1y = verts[i+1] + offset.y;
        var v2x = verts[(i+2)%len] + offset.x;
        var v2y = verts[(i+3)%len] + offset.y;
        var a = vcross2(v2x, v2y, v1x, v1y);
        var b = vdot2(v1x, v1y, v1x, v1y) + vdot2(v1x, v1y, v2x, v2y) + vdot2(v2x, v2y, v2x, v2y);
        sum1 += a*b;
        sum2 += a;
    }
    return (m*sum1)/(6*sum2);
};
cp.areaForPoly = function(verts)
{
    var area = 0;
    for(var i=0, len=verts.length; i<len; i+=2){
        area += vcross(new Vect(verts[i], verts[i+1]), new Vect(verts[(i+2)%len], verts[(i+3)%len]));
    }
    return -area/2;
};
cp.centroidForPoly = function(verts)
{
    var sum = 0;
    var vsum = new Vect(0,0);
    for(var i=0, len=verts.length; i<len; i+=2){
        var v1 = new Vect(verts[i], verts[i+1]);
        var v2 = new Vect(verts[(i+2)%len], verts[(i+3)%len]);
        var cross = vcross(v1, v2);
        sum += cross;
        vsum = vadd(vsum, vmult(vadd(v1, v2), cross));
    }
    return vmult(vsum, 1/(3*sum));
};
cp.recenterPoly = function(verts)
{
    var centroid = cp.centroidForPoly(verts);
    for(var i=0; i<verts.length; i+=2){
        verts[i] -= centroid.x;
        verts[i+1] -= centroid.y;
    }
};
cp.momentForBox = function(m, width, height)
{
    return m*(width*width + height*height)/12;
};
cp.momentForBox2 = function(m, box)
{
    var width = box.r - box.l;
    var height = box.t - box.b;
    var offset = vmult([box.l + box.r, box.b + box.t], 0.5);
    return cp.momentForBox(m, width, height) + m*vlengthsq(offset);
};
var loopIndexes = cp.loopIndexes = function(verts)
{
    var start = 0, end = 0;
    var minx, miny, maxx, maxy;
    minx = maxx = verts[0];
    miny = maxy = verts[1];
    var count = verts.length >> 1;
  for(var i=1; i<count; i++){
        var x = verts[i*2];
        var y = verts[i*2 + 1];
    if(x < minx || (x == minx && y < miny)){
            minx = x;
            miny = y;
      start = i;
    } else if(x > maxx || (x == maxx && y > maxy)){
            maxx = x;
            maxy = y;
            end = i;
        }
    }
    return [start, end];
};
var SWAP = function(arr, idx1, idx2)
{
    var tmp = arr[idx1*2];
    arr[idx1*2] = arr[idx2*2];
    arr[idx2*2] = tmp;
    tmp = arr[idx1*2+1];
    arr[idx1*2+1] = arr[idx2*2+1];
    arr[idx2*2+1] = tmp;
};
var QHullPartition = function(verts, offs, count, a, b, tol)
{
    if(count === 0) return 0;
    var max = 0;
    var pivot = offs;
    var delta = vsub(b, a);
    var valueTol = tol * vlength(delta);
    var head = offs;
    for(var tail = offs+count-1; head <= tail;){
        var v = new Vect(verts[head * 2], verts[head * 2 + 1]);
        var value = vcross(delta, vsub(v, a));
        if(value > valueTol){
            if(value > max){
                max = value;
                pivot = head;
            }
            head++;
        } else {
            SWAP(verts, head, tail);
            tail--;
        }
    }
    if(pivot != offs) SWAP(verts, offs, pivot);
    return head - offs;
};
var QHullReduce = function(tol, verts, offs, count, a, pivot, b, resultPos)
{
    if(count < 0){
        return 0;
    } else if(count == 0) {
        verts[resultPos*2] = pivot.x;
        verts[resultPos*2+1] = pivot.y;
        return 1;
    } else {
        var left_count = QHullPartition(verts, offs, count, a, pivot, tol);
        var left = new Vect(verts[offs*2], verts[offs*2+1]);
        var index = QHullReduce(tol, verts, offs + 1, left_count - 1, a, left, pivot, resultPos);
        var pivotPos = resultPos + index++;
        verts[pivotPos*2] = pivot.x;
        verts[pivotPos*2+1] = pivot.y;
        var right_count = QHullPartition(verts, offs + left_count, count - left_count, pivot, b, tol);
        var right = new Vect(verts[(offs+left_count)*2], verts[(offs+left_count)*2+1]);
        return index + QHullReduce(tol, verts, offs + left_count + 1, right_count - 1, pivot, right, b, resultPos + index);
    }
};
cp.convexHull = function(verts, result, tolerance)
{
    if(result){
        for (var i = 0; i < verts.length; i++){
            result[i] = verts[i];
        }
    } else {
        result = verts;
    }
    var indexes = loopIndexes(verts);
    var start = indexes[0], end = indexes[1];
    if(start == end){
        result.length = 2;
        return result;
    }
    SWAP(result, 0, start);
    SWAP(result, 1, end == 0 ? start : end);
    var a = new Vect(result[0], result[1]);
    var b = new Vect(result[2], result[3]);
    var count = verts.length >> 1;
    var resultCount = QHullReduce(tolerance, result, 2, count - 2, a, b, a, 1) + 1;
    result.length = resultCount*2;
    assertSoft(polyValidate(result),
        "Internal error: cpConvexHull() and cpPolyValidate() did not agree." +
        "Please report this error with as much info as you can.");
    return result;
};
var clamp = function(f, minv, maxv)
{
    return min(max(f, minv), maxv);
};
var clamp01 = function(f)
{
    return max(0, min(f, 1));
};
var lerp = function(f1, f2, t)
{
    return f1*(1 - t) + f2*t;
};
var lerpconst = function(f1, f2, d)
{
    return f1 + clamp(f2 - f1, -d, d);
};
var Vect = cp.Vect = function(x, y)
{
    this.x = x;
    this.y = y;
};
cp.v = function (x,y) { return new Vect(x, y) };
var vzero = cp.vzero = new Vect(0,0);
var vdot = cp.v.dot = function(v1, v2)
{
    return v1.x*v2.x + v1.y*v2.y;
};
var vdot2 = function(x1, y1, x2, y2)
{
    return x1*x2 + y1*y2;
};
var vlength = cp.v.len = function(v)
{
    return Math.sqrt(vdot(v, v));
};
var vlength2 = cp.v.len2 = function(x, y)
{
    return Math.sqrt(x*x + y*y);
};
var veql = cp.v.eql = function(v1, v2)
{
    return (v1.x === v2.x && v1.y === v2.y);
};
var vadd = cp.v.add = function(v1, v2)
{
    return new Vect(v1.x + v2.x, v1.y + v2.y);
};
Vect.prototype.add = function(v2)
{
    this.x += v2.x;
    this.y += v2.y;
    return this;
};
var vsub = cp.v.sub = function(v1, v2)
{
    return new Vect(v1.x - v2.x, v1.y - v2.y);
};
Vect.prototype.sub = function(v2)
{
    this.x -= v2.x;
    this.y -= v2.y;
    return this;
};
var vneg = cp.v.neg = function(v)
{
    return new Vect(-v.x, -v.y);
};
Vect.prototype.neg = function()
{
    this.x = -this.x;
    this.y = -this.y;
    return this;
};
var vmult = cp.v.mult = function(v, s)
{
    return new Vect(v.x*s, v.y*s);
};
Vect.prototype.mult = function(s)
{
    this.x *= s;
    this.y *= s;
    return this;
};
var vcross = cp.v.cross = function(v1, v2)
{
    return v1.x*v2.y - v1.y*v2.x;
};
var vcross2 = function(x1, y1, x2, y2)
{
    return x1*y2 - y1*x2;
};
var vperp = cp.v.perp = function(v)
{
    return new Vect(-v.y, v.x);
};
var vpvrperp = cp.v.pvrperp = function(v)
{
    return new Vect(v.y, -v.x);
};
var vproject = cp.v.project = function(v1, v2)
{
    return vmult(v2, vdot(v1, v2)/vlengthsq(v2));
};
Vect.prototype.project = function(v2)
{
    this.mult(vdot(this, v2) / vlengthsq(v2));
    return this;
};
var vrotate = cp.v.rotate = function(v1, v2)
{
    return new Vect(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
};
Vect.prototype.rotate = function(v2)
{
    this.x = this.x * v2.x - this.y * v2.y;
    this.y = this.x * v2.y + this.y * v2.x;
    return this;
};
var vunrotate = cp.v.unrotate = function(v1, v2)
{
    return new Vect(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
};
var vlengthsq = cp.v.lengthsq = function(v)
{
    return vdot(v, v);
};
var vlengthsq2 = cp.v.lengthsq2 = function(x, y)
{
    return x*x + y*y;
};
var vlerp = cp.v.lerp = function(v1, v2, t)
{
    return vadd(vmult(v1, 1 - t), vmult(v2, t));
};
var vnormalize = cp.v.normalize = function(v)
{
    return vmult(v, 1/vlength(v));
};
var vnormalize_safe = cp.v.normalize_safe = function(v)
{
    return (v.x === 0 && v.y === 0 ? vzero : vnormalize(v));
};
var vclamp = cp.v.clamp = function(v, len)
{
    return (vdot(v,v) > len*len) ? vmult(vnormalize(v), len) : v;
};
var vlerpconst = cp.v.lerpconst = function(v1, v2, d)
{
    return vadd(v1, vclamp(vsub(v2, v1), d));
};
var vdist = cp.v.dist = function(v1, v2)
{
    return vlength(vsub(v1, v2));
};
var vdistsq = cp.v.distsq = function(v1, v2)
{
    return vlengthsq(vsub(v1, v2));
};
var vnear = cp.v.near = function(v1, v2, dist)
{
    return vdistsq(v1, v2) < dist*dist;
};
var vslerp = cp.v.slerp = function(v1, v2, t)
{
    var omega = Math.acos(vdot(v1, v2));
    if(omega) {
        var denom = 1/Math.sin(omega);
        return vadd(vmult(v1, Math.sin((1 - t)*omega)*denom), vmult(v2, Math.sin(t*omega)*denom));
    } else {
        return v1;
    }
};
var vslerpconst = cp.v.slerpconst = function(v1, v2, a)
{
    var angle = Math.acos(vdot(v1, v2));
    return vslerp(v1, v2, min(a, angle)/angle);
};
var vforangle = cp.v.forangle = function(a)
{
    return new Vect(Math.cos(a), Math.sin(a));
};
var vtoangle = cp.v.toangle = function(v)
{
    return Math.atan2(v.y, v.x);
};
var vstr = cp.v.str = function(v)
{
    return "(" + v.x.toFixed(3) + ", " + v.y.toFixed(3) + ")";
};
var numBB = 0;
var BB = cp.BB = function(l, b, r, t)
{
    this.l = l;
    this.b = b;
    this.r = r;
    this.t = t;
    numBB++;
};
cp.bb = function(l, b, r, t) { return new BB(l, b, r, t); };
var bbNewForCircle = function(p, r)
{
    return new BB(
            p.x - r,
            p.y - r,
            p.x + r,
            p.y + r
        );
};
var bbIntersects = function(a, b)
{
    return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t);
};
var bbIntersects2 = function(bb, l, b, r, t)
{
    return (bb.l <= r && l <= bb.r && bb.b <= t && b <= bb.t);
};
var bbContainsBB = function(bb, other)
{
    return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t);
};
var bbContainsVect = function(bb, v)
{
    return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y);
};
var bbContainsVect2 = function(l, b, r, t, v)
{
    return (l <= v.x && r >= v.x && b <= v.y && t >= v.y);
};
var bbMerge = function(a, b){
    return new BB(
            min(a.l, b.l),
            min(a.b, b.b),
            max(a.r, b.r),
            max(a.t, b.t)
        );
};
var bbExpand = function(bb, v){
    return new BB(
            min(bb.l, v.x),
            min(bb.b, v.y),
            max(bb.r, v.x),
            max(bb.t, v.y)
        );
};
var bbArea = function(bb)
{
    return (bb.r - bb.l)*(bb.t - bb.b);
};
var bbMergedArea = function(a, b)
{
    return (max(a.r, b.r) - min(a.l, b.l))*(max(a.t, b.t) - min(a.b, b.b));
};
var bbMergedArea2 = function(bb, l, b, r, t)
{
    return (max(bb.r, r) - min(bb.l, l))*(max(bb.t, t) - min(bb.b, b));
};
var bbIntersectsSegment = function(bb, a, b)
{
    return (bbSegmentQuery(bb, a, b) != Infinity);
};
var bbClampVect = function(bb, v)
{
    var x = min(max(bb.l, v.x), bb.r);
    var y = min(max(bb.b, v.y), bb.t);
    return new Vect(x, y);
};
var bbWrapVect = function(bb, v)
{
    var ix = Math.abs(bb.r - bb.l);
    var modx = (v.x - bb.l) % ix;
    var x = (modx > 0) ? modx : modx + ix;
    var iy = Math.abs(bb.t - bb.b);
    var mody = (v.y - bb.b) % iy;
    var y = (mody > 0) ? mody : mody + iy;
    return new Vect(x + bb.l, y + bb.b);
};
var shapeIDCounter = 0;
var CP_NO_GROUP = cp.NO_GROUP = 0;
var CP_ALL_LAYERS = cp.ALL_LAYERS = ~0;
var CP_ALL_CATEGORIES = cp.ALL_CATEGORIES = ~0;
cp.resetShapeIdCounter = function()
{
    shapeIDCounter = 0;
};
var Shape = cp.Shape = function(body) {
    this.body = body;
    this.bb_l = this.bb_b = this.bb_r = this.bb_t = 0;
    this.hashid = shapeIDCounter++;
    this.sensor = false;
    this.e = 0;
    this.u = 0;
    this.surface_v = vzero;
    this.collision_type = 0;
    this.group = 0;
    this.layers = CP_ALL_LAYERS;
    this.space = null;
    this.collisionCode = this.collisionCode;
};
Shape.prototype.setElasticity = function(e) { this.e = e; };
Shape.prototype.setFriction = function(u) { this.body.activate(); this.u = u; };
Shape.prototype.setLayers = function(layers) { this.body.activate(); this.layers = layers; };
Shape.prototype.setSensor = function(sensor) { this.body.activate(); this.sensor = sensor; };
Shape.prototype.setCollisionType = function(collision_type) { this.body.activate(); this.collision_type = collision_type; };
Shape.prototype.getBody = function() { return this.body; };
Shape.prototype.active = function()
{
    return this.body && this.body.shapeList.indexOf(this) !== -1;
};
Shape.prototype.setBody = function(body)
{
    assert(!this.active(), "You cannot change the body on an active shape. You must remove the shape from the space before changing the body.");
    this.body = body;
};
Shape.prototype.cacheBB = function()
{
    return this.update(this.body.p, this.body.rot);
};
Shape.prototype.update = function(pos, rot)
{
    assert(!isNaN(rot.x), 'Rotation is NaN');
    assert(!isNaN(pos.x), 'Position is NaN');
    this.cacheData(pos, rot);
};
Shape.prototype.pointQuery = function(p)
{
    var info = this.nearestPointQuery(p);
    if (info.d < 0) return info;
};
Shape.prototype.getBB = function()
{
    return new BB(this.bb_l, this.bb_b, this.bb_r, this.bb_t);
};
var PointQueryExtendedInfo = function(shape)
{
    this.shape = shape;
    this.d = Infinity;
    this.n = vzero;
};
var NearestPointQueryInfo = function(shape, p, d)
{
    this.shape = shape;
    this.p = p;
    this.d = d;
};
var SegmentQueryInfo = function(shape, t, n)
{
    this.shape = shape;
    this.t = t;
    this.n = n;
};
SegmentQueryInfo.prototype.hitPoint = function(start, end)
{
    return vlerp(start, end, this.t);
};
SegmentQueryInfo.prototype.hitDist = function(start, end)
{
    return vdist(start, end) * this.t;
};
var CircleShape = cp.CircleShape = function(body, radius, offset)
{
    this.c = this.tc = offset;
    this.r = radius;
    this.type = 'circle';
    Shape.call(this, body);
};
CircleShape.prototype = Object.create(Shape.prototype);
CircleShape.prototype.cacheData = function(p, rot)
{
    var c = this.tc = vrotate(this.c, rot).add(p);
    var r = this.r;
    this.bb_l = c.x - r;
    this.bb_b = c.y - r;
    this.bb_r = c.x + r;
    this.bb_t = c.y + r;
};
CircleShape.prototype.nearestPointQuery = function(p)
{
    var deltax = p.x - this.tc.x;
    var deltay = p.y - this.tc.y;
    var d = vlength2(deltax, deltay);
    var r = this.r;
    var nearestp = new Vect(this.tc.x + deltax * r/d, this.tc.y + deltay * r/d);
    return new NearestPointQueryInfo(this, nearestp, d - r);
};
var circleSegmentQuery = function(shape, center, r, a, b, info)
{
    a = vsub(a, center);
    b = vsub(b, center);
    var qa = vdot(a, a) - 2*vdot(a, b) + vdot(b, b);
    var qb = -2*vdot(a, a) + 2*vdot(a, b);
    var qc = vdot(a, a) - r*r;
    var det = qb*qb - 4*qa*qc;
    if(det >= 0)
    {
        var t = (-qb - Math.sqrt(det))/(2*qa);
        if(0 <= t && t <= 1){
            return new SegmentQueryInfo(shape, t, vnormalize(vlerp(a, b, t)));
        }
    }
};
CircleShape.prototype.segmentQuery = function(a, b)
{
    return circleSegmentQuery(this, this.tc, this.r, a, b);
};
var SegmentShape = cp.SegmentShape = function(body, a, b, r)
{
    this.a = a;
    this.b = b;
    this.n = vperp(vnormalize(vsub(b, a)));
    this.ta = this.tb = this.tn = null;
    this.r = r;
    this.a_tangent = vzero;
    this.b_tangent = vzero;
    this.type = 'segment';
    Shape.call(this, body);
};
SegmentShape.prototype = Object.create(Shape.prototype);
SegmentShape.prototype.cacheData = function(p, rot)
{
    this.ta = vadd(p, vrotate(this.a, rot));
    this.tb = vadd(p, vrotate(this.b, rot));
    this.tn = vrotate(this.n, rot);
    var l,r,b,t;
    if(this.ta.x < this.tb.x){
        l = this.ta.x;
        r = this.tb.x;
    } else {
        l = this.tb.x;
        r = this.ta.x;
    }
    if(this.ta.y < this.tb.y){
        b = this.ta.y;
        t = this.tb.y;
    } else {
        b = this.tb.y;
        t = this.ta.y;
    }
    var rad = this.r;
    this.bb_l = l - rad;
    this.bb_b = b - rad;
    this.bb_r = r + rad;
    this.bb_t = t + rad;
};
SegmentShape.prototype.nearestPointQuery = function(p)
{
    var closest = closestPointOnSegment(p, this.ta, this.tb);
    var deltax = p.x - closest.x;
    var deltay = p.y - closest.y;
    var d = vlength2(deltax, deltay);
    var r = this.r;
    var nearestp = (d ? vadd(closest, vmult(new Vect(deltax, deltay), r/d)) : closest);
    return new NearestPointQueryInfo(this, nearestp, d - r);
};
SegmentShape.prototype.segmentQuery = function(a, b)
{
    var n = this.tn;
    var d = vdot(vsub(this.ta, a), n);
    var r = this.r;
    var flipped_n = (d > 0 ? vneg(n) : n);
    var n_offset = vsub(vmult(flipped_n, r), a);
    var seg_a = vadd(this.ta, n_offset);
    var seg_b = vadd(this.tb, n_offset);
    var delta = vsub(b, a);
    if(vcross(delta, seg_a)*vcross(delta, seg_b) <= 0){
        var d_offset = d + (d > 0 ? -r : r);
        var ad = -d_offset;
        var bd = vdot(delta, n) - d_offset;
        if(ad*bd < 0){
            return new SegmentQueryInfo(this, ad/(ad - bd), flipped_n);
        }
    } else if(r !== 0){
        var info1 = circleSegmentQuery(this, this.ta, this.r, a, b);
        var info2 = circleSegmentQuery(this, this.tb, this.r, a, b);
        if (info1){
            return info2 && info2.t < info1.t ? info2 : info1;
        } else {
            return info2;
        }
    }
};
SegmentShape.prototype.setNeighbors = function(prev, next)
{
    this.a_tangent = vsub(prev, this.a);
    this.b_tangent = vsub(next, this.b);
};
SegmentShape.prototype.setEndpoints = function(a, b)
{
    this.a = a;
    this.b = b;
    this.n = vperp(vnormalize(vsub(b, a)));
};
var polyValidate = function(verts)
{
    var len = verts.length;
    for(var i=0; i<len; i+=2){
        var ax = verts[i];
         var ay = verts[i+1];
        var bx = verts[(i+2)%len];
        var by = verts[(i+3)%len];
        var cx = verts[(i+4)%len];
        var cy = verts[(i+5)%len];
        if(vcross2(bx - ax, by - ay, cx - bx, cy - by) > 0){
            return false;
        }
    }
    return true;
};
var PolyShape = cp.PolyShape = function(body, verts, offset)
{
    this.setVerts(verts, offset);
    this.type = 'poly';
    Shape.call(this, body);
};
PolyShape.prototype = Object.create(Shape.prototype);
var SplittingPlane = function(n, d)
{
    this.n = n;
    this.d = d;
};
SplittingPlane.prototype.compare = function(v)
{
    return vdot(this.n, v) - this.d;
};
PolyShape.prototype.setVerts = function(verts, offset)
{
    assert(verts.length >= 4, "Polygons require some verts");
    assert(typeof(verts[0]) === 'number',
            'Polygon verticies should be specified in a flattened list (eg [x1,y1,x2,y2,x3,y3,...])');
    assert(polyValidate(verts), "Polygon is concave or has a reversed winding. Consider using cpConvexHull()");
    var len = verts.length;
    var numVerts = len >> 1;
    this.verts = new Array(len);
    this.tVerts = new Array(len);
    this.planes = new Array(numVerts);
    this.tPlanes = new Array(numVerts);
    for(var i=0; i<len; i+=2){
        var ax = verts[i] + offset.x;
         var ay = verts[i+1] + offset.y;
        var bx = verts[(i+2)%len] + offset.x;
        var by = verts[(i+3)%len] + offset.y;
        var n = vnormalize(vperp(new Vect(bx-ax, by-ay)));
        this.verts[i  ] = ax;
        this.verts[i+1] = ay;
        this.planes[i>>1] = new SplittingPlane(n, vdot2(n.x, n.y, ax, ay));
        this.tPlanes[i>>1] = new SplittingPlane(new Vect(0,0), 0);
    }
};
var BoxShape = cp.BoxShape = function(body, width, height)
{
    var hw = width/2;
    var hh = height/2;
    return BoxShape2(body, new BB(-hw, -hh, hw, hh));
};
var BoxShape2 = cp.BoxShape2 = function(body, box)
{
    var verts = [
        box.l, box.b,
        box.l, box.t,
        box.r, box.t,
        box.r, box.b
    ];
    return new PolyShape(body, verts, vzero);
};
PolyShape.prototype.transformVerts = function(p, rot)
{
    var src = this.verts;
    var dst = this.tVerts;
    var l = Infinity, r = -Infinity;
    var b = Infinity, t = -Infinity;
    for(var i=0; i<src.length; i+=2){
        var x = src[i];
         var y = src[i+1];
        var vx = p.x + x*rot.x - y*rot.y;
        var vy = p.y + x*rot.y + y*rot.x;
        dst[i] = vx;
        dst[i+1] = vy;
        l = min(l, vx);
        r = max(r, vx);
        b = min(b, vy);
        t = max(t, vy);
    }
    this.bb_l = l;
    this.bb_b = b;
    this.bb_r = r;
    this.bb_t = t;
};
PolyShape.prototype.transformAxes = function(p, rot)
{
    var src = this.planes;
    var dst = this.tPlanes;
    for(var i=0; i<src.length; i++){
        var n = vrotate(src[i].n, rot);
        dst[i].n = n;
        dst[i].d = vdot(p, n) + src[i].d;
    }
};
PolyShape.prototype.cacheData = function(p, rot)
{
    this.transformAxes(p, rot);
    this.transformVerts(p, rot);
};
PolyShape.prototype.nearestPointQuery = function(p)
{
    var planes = this.tPlanes;
    var verts = this.tVerts;
    var v0x = verts[verts.length - 2];
    var v0y = verts[verts.length - 1];
    var minDist = Infinity;
    var closestPoint = vzero;
    var outside = false;
    for(var i=0; i<planes.length; i++){
        if(planes[i].compare(p) > 0) outside = true;
        var v1x = verts[i*2];
        var v1y = verts[i*2 + 1];
        var closest = closestPointOnSegment2(p.x, p.y, v0x, v0y, v1x, v1y);
        var dist = vdist(p, closest);
        if(dist < minDist){
            minDist = dist;
            closestPoint = closest;
        }
        v0x = v1x;
        v0y = v1y;
    }
    return new NearestPointQueryInfo(this, closestPoint, (outside ? minDist : -minDist));
};
PolyShape.prototype.segmentQuery = function(a, b)
{
    var axes = this.tPlanes;
    var verts = this.tVerts;
    var numVerts = axes.length;
    var len = numVerts * 2;
    for(var i=0; i<numVerts; i++){
        var n = axes[i].n;
        var an = vdot(a, n);
        if(axes[i].d > an) continue;
        var bn = vdot(b, n);
        var t = (axes[i].d - an)/(bn - an);
        if(t < 0 || 1 < t) continue;
        var point = vlerp(a, b, t);
        var dt = -vcross(n, point);
        var dtMin = -vcross2(n.x, n.y, verts[i*2], verts[i*2+1]);
        var dtMax = -vcross2(n.x, n.y, verts[(i*2+2)%len], verts[(i*2+3)%len]);
        if(dtMin <= dt && dt <= dtMax){
            return new SegmentQueryInfo(this, t, n);
        }
    }
};
PolyShape.prototype.valueOnAxis = function(n, d)
{
    var verts = this.tVerts;
    var m = vdot2(n.x, n.y, verts[0], verts[1]);
    for(var i=2; i<verts.length; i+=2){
        m = min(m, vdot2(n.x, n.y, verts[i], verts[i+1]));
    }
    return m - d;
};
PolyShape.prototype.containsVert = function(vx, vy)
{
    var planes = this.tPlanes;
    for(var i=0; i<planes.length; i++){
        var n = planes[i].n;
        var dist = vdot2(n.x, n.y, vx, vy) - planes[i].d;
        if(dist > 0) return false;
    }
    return true;
};
PolyShape.prototype.containsVertPartial = function(vx, vy, n)
{
    var planes = this.tPlanes;
    for(var i=0; i<planes.length; i++){
        var n2 = planes[i].n;
        if(vdot(n2, n) < 0) continue;
        var dist = vdot2(n2.x, n2.y, vx, vy) - planes[i].d;
        if(dist > 0) return false;
    }
    return true;
};
PolyShape.prototype.getNumVerts = function() { return this.verts.length / 2; };
PolyShape.prototype.getCount = PolyShape.prototype.getNumVerts;
PolyShape.prototype.getVert = function(i)
{
    return new Vect(this.verts[i * 2], this.verts[i * 2 + 1]);
};
var Body = cp.Body = function(m, i) {
    this.p = new Vect(0,0);
    this.vx = this.vy = 0;
    this.f = new Vect(0,0);
    this.w = 0;
    this.t = 0;
    this.v_limit = Infinity;
    this.w_limit = Infinity;
    this.v_biasx = this.v_biasy = 0;
    this.w_bias = 0;
    this.space = null;
    this.shapeList = [];
    this.arbiterList = null;
    this.constraintList = null;
    this.nodeRoot = null;
    this.nodeNext = null;
    this.nodeIdleTime = 0;
    this.setMass(m);
    this.setMoment(i);
    this.rot = new Vect(0,0);
    this.setAngle(0);
};
var createStaticBody = function()
{
    var body = new Body(Infinity, Infinity);
    body.nodeIdleTime = Infinity;
    return body;
};
    cp.StaticBody = createStaticBody;
if (typeof DEBUG !== 'undefined' && DEBUG) {
    var v_assert_nan = function(v, message){assert(v.x == v.x && v.y == v.y, message); };
    var v_assert_infinite = function(v, message){assert(Math.abs(v.x) !== Infinity && Math.abs(v.y) !== Infinity, message);};
    var v_assert_sane = function(v, message){v_assert_nan(v, message); v_assert_infinite(v, message);};
    Body.prototype.sanityCheck = function()
    {
        assert(this.m === this.m && this.m_inv === this.m_inv, "Body's mass is invalid.");
        assert(this.i === this.i && this.i_inv === this.i_inv, "Body's moment is invalid.");
        v_assert_sane(this.p, "Body's position is invalid.");
        v_assert_sane(this.f, "Body's force is invalid.");
        assert(this.vx === this.vx && Math.abs(this.vx) !== Infinity, "Body's velocity is invalid.");
        assert(this.vy === this.vy && Math.abs(this.vy) !== Infinity, "Body's velocity is invalid.");
        assert(this.a === this.a && Math.abs(this.a) !== Infinity, "Body's angle is invalid.");
        assert(this.w === this.w && Math.abs(this.w) !== Infinity, "Body's angular velocity is invalid.");
        assert(this.t === this.t && Math.abs(this.t) !== Infinity, "Body's torque is invalid.");
        v_assert_sane(this.rot, "Body's rotation vector is invalid.");
        assert(this.v_limit === this.v_limit, "Body's velocity limit is invalid.");
        assert(this.w_limit === this.w_limit, "Body's angular velocity limit is invalid.");
    };
} else {
    Body.prototype.sanityCheck = function(){};
}
Body.prototype.getPos = function() { return this.p; };
Body.prototype.getVel = function() { return new Vect(this.vx, this.vy); };
Body.prototype.getAngVel = function() { return this.w; };
Body.prototype.getPosition = Body.prototype.getPos;
Body.prototype.getVelocity = Body.prototype.getVel;
Body.prototype.getAngularVelocity = Body.prototype.getAngVel;
Body.prototype.getCenterOfGravity = function() {
    return this.p;
};
Body.prototype.isSleeping = function()
{
    return this.nodeRoot !== null;
};
Body.prototype.isStatic = function()
{
    return this.nodeIdleTime === Infinity;
};
Body.prototype.isRogue = function()
{
    return this.space === null;
};
Body.prototype.setMass = function(mass)
{
    assert(mass > 0, "Mass must be positive and non-zero.");
    this.activate();
    this.m = mass;
    this.m_inv = 1/mass;
};
Body.prototype.setMoment = function(moment)
{
    assert(moment > 0, "Moment of Inertia must be positive and non-zero.");
    this.activate();
    this.i = moment;
    this.i_inv = 1/moment;
};
Body.prototype.addShape = function(shape)
{
    this.shapeList.push(shape);
};
Body.prototype.removeShape = function(shape)
{
    deleteObjFromList(this.shapeList, shape);
};
var filterConstraints = function(node, body, filter)
{
    if(node === filter){
        return node.next(body);
    } else if(node.a === body){
        node.next_a = filterConstraints(node.next_a, body, filter);
    } else {
        node.next_b = filterConstraints(node.next_b, body, filter);
    }
    return node;
};
Body.prototype.removeConstraint = function(constraint)
{
    this.constraintList = filterConstraints(this.constraintList, this, constraint);
};
Body.prototype.setPos = function(pos)
{
    this.activate();
    this.sanityCheck();
    if (pos === vzero) {
        pos = cp.v(0,0);
    }
    this.p = pos;
};
Body.prototype.setVel = function(velocity)
{
    this.activate();
    this.vx = velocity.x;
    this.vy = velocity.y;
};
Body.prototype.setAngVel = function(w)
{
    this.activate();
    this.w = w;
};
Body.prototype.setAngleInternal = function(angle)
{
    assert(!isNaN(angle), "Internal Error: Attempting to set body's angle to NaN");
    this.a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
    this.rot.x = Math.cos(angle);
    this.rot.y = Math.sin(angle);
};
Body.prototype.setAngle = function(angle)
{
    this.activate();
    this.sanityCheck();
    this.setAngleInternal(angle);
};
Body.prototype.velocity_func = function(gravity, damping, dt)
{
    var vx = this.vx * damping + (gravity.x + this.f.x * this.m_inv) * dt;
    var vy = this.vy * damping + (gravity.y + this.f.y * this.m_inv) * dt;
    var v_limit = this.v_limit;
    var lensq = vx * vx + vy * vy;
    var scale = (lensq > v_limit*v_limit) ? v_limit / Math.sqrt(lensq) : 1;
    this.vx = vx * scale;
    this.vy = vy * scale;
    var w_limit = this.w_limit;
    this.w = clamp(this.w*damping + this.t*this.i_inv*dt, -w_limit, w_limit);
    this.sanityCheck();
};
Body.prototype.position_func = function(dt)
{
    this.p.x += (this.vx + this.v_biasx) * dt;
    this.p.y += (this.vy + this.v_biasy) * dt;
    this.setAngleInternal(this.a + (this.w + this.w_bias)*dt);
    this.v_biasx = this.v_biasy = 0;
    this.w_bias = 0;
    this.sanityCheck();
};
Body.prototype.resetForces = function()
{
    this.activate();
    this.f = new Vect(0,0);
    this.t = 0;
};
Body.prototype.applyForce = function(force, r)
{
    this.activate();
    this.f = vadd(this.f, force);
    this.t += vcross(r, force);
};
Body.prototype.applyImpulse = function(j, r)
{
    this.activate();
    apply_impulse(this, j.x, j.y, r);
};
Body.prototype.getVelAtPoint = function(r)
{
    return vadd(new Vect(this.vx, this.vy), vmult(vperp(r), this.w));
};
Body.prototype.getVelAtWorldPoint = function(point)
{
    return this.getVelAtPoint(vsub(point, this.p));
};
Body.prototype.getVelAtLocalPoint = function(point)
{
    return this.getVelAtPoint(vrotate(point, this.rot));
};
Body.prototype.eachShape = function(func)
{
    for(var i = 0, len = this.shapeList.length; i < len; i++) {
        func(this.shapeList[i]);
    }
};
Body.prototype.eachConstraint = function(func)
{
    var constraint = this.constraintList;
    while(constraint) {
        var next = constraint.next(this);
        func(constraint);
        constraint = next;
    }
};
Body.prototype.eachArbiter = function(func)
{
    var arb = this.arbiterList;
    while(arb){
        var next = arb.next(this);
        arb.swappedColl = (this === arb.body_b);
        func(arb);
        arb = next;
    }
};
Body.prototype.local2World = function(v)
{
    return vadd(this.p, vrotate(v, this.rot));
};
Body.prototype.world2Local = function(v)
{
    return vunrotate(vsub(v, this.p), this.rot);
};
Body.prototype.localToWorld = Body.prototype.local2World;
Body.prototype.worldToLocal = Body.prototype.world2Local;
Body.prototype.kineticEnergy = function()
{
    var vsq = this.vx*this.vx + this.vy*this.vy;
    var wsq = this.w * this.w;
    return (vsq ? vsq*this.m : 0) + (wsq ? wsq*this.i : 0);
};
var SpatialIndex = cp.SpatialIndex = function(staticIndex)
{
    this.staticIndex = staticIndex;
    if(staticIndex){
        if(staticIndex.dynamicIndex){
            throw new Error("This static index is already associated with a dynamic index.");
        }
        staticIndex.dynamicIndex = this;
    }
};
SpatialIndex.prototype.collideStatic = function(staticIndex, func)
{
    if(staticIndex.count > 0){
        var query = staticIndex.query;
        this.each(function(obj) {
            query(obj, new BB(obj.bb_l, obj.bb_b, obj.bb_r, obj.bb_t), func);
        });
    }
};
var BBTree = cp.BBTree = function(staticIndex)
{
    SpatialIndex.call(this, staticIndex);
    this.velocityFunc = null;
    this.leaves = {};
    this.count = 0;
    this.root = null;
    this.pooledNodes = null;
    this.pooledPairs = null;
    this.stamp = 0;
};
BBTree.prototype = Object.create(SpatialIndex.prototype);
var numNodes = 0;
var Node = function(tree, a, b)
{
    this.obj = null;
    this.bb_l = min(a.bb_l, b.bb_l);
    this.bb_b = min(a.bb_b, b.bb_b);
    this.bb_r = max(a.bb_r, b.bb_r);
    this.bb_t = max(a.bb_t, b.bb_t);
    this.parent = null;
    this.setA(a);
    this.setB(b);
};
BBTree.prototype.makeNode = function(a, b)
{
    var node = this.pooledNodes;
    if(node){
        this.pooledNodes = node.parent;
        node.constructor(this, a, b);
        return node;
    } else {
        numNodes++;
        return new Node(this, a, b);
    }
};
var numLeaves = 0;
var Leaf = function(tree, obj)
{
    this.obj = obj;
    tree.getBB(obj, this);
    this.parent = null;
    this.stamp = 1;
    this.pairs = null;
    numLeaves++;
};
BBTree.prototype.getBB = function(obj, dest)
{
    var velocityFunc = this.velocityFunc;
    if(velocityFunc){
        var coef = 0.1;
        var x = (obj.bb_r - obj.bb_l)*coef;
        var y = (obj.bb_t - obj.bb_b)*coef;
        var v = vmult(velocityFunc(obj), 0.1);
        dest.bb_l = obj.bb_l + min(-x, v.x);
        dest.bb_b = obj.bb_b + min(-y, v.y);
        dest.bb_r = obj.bb_r + max( x, v.x);
        dest.bb_t = obj.bb_t + max( y, v.y);
    } else {
        dest.bb_l = obj.bb_l;
        dest.bb_b = obj.bb_b;
        dest.bb_r = obj.bb_r;
        dest.bb_t = obj.bb_t;
    }
};
BBTree.prototype.getStamp = function()
{
    var dynamic = this.dynamicIndex;
    return (dynamic && dynamic.stamp ? dynamic.stamp : this.stamp);
};
BBTree.prototype.incrementStamp = function()
{
    if(this.dynamicIndex && this.dynamicIndex.stamp){
        this.dynamicIndex.stamp++;
    } else {
        this.stamp++;
    }
}
var numPairs = 0;
var Pair = function(leafA, nextA, leafB, nextB)
{
    this.prevA = null;
    this.leafA = leafA;
    this.nextA = nextA;
    this.prevB = null;
    this.leafB = leafB;
    this.nextB = nextB;
};
BBTree.prototype.makePair = function(leafA, nextA, leafB, nextB)
{
    var pair = this.pooledPairs;
    if (pair)
    {
        this.pooledPairs = pair.prevA;
        pair.prevA = null;
        pair.leafA = leafA;
        pair.nextA = nextA;
        pair.prevB = null;
        pair.leafB = leafB;
        pair.nextB = nextB;
        return pair;
    } else {
        numPairs++;
        return new Pair(leafA, nextA, leafB, nextB);
    }
};
Pair.prototype.recycle = function(tree)
{
    this.prevA = tree.pooledPairs;
    tree.pooledPairs = this;
};
var unlinkThread = function(prev, leaf, next)
{
    if(next){
        if(next.leafA === leaf) next.prevA = prev; else next.prevB = prev;
    }
    if(prev){
        if(prev.leafA === leaf) prev.nextA = next; else prev.nextB = next;
    } else {
        leaf.pairs = next;
    }
};
Leaf.prototype.clearPairs = function(tree)
{
    var pair = this.pairs,
        next;
    this.pairs = null;
    while(pair){
        if(pair.leafA === this){
            next = pair.nextA;
            unlinkThread(pair.prevB, pair.leafB, pair.nextB);
        } else {
            next = pair.nextB;
            unlinkThread(pair.prevA, pair.leafA, pair.nextA);
        }
        pair.recycle(tree);
        pair = next;
    }
};
var pairInsert = function(a, b, tree)
{
    var nextA = a.pairs, nextB = b.pairs;
    var pair = tree.makePair(a, nextA, b, nextB);
    a.pairs = b.pairs = pair;
    if(nextA){
        if(nextA.leafA === a) nextA.prevA = pair; else nextA.prevB = pair;
    }
    if(nextB){
        if(nextB.leafA === b) nextB.prevA = pair; else nextB.prevB = pair;
    }
};
Node.prototype.recycle = function(tree)
{
    this.parent = tree.pooledNodes;
    tree.pooledNodes = this;
};
Leaf.prototype.recycle = function(tree)
{
};
Node.prototype.setA = function(value)
{
    this.A = value;
    value.parent = this;
};
Node.prototype.setB = function(value)
{
    this.B = value;
    value.parent = this;
};
Leaf.prototype.isLeaf = true;
Node.prototype.isLeaf = false;
Node.prototype.otherChild = function(child)
{
    return (this.A == child ? this.B : this.A);
};
Node.prototype.replaceChild = function(child, value, tree)
{
    assertSoft(child == this.A || child == this.B, "Node is not a child of parent.");
    if(this.A == child){
        this.A.recycle(tree);
        this.setA(value);
    } else {
        this.B.recycle(tree);
        this.setB(value);
    }
    for(var node=this; node; node = node.parent){
        var a = node.A;
        var b = node.B;
        node.bb_l = min(a.bb_l, b.bb_l);
        node.bb_b = min(a.bb_b, b.bb_b);
        node.bb_r = max(a.bb_r, b.bb_r);
        node.bb_t = max(a.bb_t, b.bb_t);
    }
};
Node.prototype.bbArea = Leaf.prototype.bbArea = function()
{
    return (this.bb_r - this.bb_l)*(this.bb_t - this.bb_b);
};
var bbTreeMergedArea = function(a, b)
{
    return (max(a.bb_r, b.bb_r) - min(a.bb_l, b.bb_l))*(max(a.bb_t, b.bb_t) - min(a.bb_b, b.bb_b));
};
var bbProximity = function(a, b)
{
    return Math.abs(a.bb_l + a.bb_r - b.bb_l - b.bb_r) + Math.abs(a.bb_b + a.bb_t - b.bb_b - b.bb_t);
};
var subtreeInsert = function(subtree, leaf, tree)
{
    if(subtree == null){
        return leaf;
    } else if(subtree.isLeaf){
        return tree.makeNode(leaf, subtree);
    } else {
        var cost_a = subtree.B.bbArea() + bbTreeMergedArea(subtree.A, leaf);
        var cost_b = subtree.A.bbArea() + bbTreeMergedArea(subtree.B, leaf);
        if(cost_a === cost_b){
            cost_a = bbProximity(subtree.A, leaf);
            cost_b = bbProximity(subtree.B, leaf);
        }
        if(cost_b < cost_a){
            subtree.setB(subtreeInsert(subtree.B, leaf, tree));
        } else {
            subtree.setA(subtreeInsert(subtree.A, leaf, tree));
        }
        subtree.bb_l = min(subtree.bb_l, leaf.bb_l);
        subtree.bb_b = min(subtree.bb_b, leaf.bb_b);
        subtree.bb_r = max(subtree.bb_r, leaf.bb_r);
        subtree.bb_t = max(subtree.bb_t, leaf.bb_t);
        return subtree;
    }
};
Node.prototype.intersectsBB = Leaf.prototype.intersectsBB = function(bb)
{
    return (this.bb_l <= bb.r && bb.l <= this.bb_r && this.bb_b <= bb.t && bb.b <= this.bb_t);
};
var subtreeQuery = function(subtree, bb, func)
{
    if(subtree.intersectsBB(bb)){
        if(subtree.isLeaf){
            func(subtree.obj);
        } else {
            subtreeQuery(subtree.A, bb, func);
            subtreeQuery(subtree.B, bb, func);
        }
    }
};
var nodeSegmentQuery = function(node, a, b)
{
    var idx = 1/(b.x - a.x);
    var tx1 = (node.bb_l == a.x ? -Infinity : (node.bb_l - a.x)*idx);
    var tx2 = (node.bb_r == a.x ?  Infinity : (node.bb_r - a.x)*idx);
    var txmin = min(tx1, tx2);
    var txmax = max(tx1, tx2);
    var idy = 1/(b.y - a.y);
    var ty1 = (node.bb_b == a.y ? -Infinity : (node.bb_b - a.y)*idy);
    var ty2 = (node.bb_t == a.y ?  Infinity : (node.bb_t - a.y)*idy);
    var tymin = min(ty1, ty2);
    var tymax = max(ty1, ty2);
    if(tymin <= txmax && txmin <= tymax){
        var min_ = max(txmin, tymin);
        var max_ = min(txmax, tymax);
        if(0.0 <= max_ && min_ <= 1.0) return max(min_, 0.0);
    }
    return Infinity;
};
var subtreeSegmentQuery = function(subtree, a, b, t_exit, func)
{
    if(subtree.isLeaf){
        return func(subtree.obj);
    } else {
        var t_a = nodeSegmentQuery(subtree.A, a, b);
        var t_b = nodeSegmentQuery(subtree.B, a, b);
        if(t_a < t_b){
            if(t_a < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.A, a, b, t_exit, func));
            if(t_b < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.B, a, b, t_exit, func));
        } else {
            if(t_b < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.B, a, b, t_exit, func));
            if(t_a < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.A, a, b, t_exit, func));
        }
        return t_exit;
    }
};
BBTree.prototype.subtreeRecycle = function(node)
{
    if(node.isLeaf){
        this.subtreeRecycle(node.A);
        this.subtreeRecycle(node.B);
        node.recycle(this);
    }
};
var subtreeRemove = function(subtree, leaf, tree)
{
    if(leaf == subtree){
        return null;
    } else {
        var parent = leaf.parent;
        if(parent == subtree){
            var other = subtree.otherChild(leaf);
            other.parent = subtree.parent;
            subtree.recycle(tree);
            return other;
        } else {
            parent.parent.replaceChild(parent, parent.otherChild(leaf), tree);
            return subtree;
        }
    }
};
var bbTreeIntersectsNode = function(a, b)
{
    return (a.bb_l <= b.bb_r && b.bb_l <= a.bb_r && a.bb_b <= b.bb_t && b.bb_b <= a.bb_t);
};
Leaf.prototype.markLeafQuery = function(leaf, left, tree, func)
{
    if(bbTreeIntersectsNode(leaf, this)){
    if(left){
      pairInsert(leaf, this, tree);
    } else {
      if(this.stamp < leaf.stamp) pairInsert(this, leaf, tree);
      if(func) func(leaf.obj, this.obj);
    }
  }
};
Node.prototype.markLeafQuery = function(leaf, left, tree, func)
{
    if(bbTreeIntersectsNode(leaf, this)){
    this.A.markLeafQuery(leaf, left, tree, func);
    this.B.markLeafQuery(leaf, left, tree, func);
    }
};
Leaf.prototype.markSubtree = function(tree, staticRoot, func)
{
    if(this.stamp == tree.getStamp()){
        if(staticRoot) staticRoot.markLeafQuery(this, false, tree, func);
        for(var node = this; node.parent; node = node.parent){
            if(node == node.parent.A){
                node.parent.B.markLeafQuery(this, true, tree, func);
            } else {
                node.parent.A.markLeafQuery(this, false, tree, func);
            }
        }
    } else {
        var pair = this.pairs;
        while(pair){
            if(this === pair.leafB){
                if(func) func(pair.leafA.obj, this.obj);
                pair = pair.nextB;
            } else {
                pair = pair.nextA;
            }
        }
    }
};
Node.prototype.markSubtree = function(tree, staticRoot, func)
{
  this.A.markSubtree(tree, staticRoot, func);
  this.B.markSubtree(tree, staticRoot, func);
};
Leaf.prototype.containsObj = function(obj)
{
    return (this.bb_l <= obj.bb_l && this.bb_r >= obj.bb_r && this.bb_b <= obj.bb_b && this.bb_t >= obj.bb_t);
};
Leaf.prototype.update = function(tree)
{
    var root = tree.root;
    var obj = this.obj;
    if(!this.containsObj(obj)){
        tree.getBB(this.obj, this);
        root = subtreeRemove(root, this, tree);
        tree.root = subtreeInsert(root, this, tree);
        this.clearPairs(tree);
        this.stamp = tree.getStamp();
        return true;
    }
    return false;
};
Leaf.prototype.addPairs = function(tree)
{
    var dynamicIndex = tree.dynamicIndex;
    if(dynamicIndex){
        var dynamicRoot = dynamicIndex.root;
        if(dynamicRoot){
            dynamicRoot.markLeafQuery(this, true, dynamicIndex, null);
        }
    } else {
        var staticRoot = tree.staticIndex.root;
        this.markSubtree(tree, staticRoot, null);
    }
};
BBTree.prototype.insert = function(obj, hashid)
{
    var leaf = new Leaf(this, obj);
    this.leaves[hashid] = leaf;
    this.root = subtreeInsert(this.root, leaf, this);
    this.count++;
    leaf.stamp = this.getStamp();
    leaf.addPairs(this);
    this.incrementStamp();
};
BBTree.prototype.remove = function(obj, hashid)
{
    var leaf = this.leaves[hashid];
    delete this.leaves[hashid];
    this.root = subtreeRemove(this.root, leaf, this);
    this.count--;
    leaf.clearPairs(this);
    leaf.recycle(this);
};
BBTree.prototype.contains = function(obj, hashid)
{
    return this.leaves[hashid] != null;
};
var voidQueryFunc = function(obj1, obj2){};
BBTree.prototype.reindexQuery = function(func)
{
    if(!this.root) return;
    var hashid,
        leaves = this.leaves;
    for (hashid in leaves)
    {
        leaves[hashid].update(this);
    }
    var staticIndex = this.staticIndex;
    var staticRoot = staticIndex && staticIndex.root;
    this.root.markSubtree(this, staticRoot, func);
    if(staticIndex && !staticRoot) this.collideStatic(this, staticIndex, func);
    this.incrementStamp();
};
BBTree.prototype.reindex = function()
{
    this.reindexQuery(voidQueryFunc);
};
BBTree.prototype.reindexObject = function(obj, hashid)
{
    var leaf = this.leaves[hashid];
    if(leaf){
        if(leaf.update(this)) leaf.addPairs(this);
        this.incrementStamp();
    }
};
BBTree.prototype.pointQuery = function(point, func)
{
    this.query(new BB(point.x, point.y, point.x, point.y), func);
};
BBTree.prototype.segmentQuery = function(a, b, t_exit, func)
{
    if(this.root) subtreeSegmentQuery(this.root, a, b, t_exit, func);
};
BBTree.prototype.query = function(bb, func)
{
    if(this.root) subtreeQuery(this.root, bb, func);
};
BBTree.prototype.count = function()
{
    return this.count;
};
BBTree.prototype.each = function(func)
{
    var hashid;
    for(hashid in this.leaves)
    {
        func(this.leaves[hashid].obj);
    }
};
var bbTreeMergedArea2 = function(node, l, b, r, t)
{
    return (max(node.bb_r, r) - min(node.bb_l, l))*(max(node.bb_t, t) - min(node.bb_b, b));
};
var partitionNodes = function(tree, nodes, offset, count)
{
    if(count == 1){
        return nodes[offset];
    } else if(count == 2) {
        return tree.makeNode(nodes[offset], nodes[offset + 1]);
    }
    var node = nodes[offset];
    var bb_l = node.bb_l,
        bb_b = node.bb_b,
        bb_r = node.bb_r,
        bb_t = node.bb_t;
    var end = offset + count;
    for(var i=offset + 1; i<end; i++){
        node = nodes[i];
        bb_l = min(bb_l, node.bb_l);
        bb_b = min(bb_b, node.bb_b);
        bb_r = max(bb_r, node.bb_r);
        bb_t = max(bb_t, node.bb_t);
    }
    var splitWidth = (bb_r - bb_l > bb_t - bb_b);
    var bounds = new Array(count*2);
    if(splitWidth){
        for(var i=offset; i<end; i++){
            bounds[2*i + 0] = nodes[i].bb_l;
            bounds[2*i + 1] = nodes[i].bb_r;
        }
    } else {
        for(var i=offset; i<end; i++){
            bounds[2*i + 0] = nodes[i].bb_b;
            bounds[2*i + 1] = nodes[i].bb_t;
        }
    }
    bounds.sort(function(a, b) {
        return a - b;
    });
    var split = (bounds[count - 1] + bounds[count])*0.5;
    var a_l = bb_l, a_b = bb_b, a_r = bb_r, a_t = bb_t;
    var b_l = bb_l, b_b = bb_b, b_r = bb_r, b_t = bb_t;
    if(splitWidth) a_r = b_l = split; else a_t = b_b = split;
    var right = end;
    for(var left=offset; left < right;){
        var node = nodes[left];
        if(bbTreeMergedArea2(node, b_l, b_b, b_r, b_t) < bbTreeMergedArea2(node, a_l, a_b, a_r, a_t)){
            right--;
            nodes[left] = nodes[right];
            nodes[right] = node;
        } else {
            left++;
        }
    }
    if(right == count){
        var node = null;
        for(var i=offset; i<end; i++) node = subtreeInsert(node, nodes[i], tree);
        return node;
    }
    return NodeNew(tree,
        partitionNodes(tree, nodes, offset, right - offset),
        partitionNodes(tree, nodes, right, end - right)
    );
};
BBTree.prototype.optimize = function()
{
    var nodes = new Array(this.count);
    var i = 0;
    for (var hashid in this.leaves)
    {
        nodes[i++] = this.nodes[hashid];
    }
    tree.subtreeRecycle(root);
    this.root = partitionNodes(tree, nodes, nodes.length);
};
var nodeRender = function(node, depth)
{
    if(!node.isLeaf && depth <= 10){
        nodeRender(node.A, depth + 1);
        nodeRender(node.B, depth + 1);
    }
    var str = '';
    for(var i = 0; i < depth; i++) {
        str += ' ';
    }
    console.log(str + node.bb_b + ' ' + node.bb_t);
};
BBTree.prototype.log = function(){
    if(this.root) nodeRender(this.root, 0);
};
var CollisionHandler = cp.CollisionHandler = function()
{
    this.a = this.b = 0;
};
CollisionHandler.prototype.begin = function(arb, space){return true;};
CollisionHandler.prototype.preSolve = function(arb, space){return true;};
CollisionHandler.prototype.postSolve = function(arb, space){};
CollisionHandler.prototype.separate = function(arb, space){};
var CP_MAX_CONTACTS_PER_ARBITER = 4;
var Arbiter = function(a, b) {
    this.e = 0;
    this.u = 0;
    this.surface_vr = vzero;
    this.a = a; this.body_a = a.body;
    this.b = b; this.body_b = b.body;
    this.thread_a_next = this.thread_a_prev = null;
    this.thread_b_next = this.thread_b_prev = null;
    this.contacts = null;
    this.stamp = 0;
    this.handler = null;
    this.swappedColl = false;
    this.state = 'first coll';
};
Arbiter.prototype.getShapes = function()
{
    if (this.swappedColl){
        return [this.b, this.a];
    }else{
        return [this.a, this.b];
    }
}
Arbiter.prototype.totalImpulse = function()
{
    var contacts = this.contacts;
    var sum = new Vect(0,0);
    for(var i=0, count=contacts.length; i<count; i++){
        var con = contacts[i];
        sum.add(vmult(con.n, con.jnAcc));
    }
    return this.swappedColl ? sum : sum.neg();
};
Arbiter.prototype.totalImpulseWithFriction = function()
{
    var contacts = this.contacts;
    var sum = new Vect(0,0);
    for(var i=0, count=contacts.length; i<count; i++){
        var con = contacts[i];
        sum.add(new Vect(con.jnAcc, con.jtAcc).rotate(con.n));
    }
    return this.swappedColl ? sum : sum.neg();
};
Arbiter.prototype.totalKE = function()
{
    var eCoef = (1 - this.e)/(1 + this.e);
    var sum = 0;
    var contacts = this.contacts;
    for(var i=0, count=contacts.length; i<count; i++){
        var con = contacts[i];
        var jnAcc = con.jnAcc;
        var jtAcc = con.jtAcc;
        sum += eCoef*jnAcc*jnAcc/con.nMass + jtAcc*jtAcc/con.tMass;
    }
    return sum;
};
Arbiter.prototype.ignore = function()
{
    this.state = 'ignore';
};
Arbiter.prototype.getA = function()
{
    return this.swappedColl ? this.b : this.a;
};
Arbiter.prototype.getB = function()
{
    return this.swappedColl ? this.a : this.b;
};
Arbiter.prototype.isFirstContact = function()
{
    return this.state === 'first coll';
};
var ContactPoint = function(point, normal, dist)
{
    this.point = point;
    this.normal = normal;
    this.dist = dist;
};
Arbiter.prototype.getContactPointSet = function()
{
    var set = new Array(this.contacts.length);
    var i;
    for(i=0; i<set.length; i++){
        set[i] = new ContactPoint(this.contacts[i].p, this.contacts[i].n, this.contacts[i].dist);
    }
    return set;
};
Arbiter.prototype.getNormal = function(i)
{
    var n = this.contacts[i].n;
    return this.swappedColl ? vneg(n) : n;
};
Arbiter.prototype.getPoint = function(i)
{
    return this.contacts[i].p;
};
Arbiter.prototype.getDepth = function(i)
{
    return this.contacts[i].dist;
};
var unthreadHelper = function(arb, body, prev, next)
{
    if(prev){
        if(prev.body_a === body) {
            prev.thread_a_next = next;
        } else {
            prev.thread_b_next = next;
        }
    } else {
        body.arbiterList = next;
    }
    if(next){
        if(next.body_a === body){
            next.thread_a_prev = prev;
        } else {
            next.thread_b_prev = prev;
        }
    }
};
Arbiter.prototype.unthread = function()
{
    unthreadHelper(this, this.body_a, this.thread_a_prev, this.thread_a_next);
    unthreadHelper(this, this.body_b, this.thread_b_prev, this.thread_b_next);
    this.thread_a_prev = this.thread_a_next = null;
    this.thread_b_prev = this.thread_b_next = null;
};
Arbiter.prototype.update = function(contacts, handler, a, b)
{
    if(this.contacts){
        for(var i=0; i<this.contacts.length; i++){
            var old = this.contacts[i];
            for(var j=0; j<contacts.length; j++){
                var new_contact = contacts[j];
                if(new_contact.hash === old.hash){
                    new_contact.jnAcc = old.jnAcc;
                    new_contact.jtAcc = old.jtAcc;
                }
            }
        }
    }
    this.contacts = contacts;
    this.handler = handler;
    this.swappedColl = (a.collision_type !== handler.a);
    this.e = a.e * b.e;
    this.u = a.u * b.u;
    this.surface_vr = vsub(a.surface_v, b.surface_v);
    this.a = a; this.body_a = a.body;
    this.b = b; this.body_b = b.body;
    if(this.state == 'cached') this.state = 'first coll';
};
Arbiter.prototype.preStep = function(dt, slop, bias)
{
    var a = this.body_a;
    var b = this.body_b;
    for(var i=0; i<this.contacts.length; i++){
        var con = this.contacts[i];
        con.r1 = vsub(con.p, a.p);
        con.r2 = vsub(con.p, b.p);
        con.nMass = 1/k_scalar(a, b, con.r1, con.r2, con.n);
        con.tMass = 1/k_scalar(a, b, con.r1, con.r2, vperp(con.n));
        con.bias = -bias*min(0, con.dist + slop)/dt;
        con.jBias = 0;
        con.bounce = normal_relative_velocity(a, b, con.r1, con.r2, con.n)*this.e;
    }
};
Arbiter.prototype.applyCachedImpulse = function(dt_coef)
{
    if(this.isFirstContact()) return;
    var a = this.body_a;
    var b = this.body_b;
    for(var i=0; i<this.contacts.length; i++){
        var con = this.contacts[i];
        var nx = con.n.x;
        var ny = con.n.y;
        var jx = nx*con.jnAcc - ny*con.jtAcc;
        var jy = nx*con.jtAcc + ny*con.jnAcc;
        apply_impulses(a, b, con.r1, con.r2, jx * dt_coef, jy * dt_coef);
    }
};
var numApplyImpulse = 0;
var numApplyContact = 0;
Arbiter.prototype.applyImpulse = function()
{
    numApplyImpulse++;
    var a = this.body_a;
    var b = this.body_b;
    var surface_vr = this.surface_vr;
    var friction = this.u;
    for(var i=0; i<this.contacts.length; i++){
        numApplyContact++;
        var con = this.contacts[i];
        var nMass = con.nMass;
        var n = con.n;
        var r1 = con.r1;
        var r2 = con.r2;
        var vrx = b.vx - r2.y * b.w - (a.vx - r1.y * a.w);
        var vry = b.vy + r2.x * b.w - (a.vy + r1.x * a.w);
        var vbn = n.x*(b.v_biasx - r2.y * b.w_bias - a.v_biasx + r1.y * a.w_bias) +
                n.y*(r2.x*b.w_bias + b.v_biasy - r1.x * a.w_bias - a.v_biasy);
        var vrn = vdot2(vrx, vry, n.x, n.y);
        var vrt = vdot2(vrx + surface_vr.x, vry + surface_vr.y, -n.y, n.x);
        var jbn = (con.bias - vbn)*nMass;
        var jbnOld = con.jBias;
        con.jBias = max(jbnOld + jbn, 0);
        var jn = -(con.bounce + vrn)*nMass;
        var jnOld = con.jnAcc;
        con.jnAcc = max(jnOld + jn, 0);
        var jtMax = friction*con.jnAcc;
        var jt = -vrt*con.tMass;
        var jtOld = con.jtAcc;
        con.jtAcc = clamp(jtOld + jt, -jtMax, jtMax);
        var bias_x = n.x * (con.jBias - jbnOld);
        var bias_y = n.y * (con.jBias - jbnOld);
        apply_bias_impulse(a, -bias_x, -bias_y, r1);
        apply_bias_impulse(b, bias_x, bias_y, r2);
        var rot_x = con.jnAcc - jnOld;
        var rot_y = con.jtAcc - jtOld;
        apply_impulses(a, b, r1, r2, n.x*rot_x - n.y*rot_y, n.x*rot_y + n.y*rot_x);
    }
};
Arbiter.prototype.callSeparate = function(space)
{
    var handler = space.lookupHandler(this.a.collision_type, this.b.collision_type);
    handler.separate(this, space);
};
Arbiter.prototype.next = function(body)
{
    return (this.body_a == body ? this.thread_a_next : this.thread_b_next);
};
var numContacts = 0;
var Contact = function(p, n, dist, hash)
{
    this.p = p;
    this.n = n;
    this.dist = dist;
    this.r1 = this.r2 = vzero;
    this.nMass = this.tMass = this.bounce = this.bias = 0;
    this.jnAcc = this.jtAcc = this.jBias = 0;
    this.hash = hash;
    numContacts++;
};
var NONE = [];
var circle2circleQuery = function(p1, p2, r1, r2)
{
    var mindist = r1 + r2;
    var delta = vsub(p2, p1);
    var distsq = vlengthsq(delta);
    if(distsq >= mindist*mindist) return;
    var dist = Math.sqrt(distsq);
    return new Contact(
        vadd(p1, vmult(delta, 0.5 + (r1 - 0.5*mindist)/(dist ? dist : Infinity))),
        (dist ? vmult(delta, 1/dist) : new Vect(1, 0)),
        dist - mindist,
        0
    );
};
var circle2circle = function(circ1, circ2)
{
    var contact = circle2circleQuery(circ1.tc, circ2.tc, circ1.r, circ2.r);
    return contact ? [contact] : NONE;
};
var circle2segment = function(circleShape, segmentShape)
{
    var seg_a = segmentShape.ta;
    var seg_b = segmentShape.tb;
    var center = circleShape.tc;
    var seg_delta = vsub(seg_b, seg_a);
    var closest_t = clamp01(vdot(seg_delta, vsub(center, seg_a))/vlengthsq(seg_delta));
    var closest = vadd(seg_a, vmult(seg_delta, closest_t));
    var contact = circle2circleQuery(center, closest, circleShape.r, segmentShape.r);
    if(contact){
        var n = contact.n;
        return (
            (closest_t === 0 && vdot(n, segmentShape.a_tangent) < 0) ||
            (closest_t === 1 && vdot(n, segmentShape.b_tangent) < 0)
        ) ? NONE : [contact];
    } else {
        return NONE;
    }
}
var last_MSA_min = 0;
var findMSA = function(poly, planes)
{
    var min_index = 0;
    var min = poly.valueOnAxis(planes[0].n, planes[0].d);
    if(min > 0) return -1;
    for(var i=1; i<planes.length; i++){
        var dist = poly.valueOnAxis(planes[i].n, planes[i].d);
        if(dist > 0) {
            return -1;
        } else if(dist > min){
            min = dist;
            min_index = i;
        }
    }
    last_MSA_min = min;
    return min_index;
};
var findVertsFallback = function(poly1, poly2, n, dist)
{
    var arr = [];
    var verts1 = poly1.tVerts;
    for(var i=0; i<verts1.length; i+=2){
        var vx = verts1[i];
        var vy = verts1[i+1];
        if(poly2.containsVertPartial(vx, vy, vneg(n))){
            arr.push(new Contact(new Vect(vx, vy), n, dist, hashPair(poly1.hashid, i)));
        }
    }
    var verts2 = poly2.tVerts;
    for(var i=0; i<verts2.length; i+=2){
        var vx = verts2[i];
        var vy = verts2[i+1];
        if(poly1.containsVertPartial(vx, vy, n)){
            arr.push(new Contact(new Vect(vx, vy), n, dist, hashPair(poly2.hashid, i)));
        }
    }
    return arr;
};
var findVerts = function(poly1, poly2, n, dist)
{
    var arr = [];
    var verts1 = poly1.tVerts;
    for(var i=0; i<verts1.length; i+=2){
        var vx = verts1[i];
        var vy = verts1[i+1];
        if(poly2.containsVert(vx, vy)){
            arr.push(new Contact(new Vect(vx, vy), n, dist, hashPair(poly1.hashid, i>>1)));
        }
    }
    var verts2 = poly2.tVerts;
    for(var i=0; i<verts2.length; i+=2){
        var vx = verts2[i];
        var vy = verts2[i+1];
        if(poly1.containsVert(vx, vy)){
            arr.push(new Contact(new Vect(vx, vy), n, dist, hashPair(poly2.hashid, i>>1)));
        }
    }
    return (arr.length ? arr : findVertsFallback(poly1, poly2, n, dist));
};
var poly2poly = function(poly1, poly2)
{
    var mini1 = findMSA(poly2, poly1.tPlanes);
    if(mini1 == -1) return NONE;
    var min1 = last_MSA_min;
    var mini2 = findMSA(poly1, poly2.tPlanes);
    if(mini2 == -1) return NONE;
    var min2 = last_MSA_min;
    if(min1 > min2)
        return findVerts(poly1, poly2, poly1.tPlanes[mini1].n, min1);
    else
        return findVerts(poly1, poly2, vneg(poly2.tPlanes[mini2].n), min2);
};
var segValueOnAxis = function(seg, n, d)
{
    var a = vdot(n, seg.ta) - seg.r;
    var b = vdot(n, seg.tb) - seg.r;
    return min(a, b) - d;
};
var findPointsBehindSeg = function(arr, seg, poly, pDist, coef)
{
    var dta = vcross(seg.tn, seg.ta);
    var dtb = vcross(seg.tn, seg.tb);
    var n = vmult(seg.tn, coef);
    var verts = poly.tVerts;
    for(var i=0; i<verts.length; i+=2){
        var vx = verts[i];
        var vy = verts[i+1];
        if(vdot2(vx, vy, n.x, n.y) < vdot(seg.tn, seg.ta)*coef + seg.r){
            var dt = vcross2(seg.tn.x, seg.tn.y, vx, vy);
            if(dta >= dt && dt >= dtb){
                arr.push(new Contact(new Vect(vx, vy), n, pDist, hashPair(poly.hashid, i)));
            }
        }
    }
};
var seg2poly = function(seg, poly)
{
    var arr = [];
    var planes = poly.tPlanes;
    var numVerts = planes.length;
    var segD = vdot(seg.tn, seg.ta);
    var minNorm = poly.valueOnAxis(seg.tn, segD) - seg.r;
    var minNeg = poly.valueOnAxis(vneg(seg.tn), -segD) - seg.r;
    if(minNeg > 0 || minNorm > 0) return NONE;
    var mini = 0;
    var poly_min = segValueOnAxis(seg, planes[0].n, planes[0].d);
    if(poly_min > 0) return NONE;
    for(var i=0; i<numVerts; i++){
        var dist = segValueOnAxis(seg, planes[i].n, planes[i].d);
        if(dist > 0){
            return NONE;
        } else if(dist > poly_min){
            poly_min = dist;
            mini = i;
        }
    }
    var poly_n = vneg(planes[mini].n);
    var va = vadd(seg.ta, vmult(poly_n, seg.r));
    var vb = vadd(seg.tb, vmult(poly_n, seg.r));
    if(poly.containsVert(va.x, va.y))
        arr.push(new Contact(va, poly_n, poly_min, hashPair(seg.hashid, 0)));
    if(poly.containsVert(vb.x, vb.y))
        arr.push(new Contact(vb, poly_n, poly_min, hashPair(seg.hashid, 1)));
    if(minNorm >= poly_min || minNeg >= poly_min) {
        if(minNorm > minNeg)
            findPointsBehindSeg(arr, seg, poly, minNorm, 1);
        else
            findPointsBehindSeg(arr, seg, poly, minNeg, -1);
    }
    if(arr.length === 0){
        var mini2 = mini * 2;
        var verts = poly.tVerts;
        var poly_a = new Vect(verts[mini2], verts[mini2+1]);
        var con;
        if((con = circle2circleQuery(seg.ta, poly_a, seg.r, 0, arr))) return [con];
        if((con = circle2circleQuery(seg.tb, poly_a, seg.r, 0, arr))) return [con];
        var len = numVerts * 2;
        var poly_b = new Vect(verts[(mini2+2)%len], verts[(mini2+3)%len]);
        if((con = circle2circleQuery(seg.ta, poly_b, seg.r, 0, arr))) return [con];
        if((con = circle2circleQuery(seg.tb, poly_b, seg.r, 0, arr))) return [con];
    }
    return arr;
};
var circle2poly = function(circ, poly)
{
    var planes = poly.tPlanes;
    var mini = 0;
    var min = vdot(planes[0].n, circ.tc) - planes[0].d - circ.r;
    for(var i=0; i<planes.length; i++){
        var dist = vdot(planes[i].n, circ.tc) - planes[i].d - circ.r;
        if(dist > 0){
            return NONE;
        } else if(dist > min) {
            min = dist;
            mini = i;
        }
    }
    var n = planes[mini].n;
    var verts = poly.tVerts;
    var len = verts.length;
    var mini2 = mini<<1;
    var ax = verts[mini2];
    var ay = verts[mini2+1];
    var bx = verts[(mini2+2)%len];
    var by = verts[(mini2+3)%len];
    var dta = vcross2(n.x, n.y, ax, ay);
    var dtb = vcross2(n.x, n.y, bx, by);
    var dt = vcross(n, circ.tc);
    if(dt < dtb){
        var con = circle2circleQuery(circ.tc, new Vect(bx, by), circ.r, 0, con);
        return con ? [con] : NONE;
    } else if(dt < dta) {
        return [new Contact(
            vsub(circ.tc, vmult(n, circ.r + min/2)),
            vneg(n),
            min,
            0
        )];
    } else {
        var con = circle2circleQuery(circ.tc, new Vect(ax, ay), circ.r, 0, con);
        return con ? [con] : NONE;
    }
};
CircleShape.prototype.collisionCode = 0;
SegmentShape.prototype.collisionCode = 1;
PolyShape.prototype.collisionCode = 2;
CircleShape.prototype.collisionTable = [
    circle2circle,
    circle2segment,
    circle2poly
];
SegmentShape.prototype.collisionTable = [
    null,
    function(segA, segB) { return NONE; },
    seg2poly
];
PolyShape.prototype.collisionTable = [
    null,
    null,
    poly2poly
];
var collideShapes = cp.collideShapes = function(a, b)
{
    assert(a.collisionCode <= b.collisionCode, 'Collided shapes must be sorted by type');
    return a.collisionTable[b.collisionCode](a, b);
};
var defaultCollisionHandler = new CollisionHandler();
var Space = cp.Space = function() {
    this.stamp = 0;
    this.curr_dt = 0;
    this.bodies = [];
    this.rousedBodies = [];
    this.sleepingComponents = [];
    this.staticShapes = new BBTree(null);
    this.activeShapes = new BBTree(this.staticShapes);
    this.arbiters = [];
    this.contactBuffersHead = null;
    this.cachedArbiters = {};
    this.constraints = [];
    this.locked = 0;
    this.collisionHandlers = {};
    this.defaultHandler = defaultCollisionHandler;
    this.postStepCallbacks = [];
    this.iterations = 10;
    this.gravity = vzero;
    this.damping = 1;
    this.idleSpeedThreshold = 0;
    this.sleepTimeThreshold = Infinity;
    this.collisionSlop = 0.1;
    this.collisionBias = Math.pow(1 - 0.1, 60);
    this.collisionPersistence = 3;
    this.enableContactGraph = false;
    this.staticBody = new Body(Infinity, Infinity);
    this.staticBody.nodeIdleTime = Infinity;
    this.collideShapes = this.makeCollideShapes();
};
Space.prototype.getCurrentTimeStep = function() { return this.curr_dt; };
Space.prototype.setIterations = function(iter) { this.iterations = iter; };
Space.prototype.isLocked = function()
{
    return this.locked;
};
var assertSpaceUnlocked = function(space)
{
    assert(!space.locked, "This addition/removal cannot be done safely during a call to cpSpaceStep() \
 or during a query. Put these calls into a post-step callback.");
};
Space.prototype.addCollisionHandler = function(a, b, begin, preSolve, postSolve, separate)
{
    assertSpaceUnlocked(this);
    this.removeCollisionHandler(a, b);
    var handler = new CollisionHandler();
    handler.a = a;
    handler.b = b;
    if(begin) handler.begin = begin;
    if(preSolve) handler.preSolve = preSolve;
    if(postSolve) handler.postSolve = postSolve;
    if(separate) handler.separate = separate;
    this.collisionHandlers[hashPair(a, b)] = handler;
};
Space.prototype.removeCollisionHandler = function(a, b)
{
    assertSpaceUnlocked(this);
    delete this.collisionHandlers[hashPair(a, b)];
};
Space.prototype.setDefaultCollisionHandler = function(begin, preSolve, postSolve, separate)
{
    assertSpaceUnlocked(this);
    var handler = new CollisionHandler();
    if(begin) handler.begin = begin;
    if(preSolve) handler.preSolve = preSolve;
    if(postSolve) handler.postSolve = postSolve;
    if(separate) handler.separate = separate;
    this.defaultHandler = handler;
};
Space.prototype.lookupHandler = function(a, b)
{
    return this.collisionHandlers[hashPair(a, b)] || this.defaultHandler;
};
Space.prototype.addShape = function(shape)
{
    var body = shape.body;
    if(body.isStatic()) return this.addStaticShape(shape);
    assert(!shape.space, "This shape is already added to a space and cannot be added to another.");
    assertSpaceUnlocked(this);
    body.activate();
    body.addShape(shape);
    shape.update(body.p, body.rot);
    this.activeShapes.insert(shape, shape.hashid);
    shape.space = this;
    return shape;
};
Space.prototype.addStaticShape = function(shape)
{
    assert(!shape.space, "This shape is already added to a space and cannot be added to another.");
    assertSpaceUnlocked(this);
    var body = shape.body;
    body.addShape(shape);
    shape.update(body.p, body.rot);
    this.staticShapes.insert(shape, shape.hashid);
    shape.space = this;
    return shape;
};
Space.prototype.addBody = function(body)
{
    assert(!body.isStatic(), "Static bodies cannot be added to a space as they are not meant to be simulated.");
    assert(!body.space, "This body is already added to a space and cannot be added to another.");
    assertSpaceUnlocked(this);
    this.bodies.push(body);
    body.space = this;
    return body;
};
Space.prototype.addConstraint = function(constraint)
{
    assert(!constraint.space, "This shape is already added to a space and cannot be added to another.");
    assertSpaceUnlocked(this);
    var a = constraint.a, b = constraint.b;
    a.activate();
    b.activate();
    this.constraints.push(constraint);
    constraint.next_a = a.constraintList; a.constraintList = constraint;
    constraint.next_b = b.constraintList; b.constraintList = constraint;
    constraint.space = this;
    return constraint;
};
Space.prototype.filterArbiters = function(body, filter)
{
    for (var hash in this.cachedArbiters)
    {
        var arb = this.cachedArbiters[hash];
        if(
            (body === arb.body_a && (filter === arb.a || filter === null)) ||
            (body === arb.body_b && (filter === arb.b || filter === null))
        ){
            if(filter && arb.state !== 'cached') arb.callSeparate(this);
            arb.unthread();
            deleteObjFromList(this.arbiters, arb);
            delete this.cachedArbiters[hash];
        }
    }
};
Space.prototype.removeShape = function(shape)
{
    var body = shape.body;
    if(body.isStatic()){
        this.removeStaticShape(shape);
    } else {
        assert(this.containsShape(shape),
            "Cannot remove a shape that was not added to the space. (Removed twice maybe?)");
        assertSpaceUnlocked(this);
        body.activate();
        body.removeShape(shape);
        this.filterArbiters(body, shape);
        this.activeShapes.remove(shape, shape.hashid);
        shape.space = null;
    }
};
Space.prototype.removeStaticShape = function(shape)
{
    assert(this.containsShape(shape),
        "Cannot remove a static or sleeping shape that was not added to the space. (Removed twice maybe?)");
    assertSpaceUnlocked(this);
    var body = shape.body;
    if(body.isStatic()) body.activateStatic(shape);
    body.removeShape(shape);
    this.filterArbiters(body, shape);
    this.staticShapes.remove(shape, shape.hashid);
    shape.space = null;
};
Space.prototype.removeBody = function(body)
{
    assert(this.containsBody(body),
        "Cannot remove a body that was not added to the space. (Removed twice maybe?)");
    assertSpaceUnlocked(this);
    body.activate();
    deleteObjFromList(this.bodies, body);
    body.space = null;
};
Space.prototype.removeConstraint = function(constraint)
{
    assert(this.containsConstraint(constraint),
        "Cannot remove a constraint that was not added to the space. (Removed twice maybe?)");
    assertSpaceUnlocked(this);
    constraint.a.activate();
    constraint.b.activate();
    deleteObjFromList(this.constraints, constraint);
    constraint.a.removeConstraint(constraint);
    constraint.b.removeConstraint(constraint);
    constraint.space = null;
};
Space.prototype.containsShape = function(shape)
{
    return (shape.space === this);
};
Space.prototype.containsBody = function(body)
{
    return (body.space == this);
};
Space.prototype.containsConstraint = function(constraint)
{
    return (constraint.space == this);
};
Space.prototype.uncacheArbiter = function(arb)
{
    delete this.cachedArbiters[hashPair(arb.a.hashid, arb.b.hashid)];
    deleteObjFromList(this.arbiters, arb);
};
Space.prototype.eachBody = function(func)
{
    this.lock(); {
        var bodies = this.bodies;
        for(var i=0; i<bodies.length; i++){
            func(bodies[i]);
        }
        var components = this.sleepingComponents;
        for(var i=0; i<components.length; i++){
            var root = components[i];
            var body = root;
            while(body){
                var next = body.nodeNext;
                func(body);
                body = next;
            }
        }
    } this.unlock(true);
};
Space.prototype.eachShape = function(func)
{
    this.lock(); {
        this.activeShapes.each(func);
        this.staticShapes.each(func);
    } this.unlock(true);
};
Space.prototype.eachConstraint = function(func)
{
    this.lock(); {
        var constraints = this.constraints;
        for(var i=0; i<constraints.length; i++){
            func(constraints[i]);
        }
    } this.unlock(true);
};
Space.prototype.reindexStatic = function()
{
    assert(!this.locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete.");
    this.staticShapes.each(function(shape){
        var body = shape.body;
        shape.update(body.p, body.rot);
    });
    this.staticShapes.reindex();
};
Space.prototype.reindexShape = function(shape)
{
    assert(!this.locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete.");
    var body = shape.body;
    shape.update(body.p, body.rot);
    this.activeShapes.reindexObject(shape, shape.hashid);
    this.staticShapes.reindexObject(shape, shape.hashid);
};
Space.prototype.reindexShapesForBody = function(body)
{
    for(var shape = body.shapeList; shape; shape = shape.next){
        this.reindexShape(shape);
    }
};
Space.prototype.useSpatialHash = function(dim, count)
{
    throw new Error('Spatial Hash not implemented.');
    var staticShapes = new SpaceHash(dim, count, null);
    var activeShapes = new SpaceHash(dim, count, staticShapes);
    this.staticShapes.each(function(shape){
        staticShapes.insert(shape, shape.hashid);
    });
    this.activeShapes.each(function(shape){
        activeShapes.insert(shape, shape.hashid);
    });
    this.staticShapes = staticShapes;
    this.activeShapes = activeShapes;
};
Space.prototype.activateBody = function(body)
{
    assert(!body.isRogue(), "Internal error: Attempting to activate a rogue body.");
    if(this.locked){
        if(this.rousedBodies.indexOf(body) === -1) this.rousedBodies.push(body);
    } else {
        this.bodies.push(body);
        for(var i = 0; i < body.shapeList.length; i++){
            var shape = body.shapeList[i];
            this.staticShapes.remove(shape, shape.hashid);
            this.activeShapes.insert(shape, shape.hashid);
        }
        for(var arb = body.arbiterList; arb; arb = arb.next(body)){
            var bodyA = arb.body_a;
            if(body === bodyA || bodyA.isStatic()){
                var a = arb.a, b = arb.b;
                this.cachedArbiters[hashPair(a.hashid, b.hashid)] = arb;
                arb.stamp = this.stamp;
                arb.handler = this.lookupHandler(a.collision_type, b.collision_type);
                this.arbiters.push(arb);
            }
        }
        for(var constraint = body.constraintList; constraint; constraint = constraint.nodeNext){
            var bodyA = constraint.a;
            if(body === bodyA || bodyA.isStatic()) this.constraints.push(constraint);
        }
    }
};
Space.prototype.deactivateBody = function(body)
{
    assert(!body.isRogue(), "Internal error: Attempting to deactivate a rogue body.");
    deleteObjFromList(this.bodies, body);
    for(var i = 0; i < body.shapeList.length; i++){
        var shape = body.shapeList[i];
        this.activeShapes.remove(shape, shape.hashid);
        this.staticShapes.insert(shape, shape.hashid);
    }
    for(var arb = body.arbiterList; arb; arb = arb.next(body)){
        var bodyA = arb.body_a;
        if(body === bodyA || bodyA.isStatic()){
            this.uncacheArbiter(arb);
        }
    }
    for(var constraint = body.constraintList; constraint; constraint = constraint.nodeNext){
        var bodyA = constraint.a;
        if(body === bodyA || bodyA.isStatic()) deleteObjFromList(this.constraints, constraint);
    }
};
var componentRoot = function(body)
{
    return (body ? body.nodeRoot : null);
};
var componentActivate = function(root)
{
    if(!root || !root.isSleeping(root)) return;
    assert(!root.isRogue(), "Internal Error: componentActivate() called on a rogue body.");
    var space = root.space;
    var body = root;
    while(body){
        var next = body.nodeNext;
        body.nodeIdleTime = 0;
        body.nodeRoot = null;
        body.nodeNext = null;
        space.activateBody(body);
        body = next;
    }
    deleteObjFromList(space.sleepingComponents, root);
};
Body.prototype.activate = function()
{
    if(!this.isRogue()){
        this.nodeIdleTime = 0;
        componentActivate(componentRoot(this));
    }
};
Body.prototype.activateStatic = function(filter)
{
    assert(this.isStatic(), "Body.activateStatic() called on a non-static body.");
    for(var arb = this.arbiterList; arb; arb = arb.next(this)){
        if(!filter || filter == arb.a || filter == arb.b){
            (arb.body_a == this ? arb.body_b : arb.body_a).activate();
        }
    }
};
Body.prototype.pushArbiter = function(arb)
{
    assertSoft((arb.body_a === this ? arb.thread_a_next : arb.thread_b_next) === null,
        "Internal Error: Dangling contact graph pointers detected. (A)");
    assertSoft((arb.body_a === this ? arb.thread_a_prev : arb.thread_b_prev) === null,
        "Internal Error: Dangling contact graph pointers detected. (B)");
    var next = this.arbiterList;
    assertSoft(next === null || (next.body_a === this ? next.thread_a_prev : next.thread_b_prev) === null,
        "Internal Error: Dangling contact graph pointers detected. (C)");
    if(arb.body_a === this){
        arb.thread_a_next = next;
    } else {
        arb.thread_b_next = next;
    }
    if(next){
        if (next.body_a === this){
            next.thread_a_prev = arb;
        } else {
            next.thread_b_prev = arb;
        }
    }
    this.arbiterList = arb;
};
var componentAdd = function(root, body){
    body.nodeRoot = root;
    if(body !== root){
        body.nodeNext = root.nodeNext;
        root.nodeNext = body;
    }
};
var floodFillComponent = function(root, body)
{
    if(!body.isRogue()){
        var other_root = componentRoot(body);
        if(other_root == null){
            componentAdd(root, body);
            for(var arb = body.arbiterList; arb; arb = arb.next(body)){
                floodFillComponent(root, (body == arb.body_a ? arb.body_b : arb.body_a));
            }
            for(var constraint = body.constraintList; constraint; constraint = constraint.next(body)){
                floodFillComponent(root, (body == constraint.a ? constraint.b : constraint.a));
            }
        } else {
            assertSoft(other_root === root, "Internal Error: Inconsistency detected in the contact graph.");
        }
    }
};
var componentActive = function(root, threshold)
{
    for(var body = root; body; body = body.nodeNext){
        if(body.nodeIdleTime < threshold) return true;
    }
    return false;
};
Space.prototype.processComponents = function(dt)
{
    var sleep = (this.sleepTimeThreshold !== Infinity);
    var bodies = this.bodies;
    for(var i=0; i<bodies.length; i++){
        var body = bodies[i];
        assertSoft(body.nodeNext === null, "Internal Error: Dangling next pointer detected in contact graph.");
        assertSoft(body.nodeRoot === null, "Internal Error: Dangling root pointer detected in contact graph.");
    }
    if(sleep){
        var dv = this.idleSpeedThreshold;
        var dvsq = (dv ? dv*dv : vlengthsq(this.gravity)*dt*dt);
        for(var i=0; i<bodies.length; i++){
            var body = bodies[i];
            var keThreshold = (dvsq ? body.m*dvsq : 0);
            body.nodeIdleTime = (body.kineticEnergy() > keThreshold ? 0 : body.nodeIdleTime + dt);
        }
    }
    var arbiters = this.arbiters;
    for(var i=0, count=arbiters.length; i<count; i++){
        var arb = arbiters[i];
        var a = arb.body_a, b = arb.body_b;
        if(sleep){
            if((b.isRogue() && !b.isStatic()) || a.isSleeping()) a.activate();
            if((a.isRogue() && !a.isStatic()) || b.isSleeping()) b.activate();
        }
        a.pushArbiter(arb);
        b.pushArbiter(arb);
    }
    if(sleep){
        var constraints = this.constraints;
        for(var i=0; i<constraints.length; i++){
            var constraint = constraints[i];
            var a = constraint.a, b = constraint.b;
            if(b.isRogue() && !b.isStatic()) a.activate();
            if(a.isRogue() && !a.isStatic()) b.activate();
        }
        for(var i=0; i<bodies.length;){
            var body = bodies[i];
            if(componentRoot(body) === null){
                floodFillComponent(body, body);
                if(!componentActive(body, this.sleepTimeThreshold)){
                    this.sleepingComponents.push(body);
                    for(var other = body; other; other = other.nodeNext){
                        this.deactivateBody(other);
                    }
                    continue;
                }
            }
            i++;
            body.nodeRoot = null;
            body.nodeNext = null;
        }
    }
};
Body.prototype.sleep = function()
{
    this.sleepWithGroup(null);
};
Body.prototype.sleepWithGroup = function(group){
    assert(!this.isStatic() && !this.isRogue(), "Rogue and static bodies cannot be put to sleep.");
    var space = this.space;
    assert(space, "Cannot put a rogue body to sleep.");
    assert(!space.locked, "Bodies cannot be put to sleep during a query or a call to cpSpaceStep(). Put these calls into a post-step callback.");
    assert(group === null || group.isSleeping(), "Cannot use a non-sleeping body as a group identifier.");
    if(this.isSleeping()){
        assert(componentRoot(this) === componentRoot(group), "The body is already sleeping and it's group cannot be reassigned.");
        return;
    }
    for(var i = 0; i < this.shapeList.length; i++){
        this.shapeList[i].update(this.p, this.rot);
    }
    space.deactivateBody(this);
    if(group){
        var root = componentRoot(group);
        this.nodeRoot = root;
        this.nodeNext = root.nodeNext;
        this.nodeIdleTime = 0;
        root.nodeNext = this;
    } else {
        this.nodeRoot = this;
        this.nodeNext = null;
        this.nodeIdleTime = 0;
        space.sleepingComponents.push(this);
    }
    deleteObjFromList(space.bodies, this);
};
Space.prototype.activateShapesTouchingShape = function(shape){
    if(this.sleepTimeThreshold !== Infinity){
        this.shapeQuery(shape, function(shape, points) {
            shape.body.activate();
        });
    }
};
Space.prototype.pointQuery = function(point, layers, group, func)
{
    var helper = function(shape){
        if(
            !(shape.group && group === shape.group) && (layers & shape.layers) &&
            shape.pointQuery(point)
        ){
            func(shape);
        }
    };
    var bb = new BB(point.x, point.y, point.x, point.y);
    this.lock(); {
        this.activeShapes.query(bb, helper);
        this.staticShapes.query(bb, helper);
    } this.unlock(true);
};
Space.prototype.pointQueryFirst = function(point, layers, group)
{
    var outShape = null;
    this.pointQuery(point, layers, group, function(shape) {
        if(!shape.sensor) outShape = shape;
    });
    return outShape;
};
Space.prototype.nearestPointQuery = function(point, maxDistance, layers, group, func)
{
    var helper = function(shape){
        if(!(shape.group && group === shape.group) && (layers & shape.layers)){
            var info = shape.nearestPointQuery(point);
            if(info.d < maxDistance) func(shape, info.d, info.p);
        }
    };
    var bb = bbNewForCircle(point, maxDistance);
    this.lock(); {
        this.activeShapes.query(bb, helper);
        this.staticShapes.query(bb, helper);
    } this.unlock(true);
};
Space.prototype.nearestPointQueryNearest = function(point, maxDistance, layers, group)
{
    var out;
    var helper = function(shape){
        if(!(shape.group && group === shape.group) && (layers & shape.layers) && !shape.sensor){
            var info = shape.nearestPointQuery(point);
            if(info.d < maxDistance && (!out || info.d < out.d)) out = info;
        }
    };
    var bb = bbNewForCircle(point, maxDistance);
    this.activeShapes.query(bb, helper);
    this.staticShapes.query(bb, helper);
    return out;
};
cp.SHAPE_FILTER_ALL = {
        group:cp.NO_GROUP,
        categories:cp.ALL_CATEGORIES,
        mask:cp.ALL_CATEGORIES
};
Space.prototype.pointQueryNearest = function(point, maxDistance, filter)
{
    var out = this.nearestPointQueryNearest(point, maxDistance, filter.mask, filter.group);
    if (typeof out != 'undefined') {
        out.distance = out.d;
        out.point = out.p;
    }
    return out;
};
Space.prototype.segmentQuery = function(start, end, layers, group, func)
{
    var helper = function(shape){
        var info;
        if(
            !(shape.group && group === shape.group) && (layers & shape.layers) &&
            (info = shape.segmentQuery(start, end))
        ){
            func(shape, info.t, info.n);
        }
        return 1;
    };
    this.lock(); {
        this.staticShapes.segmentQuery(start, end, 1, helper);
        this.activeShapes.segmentQuery(start, end, 1, helper);
    } this.unlock(true);
};
Space.prototype.segmentQueryFirst = function(start, end, layers, group)
{
    var out = null;
    var helper = function(shape){
        var info;
        if(
            !(shape.group && group === shape.group) && (layers & shape.layers) &&
            !shape.sensor &&
            (info = shape.segmentQuery(start, end)) &&
            (out === null || info.t < out.t)
        ){
            out = info;
        }
        return out ? out.t : 1;
    };
    this.staticShapes.segmentQuery(start, end, 1, helper);
    this.activeShapes.segmentQuery(start, end, out ? out.t : 1, helper);
    if (out && out !== "null" && out !== "undefined") {
        out.normal = out.n;
        out.alpha = out.t;
        out.p = out.point = cp.v.lerp(start, end, out.t);
    }
    return out;
};
Space.prototype.bbQuery = function(bb, layers, group, func)
{
    var helper = function(shape){
        if(
            !(shape.group && group === shape.group) && (layers & shape.layers) &&
            bbIntersects2(bb, shape.bb_l, shape.bb_b, shape.bb_r, shape.bb_t)
        ){
            func(shape);
        }
    };
    this.lock(); {
        this.activeShapes.query(bb, helper);
        this.staticShapes.query(bb, helper);
    } this.unlock(true);
};
Space.prototype.shapeQuery = function(shape, func)
{
    var body = shape.body;
    if(body){
        shape.update(body.p, body.rot);
    }
    var bb = new BB(shape.bb_l, shape.bb_b, shape.bb_r, shape.bb_t);
    var anyCollision = false;
    var helper = function(b){
        var a = shape;
        if(
            (a.group && a.group === b.group) ||
            !(a.layers & b.layers) ||
            a === b
        ) return;
        var contacts;
        if(a.collisionCode <= b.collisionCode){
            contacts = collideShapes(a, b);
        } else {
            contacts = collideShapes(b, a);
            for(var i=0; i<contacts.length; i++) contacts[i].n = vneg(contacts[i].n);
        }
        if(contacts.length){
            anyCollision = !(a.sensor || b.sensor);
            if(func){
                var set = new Array(contacts.length);
                for(var i=0; i<contacts.length; i++){
                    set[i] = new ContactPoint(contacts[i].p, contacts[i].n, contacts[i].dist);
                }
                func(b, set);
            }
        }
    };
    this.lock(); {
        this.activeShapes.query(bb, helper);
        this.staticShapes.query(bb, helper);
    } this.unlock(true);
    return anyCollision;
};
Space.prototype.addPostStepCallback = function(func)
{
    assertSoft(this.locked,
        "Adding a post-step callback when the space is not locked is unnecessary. " +
        "Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query.");
    this.postStepCallbacks.push(func);
};
Space.prototype.runPostStepCallbacks = function()
{
    for(var i = 0; i < this.postStepCallbacks.length; i++){
        this.postStepCallbacks[i]();
    }
    this.postStepCallbacks = [];
};
Space.prototype.lock = function()
{
    this.locked++;
};
Space.prototype.unlock = function(runPostStep)
{
    this.locked--;
    assert(this.locked >= 0, "Internal Error: Space lock underflow.");
    if(this.locked === 0 && runPostStep){
        var waking = this.rousedBodies;
        for(var i=0; i<waking.length; i++){
            this.activateBody(waking[i]);
        }
        waking.length = 0;
        this.runPostStepCallbacks();
    }
};
Space.prototype.makeCollideShapes = function()
{
    var space_ = this;
    return function(a, b){
        var space = space_;
        if(
            !(a.bb_l <= b.bb_r && b.bb_l <= a.bb_r && a.bb_b <= b.bb_t && b.bb_b <= a.bb_t)
            || a.body === b.body
            || (a.group && a.group === b.group)
            || !(a.layers & b.layers)
        ) return;
        var handler = space.lookupHandler(a.collision_type, b.collision_type);
        var sensor = a.sensor || b.sensor;
        if(sensor && handler === defaultCollisionHandler) return;
        if(a.collisionCode > b.collisionCode){
            var temp = a;
            a = b;
            b = temp;
        }
        var contacts = collideShapes(a, b);
        if(contacts.length === 0) return;
        var arbHash = hashPair(a.hashid, b.hashid);
        var arb = space.cachedArbiters[arbHash];
        if (!arb){
            arb = space.cachedArbiters[arbHash] = new Arbiter(a, b);
        }
        arb.update(contacts, handler, a, b);
        if(arb.state == 'first coll' && !handler.begin(arb, space)){
            arb.ignore();
        }
        if(
            (arb.state !== 'ignore') &&
            handler.preSolve(arb, space) &&
            !sensor
        ){
            space.arbiters.push(arb);
        } else {
            arb.contacts = null;
            if(arb.state !== 'ignore') arb.state = 'normal';
        }
        arb.stamp = space.stamp;
    };
};
Space.prototype.arbiterSetFilter = function(arb)
{
    var ticks = this.stamp - arb.stamp;
    var a = arb.body_a, b = arb.body_b;
    if(
        (a.isStatic() || a.isSleeping()) &&
        (b.isStatic() || b.isSleeping())
    ){
        return true;
    }
    if(ticks >= 1 && arb.state != 'cached'){
        arb.callSeparate(this);
        arb.state = 'cached';
    }
    if(ticks >= this.collisionPersistence){
        arb.contacts = null;
        return false;
    }
    return true;
};
var updateFunc = function(shape)
{
    var body = shape.body;
    shape.update(body.p, body.rot);
};
Space.prototype.step = function(dt)
{
    if(dt === 0) return;
    assert(vzero.x === 0 && vzero.y === 0, "vzero is invalid");
    this.stamp++;
    var prev_dt = this.curr_dt;
    this.curr_dt = dt;
    var i;
    var j;
    var hash;
    var bodies = this.bodies;
    var constraints = this.constraints;
    var arbiters = this.arbiters;
    for(i=0; i<arbiters.length; i++){
        var arb = arbiters[i];
        arb.state = 'normal';
        if(!arb.body_a.isSleeping() && !arb.body_b.isSleeping()){
            arb.unthread();
        }
    }
    arbiters.length = 0;
    this.lock(); {
        for(i=0; i<bodies.length; i++){
            bodies[i].position_func(dt);
        }
        this.activeShapes.each(updateFunc);
        this.activeShapes.reindexQuery(this.collideShapes);
    } this.unlock(false);
    this.processComponents(dt);
    this.lock(); {
        for(hash in this.cachedArbiters) {
            if(!this.arbiterSetFilter(this.cachedArbiters[hash])) {
                delete this.cachedArbiters[hash];
            }
        }
        var slop = this.collisionSlop;
        var biasCoef = 1 - Math.pow(this.collisionBias, dt);
        for(i=0; i<arbiters.length; i++){
            arbiters[i].preStep(dt, slop, biasCoef);
        }
        for(i=0; i<constraints.length; i++){
            var constraint = constraints[i];
            constraint.preSolve(this);
            constraint.preStep(dt);
        }
        var damping = Math.pow(this.damping, dt);
        var gravity = this.gravity;
        for(i=0; i<bodies.length; i++){
            bodies[i].velocity_func(gravity, damping, dt);
        }
        var dt_coef = (prev_dt === 0 ? 0 : dt/prev_dt);
        for(i=0; i<arbiters.length; i++){
            arbiters[i].applyCachedImpulse(dt_coef);
        }
        for(i=0; i<constraints.length; i++){
            constraints[i].applyCachedImpulse(dt_coef);
        }
        for(i=0; i<this.iterations; i++){
            for(j=0; j<arbiters.length; j++){
                arbiters[j].applyImpulse();
            }
            for(j=0; j<constraints.length; j++){
                constraints[j].applyImpulse();
            }
        }
        for(i=0; i<constraints.length; i++){
            constraints[i].postSolve(this);
        }
        for(i=0; i<arbiters.length; i++){
            arbiters[i].handler.postSolve(arbiters[i], this);
        }
    } this.unlock(true);
};
var relative_velocity = function(a, b, r1, r2){
    var v1_sumx = a.vx + (-r1.y) * a.w;
    var v1_sumy = a.vy + ( r1.x) * a.w;
    var v2_sumx = b.vx + (-r2.y) * b.w;
    var v2_sumy = b.vy + ( r2.x) * b.w;
    return new Vect(v2_sumx - v1_sumx, v2_sumy - v1_sumy);
};
var normal_relative_velocity = function(a, b, r1, r2, n){
    var v1_sumx = a.vx + (-r1.y) * a.w;
    var v1_sumy = a.vy + ( r1.x) * a.w;
    var v2_sumx = b.vx + (-r2.y) * b.w;
    var v2_sumy = b.vy + ( r2.x) * b.w;
    return vdot2(v2_sumx - v1_sumx, v2_sumy - v1_sumy, n.x, n.y);
};
var apply_impulse = function(body, jx, jy, r){
    body.vx += jx * body.m_inv;
    body.vy += jy * body.m_inv;
    body.w += body.i_inv*(r.x*jy - r.y*jx);
};
var apply_impulses = function(a, b, r1, r2, jx, jy)
{
    apply_impulse(a, -jx, -jy, r1);
    apply_impulse(b, jx, jy, r2);
};
var apply_bias_impulse = function(body, jx, jy, r)
{
    body.v_biasx += jx * body.m_inv;
    body.v_biasy += jy * body.m_inv;
    body.w_bias += body.i_inv*vcross2(r.x, r.y, jx, jy);
};
var k_scalar_body = function(body, r, n)
{
    var rcn = vcross(r, n);
    return body.m_inv + body.i_inv*rcn*rcn;
};
var k_scalar = function(a, b, r1, r2, n)
{
    var value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n);
    assertSoft(value !== 0, "Unsolvable collision or constraint.");
    return value;
};
var k_tensor = function(a, b, r1, r2, k1, k2)
{
    var k11, k12, k21, k22;
    var m_sum = a.m_inv + b.m_inv;
    k11 = m_sum; k12 = 0;
    k21 = 0;     k22 = m_sum;
    var a_i_inv = a.i_inv;
    var r1xsq =  r1.x * r1.x * a_i_inv;
    var r1ysq =  r1.y * r1.y * a_i_inv;
    var r1nxy = -r1.x * r1.y * a_i_inv;
    k11 += r1ysq; k12 += r1nxy;
    k21 += r1nxy; k22 += r1xsq;
    var b_i_inv = b.i_inv;
    var r2xsq =  r2.x * r2.x * b_i_inv;
    var r2ysq =  r2.y * r2.y * b_i_inv;
    var r2nxy = -r2.x * r2.y * b_i_inv;
    k11 += r2ysq; k12 += r2nxy;
    k21 += r2nxy; k22 += r2xsq;
    var determinant = k11*k22 - k12*k21;
    assertSoft(determinant !== 0, "Unsolvable constraint.");
    var det_inv = 1/determinant;
    k1.x =  k22*det_inv; k1.y = -k12*det_inv;
    k2.x = -k21*det_inv; k2.y =  k11*det_inv;
};
var mult_k = function(vr, k1, k2)
{
    return new Vect(vdot(vr, k1), vdot(vr, k2));
};
var bias_coef = function(errorBias, dt)
{
    return 1 - Math.pow(errorBias, dt);
};
var Constraint = cp.Constraint = function(a, b)
{
    this.a = a;
    this.b = b;
    this.space = null;
    this.next_a = null;
    this.next_b = null;
    this.maxForce = Infinity;
    this.errorBias = Math.pow(1 - 0.1, 60);
    this.maxBias = Infinity;
};
Constraint.prototype.activateBodies = function()
{
    if(this.a) this.a.activate();
    if(this.b) this.b.activate();
};
Constraint.prototype.preStep = function(dt) {};
Constraint.prototype.applyCachedImpulse = function(dt_coef) {};
Constraint.prototype.applyImpulse = function() {};
Constraint.prototype.getImpulse = function() { return 0; };
Constraint.prototype.preSolve = function(space) {};
Constraint.prototype.postSolve = function(space) {};
Constraint.prototype.next = function(body)
{
    return (this.a === body ? this.next_a : this.next_b);
};
var PinJoint = cp.PinJoint = function(a, b, anchr1, anchr2)
{
    Constraint.call(this, a, b);
    this.anchr1 = anchr1;
    this.anchr2 = anchr2;
    var p1 = (a ? vadd(a.p, vrotate(anchr1, a.rot)) : anchr1);
    var p2 = (b ? vadd(b.p, vrotate(anchr2, b.rot)) : anchr2);
    this.dist = vlength(vsub(p2, p1));
    assertSoft(this.dist > 0, "You created a 0 length pin joint. A pivot joint will be much more stable.");
    this.r1 = this.r2 = null;
    this.n = null;
    this.nMass = 0;
    this.jnAcc = this.jnMax = 0;
    this.bias = 0;
};
PinJoint.prototype = Object.create(Constraint.prototype);
PinJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    this.r1 = vrotate(this.anchr1, a.rot);
    this.r2 = vrotate(this.anchr2, b.rot);
    var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
    var dist = vlength(delta);
    this.n = vmult(delta, 1/(dist ? dist : Infinity));
    this.nMass = 1/k_scalar(a, b, this.r1, this.r2, this.n);
    var maxBias = this.maxBias;
    this.bias = clamp(-bias_coef(this.errorBias, dt)*(dist - this.dist)/dt, -maxBias, maxBias);
    this.jnMax = this.maxForce * dt;
};
PinJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    var j = vmult(this.n, this.jnAcc*dt_coef);
    apply_impulses(this.a, this.b, this.r1, this.r2, j.x, j.y);
};
PinJoint.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var n = this.n;
    var vrn = normal_relative_velocity(a, b, this.r1, this.r2, n);
    var jn = (this.bias - vrn)*this.nMass;
    var jnOld = this.jnAcc;
    this.jnAcc = clamp(jnOld + jn, -this.jnMax, this.jnMax);
    jn = this.jnAcc - jnOld;
    apply_impulses(a, b, this.r1, this.r2, n.x*jn, n.y*jn);
};
PinJoint.prototype.getImpulse = function()
{
    return Math.abs(this.jnAcc);
};
var SlideJoint = cp.SlideJoint = function(a, b, anchr1, anchr2, min, max)
{
    Constraint.call(this, a, b);
    this.anchr1 = anchr1;
    this.anchr2 = anchr2;
    this.min = min;
    this.max = max;
    this.r1 = this.r2 = this.n = null;
    this.nMass = 0;
    this.jnAcc = this.jnMax = 0;
    this.bias = 0;
};
SlideJoint.prototype = Object.create(Constraint.prototype);
SlideJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    this.r1 = vrotate(this.anchr1, a.rot);
    this.r2 = vrotate(this.anchr2, b.rot);
    var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
    var dist = vlength(delta);
    var pdist = 0;
    if(dist > this.max) {
        pdist = dist - this.max;
        this.n = vnormalize_safe(delta);
    } else if(dist < this.min) {
        pdist = this.min - dist;
        this.n = vneg(vnormalize_safe(delta));
    } else {
        this.n = vzero;
        this.jnAcc = 0;
    }
    this.nMass = 1/k_scalar(a, b, this.r1, this.r2, this.n);
    var maxBias = this.maxBias;
    this.bias = clamp(-bias_coef(this.errorBias, dt)*pdist/dt, -maxBias, maxBias);
    this.jnMax = this.maxForce * dt;
};
SlideJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    var jn = this.jnAcc * dt_coef;
    apply_impulses(this.a, this.b, this.r1, this.r2, this.n.x * jn, this.n.y * jn);
};
SlideJoint.prototype.applyImpulse = function()
{
    if(this.n.x === 0 && this.n.y === 0) return;
    var a = this.a;
    var b = this.b;
    var n = this.n;
    var r1 = this.r1;
    var r2 = this.r2;
    var vr = relative_velocity(a, b, r1, r2);
    var vrn = vdot(vr, n);
    var jn = (this.bias - vrn)*this.nMass;
    var jnOld = this.jnAcc;
    this.jnAcc = clamp(jnOld + jn, -this.jnMax, 0);
    jn = this.jnAcc - jnOld;
    apply_impulses(a, b, this.r1, this.r2, n.x * jn, n.y * jn);
};
SlideJoint.prototype.getImpulse = function()
{
    return Math.abs(this.jnAcc);
};
var PivotJoint = cp.PivotJoint = function(a, b, anchr1, anchr2)
{
    Constraint.call(this, a, b);
    if(typeof anchr2 === 'undefined') {
        var pivot = anchr1;
        anchr1 = (a ? a.world2Local(pivot) : pivot);
        anchr2 = (b ? b.world2Local(pivot) : pivot);
    }
    this.anchr1 = anchr1;
    this.anchr2 = anchr2;
    this.r1 = this.r2 = vzero;
    this.k1 = new Vect(0,0); this.k2 = new Vect(0,0);
    this.jAcc = vzero;
    this.jMaxLen = 0;
    this.bias = vzero;
};
PivotJoint.prototype = Object.create(Constraint.prototype);
PivotJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    this.r1 = vrotate(this.anchr1, a.rot);
    this.r2 = vrotate(this.anchr2, b.rot);
    k_tensor(a, b, this.r1, this.r2, this.k1, this.k2);
    this.jMaxLen = this.maxForce * dt;
    var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
    this.bias = vclamp(vmult(delta, -bias_coef(this.errorBias, dt)/dt), this.maxBias);
};
PivotJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    apply_impulses(this.a, this.b, this.r1, this.r2, this.jAcc.x * dt_coef, this.jAcc.y * dt_coef);
};
PivotJoint.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var r1 = this.r1;
    var r2 = this.r2;
    var vr = relative_velocity(a, b, r1, r2);
    var j = mult_k(vsub(this.bias, vr), this.k1, this.k2);
    var jOld = this.jAcc;
    this.jAcc = vclamp(vadd(this.jAcc, j), this.jMaxLen);
    apply_impulses(a, b, this.r1, this.r2, this.jAcc.x - jOld.x, this.jAcc.y - jOld.y);
};
PivotJoint.prototype.getImpulse = function()
{
    return vlength(this.jAcc);
};
var GrooveJoint = cp.GrooveJoint = function(a, b, groove_a, groove_b, anchr2)
{
    Constraint.call(this, a, b);
    this.grv_a = groove_a;
    this.grv_b = groove_b;
    this.grv_n = vperp(vnormalize(vsub(groove_b, groove_a)));
    this.anchr2 = anchr2;
    this.grv_tn = null;
    this.clamp = 0;
    this.r1 = this.r2 = null;
    this.k1 = new Vect(0,0);
    this.k2 = new Vect(0,0);
    this.jAcc = vzero;
    this.jMaxLen = 0;
    this.bias = null;
};
GrooveJoint.prototype = Object.create(Constraint.prototype);
GrooveJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    var ta = a.local2World(this.grv_a);
    var tb = a.local2World(this.grv_b);
    var n = vrotate(this.grv_n, a.rot);
    var d = vdot(ta, n);
    this.grv_tn = n;
    this.r2 = vrotate(this.anchr2, b.rot);
    var td = vcross(vadd(b.p, this.r2), n);
    if(td <= vcross(ta, n)){
        this.clamp = 1;
        this.r1 = vsub(ta, a.p);
    } else if(td >= vcross(tb, n)){
        this.clamp = -1;
        this.r1 = vsub(tb, a.p);
    } else {
        this.clamp = 0;
        this.r1 = vsub(vadd(vmult(vperp(n), -td), vmult(n, d)), a.p);
    }
    k_tensor(a, b, this.r1, this.r2, this.k1, this.k2);
    this.jMaxLen = this.maxForce * dt;
    var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
    this.bias = vclamp(vmult(delta, -bias_coef(this.errorBias, dt)/dt), this.maxBias);
};
GrooveJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    apply_impulses(this.a, this.b, this.r1, this.r2, this.jAcc.x * dt_coef, this.jAcc.y * dt_coef);
};
GrooveJoint.prototype.grooveConstrain = function(j){
    var n = this.grv_tn;
    var jClamp = (this.clamp*vcross(j, n) > 0) ? j : vproject(j, n);
    return vclamp(jClamp, this.jMaxLen);
};
GrooveJoint.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var r1 = this.r1;
    var r2 = this.r2;
    var vr = relative_velocity(a, b, r1, r2);
    var j = mult_k(vsub(this.bias, vr), this.k1, this.k2);
    var jOld = this.jAcc;
    this.jAcc = this.grooveConstrain(vadd(jOld, j));
    apply_impulses(a, b, this.r1, this.r2, this.jAcc.x - jOld.x, this.jAcc.y - jOld.y);
};
GrooveJoint.prototype.getImpulse = function()
{
    return vlength(this.jAcc);
};
GrooveJoint.prototype.setGrooveA = function(value)
{
    this.grv_a = value;
    this.grv_n = vperp(vnormalize(vsub(this.grv_b, value)));
    this.activateBodies();
};
GrooveJoint.prototype.setGrooveB = function(value)
{
    this.grv_b = value;
    this.grv_n = vperp(vnormalize(vsub(value, this.grv_a)));
    this.activateBodies();
};
var defaultSpringForce = function(spring, dist){
    return (spring.restLength - dist)*spring.stiffness;
};
var DampedSpring = cp.DampedSpring = function(a, b, anchr1, anchr2, restLength, stiffness, damping)
{
    Constraint.call(this, a, b);
    this.anchr1 = anchr1;
    this.anchr2 = anchr2;
    this.restLength = restLength;
    this.stiffness = stiffness;
    this.damping = damping;
    this.springForceFunc = defaultSpringForce;
    this.target_vrn = this.v_coef = 0;
    this.r1 = this.r2 = null;
    this.nMass = 0;
    this.n = null;
};
DampedSpring.prototype = Object.create(Constraint.prototype);
DampedSpring.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    this.r1 = vrotate(this.anchr1, a.rot);
    this.r2 = vrotate(this.anchr2, b.rot);
    var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
    var dist = vlength(delta);
    this.n = vmult(delta, 1/(dist ? dist : Infinity));
    var k = k_scalar(a, b, this.r1, this.r2, this.n);
    assertSoft(k !== 0, "Unsolvable this.");
    this.nMass = 1/k;
    this.target_vrn = 0;
    this.v_coef = 1 - Math.exp(-this.damping*dt*k);
    var f_spring = this.springForceFunc(this, dist);
    apply_impulses(a, b, this.r1, this.r2, this.n.x * f_spring * dt, this.n.y * f_spring * dt);
};
DampedSpring.prototype.applyCachedImpulse = function(dt_coef){};
DampedSpring.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var n = this.n;
    var r1 = this.r1;
    var r2 = this.r2;
    var vrn = normal_relative_velocity(a, b, r1, r2, n);
    var v_damp = (this.target_vrn - vrn)*this.v_coef;
    this.target_vrn = vrn + v_damp;
    v_damp *= this.nMass;
    apply_impulses(a, b, this.r1, this.r2, this.n.x * v_damp, this.n.y * v_damp);
};
DampedSpring.prototype.getImpulse = function()
{
    return 0;
};
var defaultSpringTorque = function(spring, relativeAngle){
    return (relativeAngle - spring.restAngle)*spring.stiffness;
}
var DampedRotarySpring = cp.DampedRotarySpring = function(a, b, restAngle, stiffness, damping)
{
    Constraint.call(this, a, b);
    this.restAngle = restAngle;
    this.stiffness = stiffness;
    this.damping = damping;
    this.springTorqueFunc = defaultSpringTorque;
    this.target_wrn = 0;
    this.w_coef = 0;
    this.iSum = 0;
};
DampedRotarySpring.prototype = Object.create(Constraint.prototype);
DampedRotarySpring.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    var moment = a.i_inv + b.i_inv;
    assertSoft(moment !== 0, "Unsolvable spring.");
    this.iSum = 1/moment;
    this.w_coef = 1 - Math.exp(-this.damping*dt*moment);
    this.target_wrn = 0;
    var j_spring = this.springTorqueFunc(this, a.a - b.a)*dt;
    a.w -= j_spring*a.i_inv;
    b.w += j_spring*b.i_inv;
};
DampedRotarySpring.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var wrn = a.w - b.w;//normal_relative_velocity(a, b, r1, r2, n) - this.target_vrn;
    var w_damp = (this.target_wrn - wrn)*this.w_coef;
    this.target_wrn = wrn + w_damp;
    var j_damp = w_damp*this.iSum;
    a.w += j_damp*a.i_inv;
    b.w -= j_damp*b.i_inv;
};
var RotaryLimitJoint = cp.RotaryLimitJoint = function(a, b, min, max)
{
    Constraint.call(this, a, b);
    this.min = min;
    this.max = max;
    this.jAcc = 0;
    this.iSum = this.bias = this.jMax = 0;
};
RotaryLimitJoint.prototype = Object.create(Constraint.prototype);
RotaryLimitJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    var dist = b.a - a.a;
    var pdist = 0;
    if(dist > this.max) {
        pdist = this.max - dist;
    } else if(dist < this.min) {
        pdist = this.min - dist;
    }
    this.iSum = 1/(1/a.i + 1/b.i);
    var maxBias = this.maxBias;
    this.bias = clamp(-bias_coef(this.errorBias, dt)*pdist/dt, -maxBias, maxBias);
    this.jMax = this.maxForce * dt;
    if(!this.bias) this.jAcc = 0;
};
RotaryLimitJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    var a = this.a;
    var b = this.b;
    var j = this.jAcc*dt_coef;
    a.w -= j*a.i_inv;
    b.w += j*b.i_inv;
};
RotaryLimitJoint.prototype.applyImpulse = function()
{
    if(!this.bias) return;
    var a = this.a;
    var b = this.b;
    var wr = b.w - a.w;
    var j = -(this.bias + wr)*this.iSum;
    var jOld = this.jAcc;
    if(this.bias < 0){
        this.jAcc = clamp(jOld + j, 0, this.jMax);
    } else {
        this.jAcc = clamp(jOld + j, -this.jMax, 0);
    }
    j = this.jAcc - jOld;
    a.w -= j*a.i_inv;
    b.w += j*b.i_inv;
};
RotaryLimitJoint.prototype.getImpulse = function()
{
    return Math.abs(joint.jAcc);
};
var RatchetJoint = cp.RatchetJoint = function(a, b, phase, ratchet)
{
    Constraint.call(this, a, b);
    this.angle = 0;
    this.phase = phase;
    this.ratchet = ratchet;
    this.angle = (b ? b.a : 0) - (a ? a.a : 0);
    this.iSum = this.bias = this.jAcc = this.jMax = 0;
};
RatchetJoint.prototype = Object.create(Constraint.prototype);
RatchetJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    var angle = this.angle;
    var phase = this.phase;
    var ratchet = this.ratchet;
    var delta = b.a - a.a;
    var diff = angle - delta;
    var pdist = 0;
    if(diff*ratchet > 0){
        pdist = diff;
    } else {
        this.angle = Math.floor((delta - phase)/ratchet)*ratchet + phase;
    }
    this.iSum = 1/(a.i_inv + b.i_inv);
    var maxBias = this.maxBias;
    this.bias = clamp(-bias_coef(this.errorBias, dt)*pdist/dt, -maxBias, maxBias);
    this.jMax = this.maxForce * dt;
    if(!this.bias) this.jAcc = 0;
};
RatchetJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    var a = this.a;
    var b = this.b;
    var j = this.jAcc*dt_coef;
    a.w -= j*a.i_inv;
    b.w += j*b.i_inv;
};
RatchetJoint.prototype.applyImpulse = function()
{
    if(!this.bias) return;
    var a = this.a;
    var b = this.b;
    var wr = b.w - a.w;
    var ratchet = this.ratchet;
    var j = -(this.bias + wr)*this.iSum;
    var jOld = this.jAcc;
    this.jAcc = clamp((jOld + j)*ratchet, 0, this.jMax*Math.abs(ratchet))/ratchet;
    j = this.jAcc - jOld;
    a.w -= j*a.i_inv;
    b.w += j*b.i_inv;
};
RatchetJoint.prototype.getImpulse = function(joint)
{
    return Math.abs(joint.jAcc);
};
var GearJoint = cp.GearJoint = function(a, b, phase, ratio)
{
    Constraint.call(this, a, b);
    this.phase = phase;
    this.ratio = ratio;
    this.ratio_inv = 1/ratio;
    this.jAcc = 0;
    this.iSum = this.bias = this.jMax = 0;
};
GearJoint.prototype = Object.create(Constraint.prototype);
GearJoint.prototype.preStep = function(dt)
{
    var a = this.a;
    var b = this.b;
    this.iSum = 1/(a.i_inv*this.ratio_inv + this.ratio*b.i_inv);
    var maxBias = this.maxBias;
    this.bias = clamp(-bias_coef(this.errorBias, dt)*(b.a*this.ratio - a.a - this.phase)/dt, -maxBias, maxBias);
    this.jMax = this.maxForce * dt;
};
GearJoint.prototype.applyCachedImpulse = function(dt_coef)
{
    var a = this.a;
    var b = this.b;
    var j = this.jAcc*dt_coef;
    a.w -= j*a.i_inv*this.ratio_inv;
    b.w += j*b.i_inv;
};
GearJoint.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var wr = b.w*this.ratio - a.w;
    var j = (this.bias - wr)*this.iSum;
    var jOld = this.jAcc;
    this.jAcc = clamp(jOld + j, -this.jMax, this.jMax);
    j = this.jAcc - jOld;
    a.w -= j*a.i_inv*this.ratio_inv;
    b.w += j*b.i_inv;
};
GearJoint.prototype.getImpulse = function()
{
    return Math.abs(this.jAcc);
};
GearJoint.prototype.setRatio = function(value)
{
    this.ratio = value;
    this.ratio_inv = 1/value;
    this.activateBodies();
};
var SimpleMotor = cp.SimpleMotor = function(a, b, rate)
{
    Constraint.call(this, a, b);
    this.rate = rate;
    this.jAcc = 0;
    this.iSum = this.jMax = 0;
};
SimpleMotor.prototype = Object.create(Constraint.prototype);
SimpleMotor.prototype.preStep = function(dt)
{
    this.iSum = 1/(this.a.i_inv + this.b.i_inv);
    this.jMax = this.maxForce * dt;
};
SimpleMotor.prototype.applyCachedImpulse = function(dt_coef)
{
    var a = this.a;
    var b = this.b;
    var j = this.jAcc*dt_coef;
    a.w -= j*a.i_inv;
    b.w += j*b.i_inv;
};
SimpleMotor.prototype.applyImpulse = function()
{
    var a = this.a;
    var b = this.b;
    var wr = b.w - a.w + this.rate;
    var j = -wr*this.iSum;
    var jOld = this.jAcc;
    this.jAcc = clamp(jOld + j, -this.jMax, this.jMax);
    j = this.jAcc - jOld;
    a.w -= j*a.i_inv;
    b.w += j*b.i_inv;
};
SimpleMotor.prototype.getImpulse = function()
{
    return Math.abs(this.jAcc);
};
})();
var sp = sp || {};
sp.VERTEX_INDEX = {
    X1: 0,
    Y1: 1,
    X2: 2,
    Y2: 3,
    X3: 4,
    Y3: 5,
    X4: 6,
    Y4: 7
};
sp.ATTACHMENT_TYPE = {
    REGION: 0,
    BOUNDING_BOX: 1,
    MESH: 2,
    SKINNED_MESH:3
};
sp.Skeleton = cc.Node.extend({
    _skeleton: null,
    _rootBone: null,
    _timeScale: 1,
    _debugSlots: false,
    _debugBones: false,
    _premultipliedAlpha: false,
    _ownsSkeletonData: null,
    _atlas: null,
    _blendFunc: null,
    ctor:function(skeletonDataFile, atlasFile, scale){
        cc.Node.prototype.ctor.call(this);
        if(arguments.length === 0)
            this.init();
        else
            this.initWithArgs(skeletonDataFile, atlasFile, scale);
    },
    _createRenderCmd:function () {
        if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
            return new sp.Skeleton.CanvasRenderCmd(this);
        else
            return new sp.Skeleton.WebGLRenderCmd(this);
    },
    init: function () {
        cc.Node.prototype.init.call(this);
        this._premultipliedAlpha = (cc._renderType === cc.game.RENDER_TYPE_WEBGL && cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA);
        this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
        this.scheduleUpdate();
    },
    setDebugSolots:function(enable){
        this._debugSlots = enable;
    },
    setDebugBones:function(enable){
        this._debugBones = enable;
    },
    setDebugSlotsEnabled: function(enabled) {
        this._debugSlots = enabled;
    },
    getDebugSlotsEnabled: function() {
        return this._debugSlots;
    },
    setDebugBonesEnabled: function(enabled) {
        this._debugBones = enabled;
    },
    getDebugBonesEnabled: function() {
        return this._debugBones;
    },
    setTimeScale:function(scale){
        this._timeScale = scale;
    },
    getTimeScale: function(){
        return this._timeScale;
    },
    initWithArgs: function (skeletonDataFile, atlasFile, scale) {
        var argSkeletonFile = skeletonDataFile, argAtlasFile = atlasFile,
            skeletonData, atlas, ownsSkeletonData;
        if (cc.isString(argSkeletonFile)) {
            if (cc.isString(argAtlasFile)) {
                var data = cc.loader.getRes(argAtlasFile);
                sp._atlasLoader.setAtlasFile(argAtlasFile);
                atlas = new spine.Atlas(data, sp._atlasLoader);
            } else {
                atlas = atlasFile;
            }
            scale = scale || 1 / cc.director.getContentScaleFactor();
            var attachmentLoader = new spine.AtlasAttachmentLoader(atlas);
            var skeletonJsonReader = new spine.SkeletonJson(attachmentLoader);
            skeletonJsonReader.scale = scale;
            var skeletonJson = cc.loader.getRes(argSkeletonFile);
            skeletonData = skeletonJsonReader.readSkeletonData(skeletonJson);
            atlas.dispose(skeletonJsonReader);
            ownsSkeletonData = true;
        } else {
            skeletonData = skeletonDataFile;
            ownsSkeletonData = atlasFile;
        }
        this.setSkeletonData(skeletonData, ownsSkeletonData);
        this.init();
    },
    getBoundingBox: function () {
        var minX = cc.FLT_MAX, minY = cc.FLT_MAX, maxX = cc.FLT_MIN, maxY = cc.FLT_MIN;
        var scaleX = this.getScaleX(), scaleY = this.getScaleY(), vertices = [],
            slots = this._skeleton.slots, VERTEX = sp.VERTEX_INDEX;
        for (var i = 0, slotCount = slots.length; i < slotCount; ++i) {
            var slot = slots[i];
            if (!slot.attachment || slot.attachment.type != sp.ATTACHMENT_TYPE.REGION)
                continue;
            var attachment = slot.attachment;
            this._computeRegionAttachmentWorldVertices(attachment, slot.bone.skeleton.x, slot.bone.skeleton.y, slot.bone, vertices);
            minX = Math.min(minX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX);
            minY = Math.min(minY, vertices[VERTEX.Y1] * scaleY, vertices[VERTEX.Y4] * scaleY, vertices[VERTEX.Y2] * scaleY, vertices[VERTEX.Y3] * scaleY);
            maxX = Math.max(maxX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX);
            maxY = Math.max(maxY, vertices[VERTEX.Y1] * scaleY, vertices[VERTEX.Y4] * scaleY, vertices[VERTEX.Y2] * scaleY, vertices[VERTEX.Y3] * scaleY);
        }
        var position = this.getPosition();
        return cc.rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
    },
    _computeRegionAttachmentWorldVertices : function(self, x, y, bone, vertices){
        var offset = self.offset, vertexIndex = sp.VERTEX_INDEX;
        x += bone.worldX;
        y += bone.worldY;
        vertices[vertexIndex.X1] = offset[vertexIndex.X1] * bone.m00 + offset[vertexIndex.Y1] * bone.m01 + x;
        vertices[vertexIndex.Y1] = offset[vertexIndex.X1] * bone.m10 + offset[vertexIndex.Y1] * bone.m11 + y;
        vertices[vertexIndex.X2] = offset[vertexIndex.X2] * bone.m00 + offset[vertexIndex.Y2] * bone.m01 + x;
        vertices[vertexIndex.Y2] = offset[vertexIndex.X2] * bone.m10 + offset[vertexIndex.Y2] * bone.m11 + y;
        vertices[vertexIndex.X3] = offset[vertexIndex.X3] * bone.m00 + offset[vertexIndex.Y3] * bone.m01 + x;
        vertices[vertexIndex.Y3] = offset[vertexIndex.X3] * bone.m10 + offset[vertexIndex.Y3] * bone.m11 + y;
        vertices[vertexIndex.X4] = offset[vertexIndex.X4] * bone.m00 + offset[vertexIndex.Y4] * bone.m01 + x;
        vertices[vertexIndex.Y4] = offset[vertexIndex.X4] * bone.m10 + offset[vertexIndex.Y4] * bone.m11 + y;
    },
    updateWorldTransform: function () {
        this._skeleton.updateWorldTransform();
    },
    setToSetupPose: function () {
        this._skeleton.setToSetupPose();
    },
    setBonesToSetupPose: function () {
        this._skeleton.setBonesToSetupPose();
    },
    setSlotsToSetupPose: function () {
        this._skeleton.setSlotsToSetupPose();
    },
    findBone: function (boneName) {
        return this._skeleton.findBone(boneName);
    },
    findSlot: function (slotName) {
        return this._skeleton.findSlot(slotName);
    },
    setSkin: function (skinName) {
        return this._skeleton.setSkinByName(skinName);
    },
    getAttachment: function (slotName, attachmentName) {
        return this._skeleton.getAttachmentBySlotName(slotName, attachmentName);
    },
    setAttachment: function (slotName, attachmentName) {
        this._skeleton.setAttachment(slotName, attachmentName);
    },
    setPremultipliedAlpha: function (premultiplied) {
        this._premultipliedAlpha = premultiplied;
    },
    isPremultipliedAlpha: function () {
        return this._premultipliedAlpha;
    },
    setSkeletonData: function (skeletonData, ownsSkeletonData) {
        if(skeletonData.width != null && skeletonData.height != null)
            this.setContentSize(skeletonData.width / cc.director.getContentScaleFactor(), skeletonData.height / cc.director.getContentScaleFactor());
        this._skeleton = new spine.Skeleton(skeletonData);
        this._skeleton.updateWorldTransform();
        this._rootBone = this._skeleton.getRootBone();
        this._ownsSkeletonData = ownsSkeletonData;
        this._renderCmd._createChildFormSkeletonData();
    },
    getTextureAtlas: function (regionAttachment) {
        return regionAttachment.rendererObject.page.rendererObject;
    },
    getBlendFunc: function () {
        return this._blendFunc;
    },
    setBlendFunc: function (src, dst) {
        var locBlendFunc = this._blendFunc;
        if (dst === undefined) {
            locBlendFunc.src = src.src;
            locBlendFunc.dst = src.dst;
        } else {
            locBlendFunc.src = src;
            locBlendFunc.dst = dst;
        }
    },
    update: function (dt) {
        this._skeleton.update(dt);
    }
});
sp.Skeleton.create = function (skeletonDataFile, atlasFile, scale) {
    return new sp.Skeleton(skeletonDataFile, atlasFile, scale);
};
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.length = this.x = this.y = this.rotation = 0;
    this.scaleX = this.scaleY = 1;
    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.BlendMode = {
    normal: 0,
    additive: 1,
    multiply: 2,
    screen: 3
};
spine.SlotData = function (name, boneData) {
    this.r = this.g = this.b = this.a = 1;
    this.blendMode = spine.BlendMode.normal;
    this.name = name;
    this.boneData = boneData;
};
spine.SlotData.prototype = {
    r: 1, g: 1, b: 1, a: 1,
    attachmentName: null,
    blendMode: spine.BlendMode.normal
};
spine.IkConstraintData = function (name) {
    this.bendDirection = this.mix = 1;
    this.name = name;
    this.bones = [];
};
spine.IkConstraintData.prototype = {
    target: null,
    bendDirection: 1,
    mix: 1
};
spine.Bone = function (boneData, skeleton, parent) {
    this.x = this.y = this.rotation = this.rotationIK = 0;
    this.scaleX = this.scaleY = 1;
    this.flipX = this.flipY = false;
    this.m00 = this.m01 = this.worldX = 0;
    this.m10 = this.m11= this.worldY = 0;
    this.worldRotation = 0;
    this.worldScaleX = this.worldScaleY = 1;
    this.worldFlipX = this.worldFlipY = false;
    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,
    m10: 0, m11: 0, worldY: 0,
    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.r = this.g = this.b = this.a = 1;
    this._attachmentTime = 0;
    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;
        }
    }
};
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;
};
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;
    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 = [];
};
spine.Curves.prototype = {
    setLinear: function (frameIndex) {
        this.curves[frameIndex * 19] = 0;
    },
    setStepped: function (frameIndex) {
        this.curves[frameIndex * 19] = 1;
    },
    setCurve: function (frameIndex, cx1, cy1, cx2, cy2) {
        var subdiv1 = 1 / 10, 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;
        var curves = this.curves;
        curves[i++] = 2;
        var x = dfx, y = dfy;
        for (var n = i + 19 - 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;
        var type = curves[i];
        if (type === 0) return percent;
        if (type == 1) return 0;
        i++;
        var x = 0;
        for (var start = i, n = i + 19 - 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);
    }
};
spine.RotateTimeline = function (frameCount) {
    this.boneIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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;
        var bone = skeleton.bones[this.boneIndex];
        if (time >= frames[frames.length - 2]) {
            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;
        }
        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] - frameTime);
        percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent);
        var amount = frames[frameIndex + 1] - 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.boneIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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;
        var bone = skeleton.bones[this.boneIndex];
        if (time >= frames[frames.length - 3]) {
            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;
        }
        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] - frameTime);
        percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
        bone.x += (bone.data.x + prevFrameX + (frames[frameIndex + 1] - prevFrameX) * percent - bone.x) * alpha;
        bone.y += (bone.data.y + prevFrameY + (frames[frameIndex + 2] - prevFrameY) * percent - bone.y) * alpha;
    }
};
spine.ScaleTimeline = function (frameCount) {
    this.boneIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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;
        var bone = skeleton.bones[this.boneIndex];
        if (time >= frames[frames.length - 3]) {
            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;
        }
        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] - frameTime);
        percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
        bone.scaleX += (bone.data.scaleX * (prevFrameX + (frames[frameIndex + 1] - prevFrameX) * percent) - bone.scaleX) * alpha;
        bone.scaleY += (bone.data.scaleY * (prevFrameY + (frames[frameIndex + 2] - prevFrameY) * percent) - bone.scaleY) * alpha;
    }
};
spine.ColorTimeline = function (frameCount) {
    this.boneIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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;
        var r, g, b, a;
        if (time >= frames[frames.length - 5]) {
            var i = frames.length - 1;
            r = frames[i - 3];
            g = frames[i - 2];
            b = frames[i - 1];
            a = frames[i];
        } else {
            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] - frameTime);
            percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent);
            r = prevFrameR + (frames[frameIndex + 1] - prevFrameR) * percent;
            g = prevFrameG + (frames[frameIndex + 2] - prevFrameG) * percent;
            b = prevFrameB + (frames[frameIndex + 3] - prevFrameB) * percent;
            a = prevFrameA + (frames[frameIndex + 4] - 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.slotIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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 = [];
    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;
    },
    apply: function (skeleton, lastTime, time, firedEvents, alpha) {
        if (!firedEvents) return;
        var frames = this.frames;
        var frameCount = frames.length;
        if (lastTime > time) {
            this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha);
            lastTime = -1;
        } else if (lastTime >= frames[frameCount - 1])
            return;
        if (time < frames[0]) return;
        var frameIndex;
        if (lastTime < frames[0])
            frameIndex = 0;
        else {
            frameIndex = spine.Animation.binarySearch1(frames, lastTime);
            var frame = frames[frameIndex];
            while (frameIndex > 0) {
                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 = [];
    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;
        var frameIndex;
        if (time >= frames[frames.length - 1])
            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.slotIndex = this.attachment = 0;
    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;
        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]) {
            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;
        }
        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.ikConstraintIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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;
        var ikConstraint = skeleton.ikConstraints[this.ikConstraintIndex];
        if (time >= frames[frames.length - 3]) {
            ikConstraint.mix += (frames[frames.length - 2] - ikConstraint.mix) * alpha;
            ikConstraint.bendDirection = frames[frames.length - 1];
            return;
        }
        var frameIndex = spine.Animation.binarySearch(frames, time, 3);
        var prevFrameMix = frames[frameIndex + -2];
        var frameTime = frames[frameIndex];
        var percent = 1 - (time - frameTime) / (frames[frameIndex + -3] - frameTime);
        percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
        var mix = prevFrameMix + (frames[frameIndex + 1] - prevFrameMix) * percent;
        ikConstraint.mix += (mix - ikConstraint.mix) * alpha;
        ikConstraint.bendDirection = frames[frameIndex + -1];
    }
};
spine.FlipXTimeline = function (frameCount) {
    this.boneIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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.boneIndex = 0;
    this.curves = new spine.Curves(frameCount);
    this.frames = [];
    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.width = this.height = 0;
    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,
    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;
    },
    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;
    },
    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;
    },
    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;
    },
    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;
    },
    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;
    },
    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;
    },
    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.x = this.y = 0;
    this.r = this.g = this.b = this.a = 1;
    this.time = 0;
    this.flipX = this.flipY = false;
    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,
    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;
        }
    },
    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++;
        }
    },
    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);
        }
    },
    getRootBone: function () {
        return this.bones.length ? this.bones[0] : 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;
    },
    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;
    },
    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;
    },
    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 new Error("Skin not found: " + skinName);
        this.setSkin(skin);
    },
    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;
    },
    getAttachmentBySlotName: function (slotName, attachmentName) {
        return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName);
    },
    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;
    },
    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 new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName);
                }
                slot.setAttachment(attachment);
                return;
            }
        }
        throw new Error("Slot not found: " + slotName);
    },
    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.intValue = this.floatValue = 0;
    this.name = name;
};
spine.EventData.prototype = {
    intValue: 0,
    floatValue: 0,
    stringValue: null
};
spine.Event = function (data) {
    this.intValue = this.floatValue = 0;
    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.type = spine.AttachmentType.region;
    this.x = this.y = this.rotation = 0;
    this.scaleX = this.scaleY = 1;
    this.width = this.height = 0;
    this.r = this.g = this.b = this.a = 1;
    this.regionOffsetX = this.regionOffsetY = this.regionWidth = this.regionHeight = this.regionOriginalWidth = this.regionOriginalHeight = 0;
    this.name = name;
    this.offset = [];
    this.offset.length = 8;
    this.uvs = [];
    this.uvs.length = 8;
};
spine.RegionAttachment.prototype = {
    x: 0, y: 0,
    rotation: 0,
    scaleX: 1, scaleY: 1,
    width: 0, height: 0,
    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] = u;
            uvs[3] = v2;
            uvs[4] = u;
            uvs[5] = v;
            uvs[6] = u2;
            uvs[7] = v;
            uvs[0] = u2;
            uvs[1] = v2;
        } else {
            uvs[0] = u;
            uvs[1] = v2;
            uvs[2] = u;
            uvs[3] = v;
            uvs[4] = u2;
            uvs[5] = v;
            uvs[6] = u2;
            uvs[7] = 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] = localXCos - localYSin;
        offset[1] = localYCos + localXSin;
        offset[2] = localXCos - localY2Sin;
        offset[3] = localY2Cos + localXSin;
        offset[4] = localX2Cos - localY2Sin;
        offset[5] = localY2Cos + localX2Sin;
        offset[6] = localX2Cos - localYSin;
        offset[7] = 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] = offset[0] * m00 + offset[1] * m01 + x;
        vertices[1] = offset[0] * m10 + offset[1] * m11 + y;
        vertices[2] = offset[2] * m00 + offset[3] * m01 + x;
        vertices[3] = offset[2] * m10 + offset[3] * m11 + y;
        vertices[4] = offset[4] * m00 + offset[5] * m01 + x;
        vertices[5] = offset[4] * m10 + offset[5] * m11 + y;
        vertices[6] = offset[6] * m00 + offset[7] * m01 + x;
        vertices[7] = offset[6] * m10 + offset[7] * m11 + y;
    }
};
spine.MeshAttachment = function (name) {
    this.type = spine.AttachmentType.mesh;
    this.hullLength = 0;
    this.r = this.g = this.b = this.a = 1;
    this.regionU = this.regionV = this.regionV2 = 0;
    this.regionRotate = false;
    this.regionOffsetX = this.regionOffsetY = this.regionWidth = this.regionHeight = this.regionOriginalWidth = this.regionOriginalHeight = 0;
    this.width = this.height = 0;
    this.name = name;
};
spine.MeshAttachment.prototype = {
    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.type = spine.AttachmentType.skinnedmesh;
    this.hullLength = 0;
    this.r = this.g = this.b = this.a = 1;
    this.regionU = this.regionV = this.regionU2 = this.regionV2 = 0;
    this.regionRotate = false;
    this.regionOffsetX = this.regionOffsetY = this.regionWidth = this.regionHeight = this.regionOriginalWidth = this.regionOriginalHeight = 0;
    this.width = this.height = 0;
    this.name = name;
};
spine.SkinnedMeshAttachment.prototype = {
    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.type = spine.AttachmentType.boundingbox;
    this.name = name;
    this.vertices = [];
};
spine.BoundingBoxAttachment.prototype = {
    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 = {};
    this.defaultMix = 0;
};
spine.AnimationStateData.prototype = {
    defaultMix: 0,
    setMixByName: function (fromName, toName, duration) {
        var from = this.skeletonData.findAnimation(fromName);
        if (!from) throw new Error("Animation not found: " + fromName);
        var to = this.skeletonData.findAnimation(toName);
        if (!to) throw new Error("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 () {
    this.delay = this.time = this.endTime = 0;
    this.lastTime = -1;
    this.timeScale = 1;
    this.mixTime = this.mixDuration = 1;
    this.mix = 1;
};
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.timeScale = 1;
    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 {
                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);
            }
            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 (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 new Error("Animation not found: " + animationName);
        return this.setAnimation(trackIndex, animation, loop);
    },
    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 new Error("Animation not found: " + animationName);
        return this.addAnimation(trackIndex, animation, loop, 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;
    },
    getCurrent: function (trackIndex) {
        if (trackIndex >= this.tracks.length) return null;
        return this.tracks[trackIndex];
    }
};
spine.SkeletonJson = function (attachmentLoader) {
    this.scale = 1;
    this.attachmentLoader = attachmentLoader;
};
spine.SkeletonJson.prototype = {
    scale: 1,
    readSkeletonData: function (root, name) {
        var skeletonData = new spine.SkeletonData();
        skeletonData.name = name;
        var skeletonMap = root["skeleton"];
        if (skeletonMap) {
            skeletonData.hash = skeletonMap["hash"];
            skeletonData.version = skeletonMap["spine"];
            skeletonData.width = skeletonMap["width"] || 0;
            skeletonData.height = skeletonMap["height"] || 0;
        }
        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 new Error("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);
        }
        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 new Error("IK bone not found: " + bones[ii]);
                    ikConstraintData.bones.push(bone);
                }
                ikConstraintData.target = skeletonData.findBone(ikMap["target"]);
                if (!ikConstraintData.target) throw new Error("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);
            }
        }
        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 new Error("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.blendMode = spine.AttachmentType[slotMap["blend"] || "normal"];
            skeletonData.slots.push(slotData);
        }
        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;
        }
        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);
        }
        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 new Error("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 new Error("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 new Error("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 new Error("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 new Error("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 new Error("Slot not found: " + offsetMap["slot"]);
                        while (originalIndex != slotIndex)
                            unchanged[unchangedIndex++] = originalIndex++;
                        drawOrder[originalIndex + offsetMap["offset"]] = originalIndex++;
                    }
                    while (originalIndex < slotCount)
                        unchanged[unchangedIndex++] = originalIndex++;
                    for (var 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 new Error("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 new Error("Color hexadecimal length must be 8, received: " + 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) {
                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) {
                region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
                if (reader.readTuple(tuple) == 4) {
                    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 () {
    this.width = this.height = 0;
};
spine.AtlasPage.prototype = {
    name: null,
    format: null,
    minFilter: null,
    magFilter: null,
    uWrap: null,
    vWrap: null,
    rendererObject: null,
    width: 0,
    height: 0
};
spine.AtlasRegion = function () {
    this.x = this.y = this.width = this.height =
        this.u = this.v = this.u2 = this.v2 =
            this.offsetX = this.offsetY =
                this.originalWidth = this.originalHeight = 0;
    this.index = 0;
};
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.index = 0;
    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 new Error("Invalid line: " + line);
        return this.trim(line.substring(colon + 1));
    },
    readTuple: function (tuple) {
        var line = this.readLine();
        var colon = line.indexOf(":");
        if (colon == -1) throw new Error("Invalid line: " + line);
        var i = 0, lastMatch = colon + 1;
        for (; i < 3; i++) {
            var comma = line.indexOf(",", lastMatch);
            if (comma == -1) break;
            tuple[i] = 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 new Error("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 new Error("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 new Error("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.minX = this.minY = this.maxX = this.maxY = 0;
    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;
    },
    aabbContainsPoint: function (x, y) {
        return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
    },
    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;
    },
    aabbIntersectsSkeleton: function (bounds) {
        return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;
    },
    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;
    },
    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;
    },
    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;
    },
    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;
    }
};
sp._atlasPage_createTexture_webGL = function (self, path) {
    var texture = cc.textureCache.addImage(path);
    self.rendererObject = new cc.TextureAtlas(texture, 128);
    self.width = texture.getPixelsWide();
    self.height = texture.getPixelsHigh();
};
sp._atlasPage_createTexture_canvas = function(self, path) {
    self._texture = cc.textureCache.addImage(path);
};
sp._atlasPage_disposeTexture = function (self) {
    self.rendererObject.release();
};
sp._atlasLoader = {
    spAtlasFile:null,
    setAtlasFile:function(spAtlasFile){
        this.spAtlasFile = spAtlasFile;
    },
    load:function(page, line, spAtlas){
        var texturePath = cc.path.join(cc.path.dirname(this.spAtlasFile), line);
        if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
            sp._atlasPage_createTexture_webGL(page,texturePath);
        else
            sp._atlasPage_createTexture_canvas(page,texturePath);
    },
    unload:function(obj){
    }
};
sp.ANIMATION_EVENT_TYPE = {
    START: 0,
    END: 1,
    COMPLETE: 2,
    EVENT: 3
};
sp.TrackEntryListeners = function(startListener, endListener, completeListener, eventListener){
    this.startListener = startListener || null;
    this.endListener = endListener || null;
    this.completeListener = completeListener || null;
    this.eventListener = eventListener || null;
};
sp.TrackEntryListeners.getListeners = function(entry){
    if(!entry.rendererObject){
        entry.rendererObject = new sp.TrackEntryListeners();
        entry.listener = sp.trackEntryCallback;
    }
    return entry.rendererObject;
};
sp.trackEntryCallback = function(state, trackIndex, type, event, loopCount) {
    state.rendererObject.onTrackEntryEvent(trackIndex, type, event, loopCount);
};
sp.SkeletonAnimation = sp.Skeleton.extend({
    _state: null,
    _target: null,
    _callback: null,
    _ownsAnimationStateData: false,
    _startListener: null,
    _endListener: null,
    _completeListener: null,
    _eventListener: null,
    init: function () {
        sp.Skeleton.prototype.init.call(this);
        this._ownsAnimationStateData = true;
        this.setAnimationStateData(new spine.AnimationStateData(this._skeleton.data));
    },
    setAnimationStateData: function (stateData) {
        var state = new spine.AnimationState(stateData);
        state.rendererObject = this;
        state.onStart = this._onAnimationStateStart.bind(this);
        state.onComplete = this._onAnimationStateComplete.bind(this);
        state.onEnd = this._onAnimationStateEnd.bind(this);
        state.onEvent = this._onAnimationStateEvent.bind(this);
        this._state = state;
    },
    setMix: function (fromAnimation, toAnimation, duration) {
        this._state.data.setMixByName(fromAnimation, toAnimation, duration);
    },
    setAnimationListener: function (target, callback) {
        this._target = target;
        this._callback = callback;
    },
    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);
    },
    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);
    },
    getCurrent: function (trackIndex) {
        return this._state.getCurrent(trackIndex);
    },
    clearTracks: function () {
        this._state.clearTracks();
    },
    clearTrack: function (trackIndex) {
        this._state.clearTrack(trackIndex);
    },
    update: function (dt) {
        this._super(dt);
        dt *= this._timeScale;
        this._state.update(dt);
        this._state.apply(this._skeleton);
        this._skeleton.updateWorldTransform();
        this._renderCmd._updateChild();
    },
    setStartListener: function(listener){
        this._startListener = 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)
        }
    }
});
sp.SkeletonAnimation.create = function (skeletonDataFile, atlasFile, scale) {
    return new sp.SkeletonAnimation(skeletonDataFile, atlasFile, scale);
};
(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) {
            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) {
            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});
            }
            drawingUtil.setPointSize(4);
            drawingUtil.setDrawColor(0, 0, 255, 255);
            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){
            }
        }
    };
    var loaded = function (sprite, texture, rendererObject, attachment) {
        var rect = new cc.Rect(rendererObject.x, rendererObject.y, rendererObject.width, rendererObject.height);
        sprite.initWithTexture(texture, rect, rendererObject.rotate, false);
        sprite._rect.width = attachment.width;
        sprite._rect.height = attachment.height;
        sprite.setContentSize(attachment.width, attachment.height);
        sprite.setRotation(-attachment.rotation);
        sprite.setScale(rendererObject.width / rendererObject.originalWidth * attachment.scaleX,
            rendererObject.height / rendererObject.originalHeight * attachment.scaleY);
    };
    proto._createSprite = function(slot, attachment){
        var rendererObject = attachment.rendererObject;
        var texture = rendererObject.page._texture;
        var sprite = new cc.Sprite();
        if (texture.isLoaded()) {
            loaded(sprite, texture, rendererObject, attachment);
        } else {
            texture.addEventListener('load', function () {
                loaded(sprite, texture, rendererObject, attachment);
            }, this);
        }
        slot.sprites = slot.sprites || {};
        slot.sprites[rendererObject.name] = sprite;
        return sprite;
    };
    proto._updateChild = function(){
        var locSkeleton = this._node._skeleton, slots = locSkeleton.slots;
        var 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);
                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);
                }
                selSprite._renderCmd._displayedOpacity = 0 | (this._node.getOpacity() * locSkeleton.a * slot.a);
                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) {
            } else {
                slotNode.setVisible(false);
                continue;
            }
            slotNode.setVisible(true);
        }
    };
})();
(function(){
    sp.Skeleton.WebGLRenderCmd = function (renderableObject) {
        cc.Node.WebGLRenderCmd.call(this, renderableObject);
        this._needDraw = true;
        this._matrix = new cc.math.Matrix4();
        this._matrix.identity();
        this._tmpQuad = new cc.V3F_C4B_T2F_Quad();
        this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
    };
    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;
        var color = node.getColor(), locSkeleton = node._skeleton;
        var blendMode, textureAtlas, attachment, slot, i, n;
        var locBlendFunc = node._blendFunc;
        var premultiAlpha = node._premultipliedAlpha;
        var wt = this._worldTransform;
        this._matrix.mat[0] = wt.a;
        this._matrix.mat[4] = wt.c;
        this._matrix.mat[12] = wt.tx;
        this._matrix.mat[1] = wt.b;
        this._matrix.mat[5] = wt.d;
        this._matrix.mat[13] = wt.ty;
        this._shaderProgram.use();
        this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix);
        locSkeleton.r = color.r / 255;
        locSkeleton.g = color.g / 255;
        locSkeleton.b = color.b / 255;
        locSkeleton.a = node.getOpacity() / 255;
        if (premultiAlpha) {
            locSkeleton.r *= locSkeleton.a;
            locSkeleton.g *= locSkeleton.a;
            locSkeleton.b *= locSkeleton.a;
        }
        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, premultiAlpha);
                    break;
                case sp.ATTACHMENT_TYPE.MESH:
                    this._updateMeshAttachmentQuad(attachment, slot, tmpQuad, premultiAlpha);
                    break;
                case sp.ATTACHMENT_TYPE.SKINNED_MESH:
                    break;
                default:
                    continue;
            }
            var regionTextureAtlas = node.getTextureAtlas(attachment);
            if (slot.data.blendMode != blendMode) {
                if (textureAtlas) {
                    textureAtlas.drawQuads();
                    textureAtlas.removeAllQuads();
                }
                blendMode = slot.data.blendMode;
                switch (blendMode) {
                case spine.BlendMode.additive:
                    cc.glBlendFunc(premultiAlpha ? cc.ONE : cc.SRC_ALPHA, cc.ONE);
                    break;
                case spine.BlendMode.multiply:
                    cc.glBlendFunc(cc.DST_COLOR, cc.ONE_MINUS_SRC_ALPHA);
                    break;
                case spine.BlendMode.screen:
                    cc.glBlendFunc(cc.ONE, cc.ONE_MINUS_SRC_COLOR);
                    break;
                default:
                    cc.glBlendFunc(locBlendFunc.src, 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.current_stack.stack.push(cc.current_stack.top);
            cc.current_stack.top = this._matrix;
            var drawingUtil = cc._drawingUtil;
            if (node._debugSlots) {
                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) {
                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));
                }
                drawingUtil.setPointSize(4);
                drawingUtil.setDrawColor(0, 0, 255, 255);
                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];
    };
})();
(function(){
    gaf.Sprite.WebGLRenderCmd = function (renderable) {
        cc.Sprite.WebGLRenderCmd.call(this, renderable);
        this._defualtShader = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
        this._customShader = gaf._Shaders.Alpha;
        this._tintMult = null;
        this._tintOffset = null;
        this._ctxMatrixBody = null;
        this._ctxMatrixAppendix = null;
    };
    var proto = gaf.Sprite.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
    proto.constructor = gaf.Sprite.WebGLRenderCmd;
    proto._identityVec = [1.0, 1.0, 1.0, 1.0];
    proto._zeroVec = [0.0, 0.0, 0.0, 0.0];
    proto._identityMat = [
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    ];
    proto._disableCtx = function(){
        this.setShaderProgram(this._defualtShader);
    };
    proto._enableCtx = function(){
        this.setShaderProgram(this._customShader);
    };
    proto._applyCtxState = function(gafObject){
        var tintMult = gafObject._cascadeColorMult;
        this._tintMult = [
            tintMult.r / 255,
            tintMult.g / 255,
            tintMult.b / 255,
            tintMult.a / 255
        ];
        var tintOffset = gafObject._cascadeColorOffset;
        this._tintOffset = [
            tintOffset.r / 255,
            tintOffset.g / 255,
            tintOffset.b / 255,
            tintOffset.a / 255
        ];
        var filterStack = gafObject._filterStack;
        if(filterStack && filterStack.length > 0 && filterStack[0].type === gaf.EFFECT_COLOR_MATRIX)
        {
            var m = filterStack[0].colorMatrix;
            this._ctxMatrixBody = [
                m.rr, m.rg, m.rb, m.ra,
                m.gr, m.gg, m.gb, m.ga,
                m.br, m.bg, m.bb, m.ba,
                m.ar, m.ag, m.ab, m.aa
            ];
            this._ctxMatrixAppendix = [
                m.r / 255,
                m.g / 255,
                m.b / 255,
                m.a / 255
            ];
        }
        else
        {
            this._ctxMatrixBody = null;
            this._ctxMatrixAppendix = null;
        }
    };
    proto._setUniforms = function()
    {
        if(this._shaderProgram === this._customShader)
        {
            this._shaderProgram.use();
            {
                this._shaderProgram.setUniformLocationWith4fv(
                    gaf._Uniforms.ColorTransformMult,
                    this._tintMult,
                    1
                );
                this._shaderProgram.setUniformLocationWith4fv(
                    gaf._Uniforms.ColorTransformOffset,
                    this._tintOffset,
                    1
                );
            }
            if(this._ctxMatrixBody && this._ctxMatrixAppendix)
            {
                this._shaderProgram.setUniformLocationWithMatrix4fv(
                    gaf._Uniforms.ColorMatrixBody,
                    this._ctxMatrixBody,
                    1
                );
                this._shaderProgram.setUniformLocationWith4fv(
                    gaf._Uniforms.ColorMatrixAppendix,
                    this._ctxMatrixAppendix,
                    1
                );
            }
            else
            {
                this._shaderProgram.setUniformLocationWithMatrix4fv(
                    gaf._Uniforms.ColorMatrixBody,
                    this._identityMat,
                    1
                );
                this._shaderProgram.setUniformLocationWith4fv(
                    gaf._Uniforms.ColorMatrixAppendix,
                    this._zeroVec,
                    1
                );
            }
        }
    };
    proto.rendering = function(ctx)
    {
        this._setUniforms();
        cc.Sprite.WebGLRenderCmd.prototype.rendering.call(this, ctx);
    };
})();