(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (factory((global['scilla-kuwo'] = {})));
}(this, (function (exports) { 'use strict';

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation. All rights reserved.
    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
    this file except in compliance with the License. You may obtain a copy of the
    License at http://www.apache.org/licenses/LICENSE-2.0

    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
    MERCHANTABLITY OR NON-INFRINGEMENT.

    See the Apache Version 2.0 License for specific language governing permissions
    and limitations under the License.
    ***************************************************************************** */
    /* global Reflect, Promise */

    var extendStatics = function(d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };

    function __extends(d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    }

    function __decorate(decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    }

    function __awaiter(thisArg, _arguments, P, generator) {
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }

    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f) throw new TypeError("Generator is already executing.");
            while (_) try {
                if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
                if (y = 0, t) op = [op[0] & 2, t.value];
                switch (op[0]) {
                    case 0: case 1: t = op; break;
                    case 4: _.label++; return { value: op[1], done: false };
                    case 5: _.label++; y = op[1]; op = [0]; continue;
                    case 7: op = _.ops.pop(); _.trys.pop(); continue;
                    default:
                        if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                        if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                        if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                        if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                        if (t[2]) _.ops.pop();
                        _.trys.pop(); continue;
                }
                op = body.call(thisArg, _);
            } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
            if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
        }
    }

    function __values(o) {
        var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
        if (m) return m.call(o);
        return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
    }

    function __read(o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    }

    function __spread() {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    }

    var HASH_CODE_INK = 0;
    function getHashCode() {
        return ++HASH_CODE_INK;
    }
    var HashObject = (function () {
        function HashObject() {
            this._hashCode = getHashCode();
        }
        Object.defineProperty(HashObject.prototype, "hashCode", {
            get: function () {
                return this._hashCode;
            },
            enumerable: true,
            configurable: true
        });
        return HashObject;
    }());

    function injectProp(target, data, callback, ignoreMethod, ignoreNull) {
        if (ignoreMethod === void 0) { ignoreMethod = true; }
        if (ignoreNull === void 0) { ignoreNull = true; }
        if (!target || !data) {
            return false;
        }
        var result = true;
        for (var key in data) {
            var value = data[key];
            if ((!ignoreMethod || typeof value != 'function') && (!ignoreNull || value != null)) {
                if (callback) {
                    callback(target, key, value);
                }
                else {
                    target[key] = value;
                }
            }
        }
        return result;
    }

    var EngineConfig = {
        lineHeightRatio: 1.2,
        entityEnabled: true,
        componentEnabled: true,
        awakeComponentWhenAdded: true,
        sleepComponentWhenRemoved: true,
        drawRenderRect: false,
        imgCrossOrigin: true,
    };
    function modifyEngineConfig(_options) {
        injectProp(EngineConfig, _options);
    }

    var interactiveMap = [
        '_dealGlobalTouchBegin',
        '_dealGlobalTouchMove',
        '_dealGlobalTouchEnd',
    ];
    var ScillaComponent = (function (_super) {
        __extends(ScillaComponent, _super);
        function ScillaComponent() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.delayCallbacks = [];
            _this._enabled = EngineConfig.componentEnabled;
            return _this;
        }
        Object.defineProperty(ScillaComponent.prototype, "enabled", {
            get: function () {
                return this._enabled;
            },
            set: function (value) {
                if (this._enabled !== value) {
                    this._enabled = value;
                    if (this.entity && this.entity.isActive) {
                        if (this._enabled) {
                            this.onEnable();
                        }
                        else {
                            this.onDisable();
                        }
                    }
                }
            },
            enumerable: true,
            configurable: true
        });
        ScillaComponent.prototype._setup = function (entity) {
            this.entity = entity;
            this.onCreate();
        };
        ScillaComponent.prototype._unSetup = function () {
            this.entity = null;
            this.onDestroy();
        };
        ScillaComponent.prototype.onCreate = function () {
        };
        ScillaComponent.prototype.onAwake = function () {
            this._firstUpdate = true;
        };
        ScillaComponent.prototype.onEnable = function () {
        };
        ScillaComponent.prototype.onDisable = function () {
        };
        ScillaComponent.prototype.$onUpdate = function (t) {
            this.onUpdate(t);
            if (!this._firstUpdate) {
                this.invokeDelayCallback(t);
            }
            this._firstUpdate = false;
        };
        ScillaComponent.prototype.invokeDelayCallback = function (t) {
            var e_1, _a;
            var removed = [];
            if (this.entity.name.indexOf('progress') >= 0) {
                console.log();
            }
            for (var i = 0, li = this.delayCallbacks.length; i < li; i++) {
                var _b = this.delayCallbacks[i], callback = _b.callback, once = _b.once;
                if (once) {
                    removed.push(i);
                }
                callback.call(this, t);
            }
            try {
                for (var removed_1 = __values(removed), removed_1_1 = removed_1.next(); !removed_1_1.done; removed_1_1 = removed_1.next()) {
                    var item = removed_1_1.value;
                    this.delayCallbacks.splice(item, 1);
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (removed_1_1 && !removed_1_1.done && (_a = removed_1.return)) _a.call(removed_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
        };
        ScillaComponent.prototype.onUpdate = function (t) {
        };
        ScillaComponent.prototype.afterUpdate = function () {
        };
        ScillaComponent.prototype.onSleep = function () {
        };
        ScillaComponent.prototype.onDestroy = function () {
        };
        ScillaComponent.prototype.onModify = function (value, key, oldValue) {
        };
        ScillaComponent.prototype.getDelayCallback = function (callback) {
            var e_2, _a;
            var result;
            try {
                for (var _b = __values(this.delayCallbacks), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var item = _c.value;
                    if (item.callback == callback) {
                        result = item;
                        break;
                    }
                }
            }
            catch (e_2_1) { e_2 = { error: e_2_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_2) throw e_2.error; }
            }
            return result;
        };
        ScillaComponent.prototype.callOnNextTick = function (callback, once) {
            if (once === void 0) { once = true; }
            var item = this.getDelayCallback(callback);
            if (!item) {
                this.delayCallbacks.push({ callback: callback, once: once });
            }
        };
        ScillaComponent.prototype.cancelOnNextTick = function (callback) {
            var item = this.getDelayCallback(callback);
            var index = this.delayCallbacks.indexOf(item);
            if (index >= 0) {
                this.delayCallbacks.splice(index, 1);
            }
        };
        ScillaComponent.prototype.onInteract = function (type, event) {
            try {
                var hitOn = this[interactiveMap[type]](event);
                return hitOn && this['touchInterrupt'];
            }
            catch (e) {
                console.warn(e);
            }
        };
        ScillaComponent.prototype._dealGlobalTouchBegin = function (e) {
            return this.onGlobalTouchBegin(e);
        };
        ScillaComponent.prototype._dealGlobalTouchMove = function (e) {
            return this.onGlobalTouchMove(e);
        };
        ScillaComponent.prototype._dealGlobalTouchEnd = function (e) {
            return this.onGlobalTouchEnd(e);
        };
        ScillaComponent.prototype.onGlobalTouchBegin = function (e) {
        };
        ScillaComponent.prototype.onGlobalTouchMove = function (e) {
        };
        ScillaComponent.prototype.onGlobalTouchEnd = function (e) {
        };
        Object.defineProperty(ScillaComponent.prototype, "transform", {
            get: function () {
                return this.entity.getComponent('components/base/Transform');
            },
            enumerable: true,
            configurable: true
        });
        ScillaComponent.prototype.broadcast = function (method, level) {
            if (level === void 0) { level = -1; }
            var params = [];
            for (var _i = 2; _i < arguments.length; _i++) {
                params[_i - 2] = arguments[_i];
            }
            var _a;
            (_a = this.entity).broadcast.apply(_a, __spread([method, level], params));
        };
        ScillaComponent.prototype.bubbling = function (method) {
            var params = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                params[_i - 1] = arguments[_i];
            }
            var _a;
            (_a = this.entity).bubbling.apply(_a, __spread([method], params));
        };
        return ScillaComponent;
    }(HashObject));

    function traverse(target, hitChild, level, includeSelf, fullCallback) {
        if (level === void 0) { level = -1; }
        if (includeSelf === void 0) { includeSelf = false; }
        var params = [];
        for (var _i = 5; _i < arguments.length; _i++) {
            params[_i - 5] = arguments[_i];
        }
        var e_1, _a;
        var interrupt;
        if (includeSelf) {
            hitChild.apply(void 0, __spread([target], params));
        }
        if (level !== 0) {
            try {
                for (var _b = __values(target.children), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var child = _c.value;
                    if (hitChild.apply(void 0, __spread([child], params))) {
                        interrupt = true;
                        continue;
                    }
                    if (child.children.length > 0) {
                        traverse.apply(void 0, __spread([child, hitChild, level - 1, false, fullCallback], params));
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_1) throw e_1.error; }
            }
        }
        !interrupt && fullCallback && fullCallback(target);
    }
    function traversePostorder(target, hitChild, level, includeSelf, fullCallback) {
        if (level === void 0) { level = -1; }
        if (includeSelf === void 0) { includeSelf = false; }
        var params = [];
        for (var _i = 5; _i < arguments.length; _i++) {
            params[_i - 5] = arguments[_i];
        }
        if (level !== 0) {
            for (var i = target.children.length - 1; i >= 0; i--) {
                var child = target.children[i];
                if (traversePostorder.apply(void 0, __spread([child, hitChild, level - 1, false, fullCallback], params))) {
                    return true;
                }
                if (hitChild.apply(void 0, __spread([child], params))) {
                    return true;
                }
            }
        }
        if (includeSelf) {
            hitChild.apply(void 0, __spread([target], params));
        }
        fullCallback && fullCallback(target);
    }
    function bubbling(target, hitParent, includeSelf) {
        if (includeSelf === void 0) { includeSelf = false; }
        var params = [];
        for (var _i = 3; _i < arguments.length; _i++) {
            params[_i - 3] = arguments[_i];
        }
        if (includeSelf) {
            hitParent.apply(void 0, __spread([target], params));
        }
        var entity = target;
        while (entity = entity.parent) {
            if (hitParent.apply(void 0, __spread([entity], params))) {
                break;
            }
        }
    }
    var Entity = (function (_super) {
        __extends(Entity, _super);
        function Entity(name, uuid) {
            var _this = _super.call(this) || this;
            _this.name = 'Entity';
            _this._isFree = true;
            _this._enabled = EngineConfig.entityEnabled;
            _this._parent = null;
            _this._children = [];
            _this._components = [];
            _this.invokeOnEntity = function (hitEntity, method) {
                var params = [];
                for (var _i = 2; _i < arguments.length; _i++) {
                    params[_i - 2] = arguments[_i];
                }
                var hitBreak = false;
                hitEntity.forEachComponent(function (comp) {
                    var m = comp[method];
                    if (m) {
                        var result = m.apply(comp, params);
                        if (result) {
                            hitBreak = true;
                        }
                    }
                    return false;
                });
                if (hitBreak) {
                    return true;
                }
            };
            if (name) {
                _this.name = name;
            }
            if (uuid) {
                _this._uuid = uuid;
            }
            return _this;
        }
        Object.defineProperty(Entity.prototype, "uuid", {
            get: function () {
                return this._uuid;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Entity.prototype, "enabled", {
            get: function () {
                return this._enabled;
            },
            set: function (value) {
                if (this._enabled !== value) {
                    this._enabled = value;
                    traverse(this, function (child) {
                        child._invokeEnabledState(value);
                        return false;
                    }, -1, true);
                }
            },
            enumerable: true,
            configurable: true
        });
        Entity.prototype._invokeEnabledState = function (enabled) {
            if (this._enabled && enabled) {
                this.onEnable();
            }
            else if (!this._enabled && !enabled) {
                this.onDisable();
            }
        };
        Object.defineProperty(Entity.prototype, "isParentActive", {
            get: function () {
                return this._parent && this._parent.enabled && !this._parent.isFree;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Entity.prototype, "isActive", {
            get: function () {
                return this.isParentActive && this._enabled;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Entity.prototype, "isFree", {
            get: function () {
                return this._isFree;
            },
            enumerable: true,
            configurable: true
        });
        Entity.prototype._free = function () {
            this._isFree = true;
            traverse(this, function (child) {
                child._free();
                return false;
            }, 1);
        };
        Entity.prototype._restrict = function () {
            this._isFree = false;
            traverse(this, function (child) {
                child._restrict();
                return false;
            }, 1);
        };
        Object.defineProperty(Entity.prototype, "parent", {
            get: function () {
                return this._parent;
            },
            enumerable: true,
            configurable: true
        });
        Entity.prototype.containsChild = function (child) {
            return this.getChildIndex(child) >= 0;
        };
        Entity.prototype._onChildAdded = function (child) {
            child._parent = this;
            if (!this._isFree && child._isFree) {
                if (child.isParentActive) {
                    child._invokeEnabledState(true);
                }
                child._restrict();
            }
        };
        Entity.prototype._onChildRemoved = function (child) {
            child._parent = null;
            if (!this._isFree && !child._isFree) {
                if (child.isActive) {
                    child._invokeEnabledState(false);
                }
                child._free();
            }
        };
        Entity.prototype.addChild = function (child) {
            this.addChildAt(child, this._children.length);
        };
        Entity.prototype.addChildAt = function (child, index) {
            if (child.parent && child.parent !== this) {
                child.parent.removeChild(child);
            }
            var currentIndex = this.getChildIndex(child);
            if (index < 0 || currentIndex == index) {
                return;
            }
            index = Math.min(this._children.length, index);
            if (currentIndex >= 0 || index < this._children.length) {
                if (currentIndex >= 0) {
                    this._children.splice(currentIndex, 1);
                }
                this._children.splice(index, 0, child);
            }
            else {
                this._children.push(child);
            }
            this._onChildAdded(child);
        };
        Entity.prototype.removeChild = function (child) {
            var index = this.getChildIndex(child);
            if (index >= 0) {
                this.removeChildAt(index);
            }
        };
        Entity.prototype.removeChildAt = function (index) {
            var child = this._children[index];
            this._onChildRemoved(child);
            this._children.splice(index, 1);
        };
        Entity.prototype.getChildIndex = function (child) {
            return this._children.indexOf(child);
        };
        Entity.prototype.getChildByIndex = function (index) {
            return this._children[index];
        };
        Entity.prototype.removeChildren = function () {
            while (this._children.length > 0) {
                this.removeChildAt(0);
            }
        };
        Object.defineProperty(Entity.prototype, "children", {
            get: function () {
                return this._children;
            },
            enumerable: true,
            configurable: true
        });
        Entity.prototype.addComponent = function (component) {
            this.onAddComponent(component);
            this._components.push(component);
        };
        Entity.prototype.addComponentAt = function (component, index) {
            var currentIndex = this._components.indexOf(component);
            if (currentIndex == index) {
                return;
            }
            if (currentIndex >= 0) {
                this._components.splice(currentIndex, 1);
            }
            this._components.splice(index, 0, component);
            this.onAddComponent(component);
        };
        Entity.prototype.removeComponent = function (component) {
            this.onRemoveComponent(component);
            var index = this._components.indexOf(component);
            if (index >= 0) {
                this._components.splice(index, 1);
            }
        };
        Entity.prototype.removeAllComponents = function () {
            while (this._components.length > 0) {
                this.removeComponent(this._components[0]);
            }
        };
        Entity.prototype.getComponents = function (clazz) {
            return this._components.filter(function (component) {
                return typeof clazz === 'string' ? component.constructor.__class__ === clazz : component instanceof clazz;
            });
        };
        Entity.prototype.getComponent = function (clazz) {
            return this.getComponents(clazz)[0];
        };
        Object.defineProperty(Entity.prototype, "components", {
            get: function () {
                return this._components;
            },
            enumerable: true,
            configurable: true
        });
        Entity.prototype.forEachComponent = function (func) {
            var e_2, _a;
            try {
                for (var _b = __values(this._components), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var component = _c.value;
                    if (func(component)) {
                        break;
                    }
                }
            }
            catch (e_2_1) { e_2 = { error: e_2_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_2) throw e_2.error; }
            }
        };
        Entity.prototype.onEnable = function () {
            this.forEachComponent(function (comp) {
                if (comp.enabled) {
                    return comp.onAwake();
                }
            });
        };
        Entity.prototype.onDisable = function () {
            this.forEachComponent(function (comp) {
                if (comp.enabled) {
                    return comp.onSleep();
                }
            });
        };
        Entity.prototype.onUpdate = function (t) {
            this.forEachComponent(function (comp) {
                if (comp.enabled) {
                    return comp.$onUpdate(t);
                }
            });
        };
        Entity.prototype.afterUpdate = function () {
            this.forEachComponent(function (comp) {
                if (comp.enabled) {
                    return comp.afterUpdate();
                }
            });
        };
        Entity.prototype.onInteract = function (type, event) {
            if (!this.isFree && this.enabled) {
                var interrupt_1 = false;
                this.forEachComponent(function (comp) {
                    if (comp.enabled && comp.interactable) {
                        var r = comp.onInteract(type, event);
                        if (r) {
                            interrupt_1 = true;
                        }
                        return false;
                    }
                });
                return interrupt_1;
            }
            else {
                return false;
            }
        };
        Entity.prototype.onAddComponent = function (component) {
            component._setup(this);
            if (EngineConfig.awakeComponentWhenAdded) {
                this.awakeComponent(component);
            }
        };
        Entity.prototype.awakeComponent = function (component) {
            if (!this._isFree && this._enabled) {
                component.onAwake();
            }
        };
        Entity.prototype.onRemoveComponent = function (component) {
            if (EngineConfig.sleepComponentWhenRemoved) {
                this.sleepComponent(component);
            }
            component._unSetup();
        };
        Entity.prototype.sleepComponent = function (component) {
            if (!this._isFree && this._enabled) {
                component.onSleep();
            }
        };
        Entity.prototype.broadcast = function (method, level) {
            if (level === void 0) { level = -1; }
            var params = [];
            for (var _i = 2; _i < arguments.length; _i++) {
                params[_i - 2] = arguments[_i];
            }
            traverse.apply(void 0, __spread([this, this.invokeOnEntity, level, true, null, method], params));
        };
        Entity.prototype.bubbling = function (method) {
            var params = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                params[_i - 1] = arguments[_i];
            }
            bubbling.apply(void 0, __spread([this, this.invokeOnEntity, false, method], params));
        };
        return Entity;
    }(HashObject));

    var Bounds = (function () {
        function Bounds(x, y, width, height) {
            if (x === void 0) { x = 0; }
            if (y === void 0) { y = 0; }
            if (width === void 0) { width = 0; }
            if (height === void 0) { height = 0; }
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }
        Object.defineProperty(Bounds.prototype, "left", {
            get: function () {
                return this.x;
            },
            set: function (v) {
                this.x = v;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Bounds.prototype, "top", {
            get: function () {
                return this.y;
            },
            set: function (v) {
                this.y = v;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Bounds.prototype, "right", {
            get: function () {
                return this.x + this.width;
            },
            set: function (v) {
                this.width = v - this.x;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Bounds.prototype, "bottom", {
            get: function () {
                return this.y + this.height;
            },
            set: function (v) {
                this.height = v - this.y;
            },
            enumerable: true,
            configurable: true
        });
        Bounds.prototype.contains = function (x, y) {
            return this.x <= x &&
                this.x + this.width >= x &&
                this.y <= y &&
                this.y + this.height >= y;
        };
        Bounds.prototype.setTo = function (x, y, width, height) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        };
        Bounds.prototype.copyFrom = function (target) {
            this.x = target.x;
            this.y = target.y;
            this.width = target.width;
            this.height = target.height;
        };
        Bounds.prototype.clone = function () {
            return new Bounds(this.x, this.y, this.width, this.height);
        };
        Bounds.prototype.inflate = function (dx, dy) {
            this.x -= dx;
            this.width += 2 * dx;
            this.y -= dy;
            this.height += 2 * dy;
        };
        Bounds.prototype.isEmpty = function () {
            return this.width <= 0 || this.height <= 0;
        };
        Bounds.prototype.setEmpty = function () {
            this.x = 0;
            this.y = 0;
            this.width = 0;
            this.height = 0;
        };
        Bounds.prototype.intersects = function (toIntersect) {
            return Math.max(this.x, toIntersect.x) <= Math.min(this.right, toIntersect.right)
                && Math.max(this.y, toIntersect.y) <= Math.min(this.bottom, toIntersect.bottom);
        };
        Bounds.prototype.containsBounds = function (bounds) {
            var r1 = bounds.x + bounds.width;
            var b1 = bounds.y + bounds.height;
            var r2 = this.x + this.width;
            var b2 = this.y + this.height;
            return (bounds.x >= this.x) && (bounds.x < r2) && (bounds.y >= this.y) && (bounds.y < b2) && (r1 > this.x) && (r1 <= r2) && (b1 > this.y) && (b1 <= b2);
        };
        Bounds.prototype.equals = function (toCompare) {
            if (this === toCompare) {
                return true;
            }
            return this.x === toCompare.x && this.y === toCompare.y
                && this.width === toCompare.width && this.height === toCompare.height;
        };
        Bounds.prototype.toString = function () {
            var _a = this, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
            return "(x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + ")";
        };
        return Bounds;
    }());

    var _canvas;
    var _touchHandler;
    var _scaleX, _scaleY, _rotation;
    var ua = navigator.userAgent.toLowerCase();
    var isMobile = (ua.indexOf('mobile') !== -1 || ua.indexOf('android') !== -1);
    function setupContext(options) {
        if (options === void 0) { options = {}; }
        var canvas = options.canvas, touchHandler = options.touchHandler;
        _touchHandler = touchHandler;
        _canvas = canvas;
        addListeners();
    }
    function updateScaleMode(scaleX, scaleY, rotation) {
        _scaleX = scaleX;
        _scaleY = scaleY;
        _rotation = rotation;
    }
    function addListeners() {
        if (window.navigator.msPointerEnabled) {
            _canvas.addEventListener("MSPointerDown", function (event) {
                event.identifier = event.pointerId;
                onTouchBegin(event);
                prevent(event);
            }, false);
            _canvas.addEventListener("MSPointerMove", function (event) {
                event.identifier = event.pointerId;
                onTouchMove(event);
                prevent(event);
            }, false);
            _canvas.addEventListener("MSPointerUp", function (event) {
                event.identifier = event.pointerId;
                onTouchEnd(event);
                prevent(event);
            }, false);
        }
        else {
            if (!isMobile) {
                addMouseListener();
            }
            addTouchListener();
        }
    }
    function prevent(event) {
        event.stopPropagation();
        if (event["isScroll"] != true && !_canvas['userTyping']) {
            event.preventDefault();
        }
    }
    function addMouseListener() {
        _canvas.addEventListener("mousedown", onTouchBegin);
        _canvas.addEventListener("mousemove", onMouseMove);
        _canvas.addEventListener("mouseup", onTouchEnd);
    }
    function addTouchListener() {
        _canvas.addEventListener("touchstart", function (event) {
            var l = event.changedTouches.length;
            for (var i = 0; i < l; i++) {
                onTouchBegin(event.changedTouches[i]);
            }
            prevent(event);
        }, false);
        _canvas.addEventListener("touchmove", function (event) {
            var l = event.changedTouches.length;
            for (var i = 0; i < l; i++) {
                onTouchMove(event.changedTouches[i]);
            }
            prevent(event);
        }, false);
        _canvas.addEventListener("touchend", function (event) {
            var l = event.changedTouches.length;
            for (var i = 0; i < l; i++) {
                onTouchEnd(event.changedTouches[i]);
            }
            prevent(event);
        }, false);
        _canvas.addEventListener("touchcancel", function (event) {
            var l = event.changedTouches.length;
            for (var i = 0; i < l; i++) {
                onTouchEnd(event.changedTouches[i]);
            }
            prevent(event);
        }, false);
    }
    function onTouchBegin(event) {
        var location = getLocation(event);
        _touchHandler.onTouchBegin(location);
    }
    function onMouseMove(event) {
        if (event.buttons === 0) {
            onTouchEnd(event);
        }
        else {
            onTouchMove(event);
        }
    }
    function onTouchMove(event) {
        var location = getLocation(event);
        _touchHandler.onTouchMove(location);
    }
    function onTouchEnd(event) {
        var location = getLocation(event);
        _touchHandler.onTouchEnd(location);
    }
    function getLocation(event) {
        var doc = document.documentElement;
        var box = _canvas.getBoundingClientRect();
        var left = box.left + window.pageXOffset - doc.clientLeft;
        var top = box.top + window.pageYOffset - doc.clientTop;
        var x = event.pageX - left, newX = x;
        var y = event.pageY - top, newY = y;
        if (_rotation === 90) {
            newX = y;
            newY = box.width - x;
        }
        else if (_rotation === -90) {
            newX = box.height - y;
            newY = x;
        }
        newX = newX / _scaleX;
        newY = newY / _scaleY;
        return {
            x: Math.round(newX),
            y: Math.round(newY),
            identifier: event.identifier || 0,
        };
    }

    var _canvas$1, context, width, height;
    var scaleX, scaleY, rotation = 0;
    var _designWidth, _designHeight, _scaleMode, _modifyCanvasSize;
    var ScaleMode = {
        SHOW_ALL: 'showAll',
        FIXED_WIDTH: 'fixedWidth',
        FIXED_HEIGHT: 'fixedHeight',
    };
    function setupContext$1(options) {
        if (options === void 0) { options = {}; }
        var canvas = options.canvas, designWidth = options.designWidth, designHeight = options.designHeight, _a = options.scaleMode, scaleMode = _a === void 0 ? ScaleMode.SHOW_ALL : _a, _b = options.modifyCanvasSize, modifyCanvasSize = _b === void 0 ? false : _b;
        _designWidth = designWidth;
        _designHeight = designHeight;
        _scaleMode = scaleMode;
        _modifyCanvasSize = modifyCanvasSize;
        _canvas$1 = canvas;
        context = canvas.getContext('2d');
        updateScaleModeSelf();
    }
    function clear() {
        context.setTransform(1, 0, 0, 1, 0, 0);
        context.clearRect(0, 0, width, height);
    }
    function getContext() {
        return context;
    }
    function getStageSize() {
        return {
            width: width,
            height: height,
        };
    }
    function createCanvas() {
        return document.createElement('canvas');
    }
    function updateScaleModeSelf() {
        var parent = _canvas$1.parentElement;
        var containerWidth = parent.clientWidth;
        var containerHeight = parent.clientHeight;
        var designWidth = _designWidth || containerWidth;
        var designHeight = _designHeight || containerHeight;
        scaleX = containerWidth / designWidth;
        scaleY = containerHeight / designHeight;
        switch (_scaleMode) {
            case ScaleMode.SHOW_ALL:
                width = designWidth;
                height = designHeight;
                break;
            case ScaleMode.FIXED_WIDTH:
                width = designWidth;
                if (_modifyCanvasSize) {
                    height = designHeight;
                }
                else {
                    height = containerHeight / scaleX;
                }
                scaleY = scaleX;
                break;
            case ScaleMode.FIXED_HEIGHT:
                if (_modifyCanvasSize) {
                    width = designWidth;
                }
                else {
                    width = containerWidth / scaleY;
                }
                height = designHeight;
                scaleX = scaleY;
                break;
        }
        updateScaleMode(scaleX, scaleY, rotation);
        var styleWidth = _modifyCanvasSize ? designWidth * scaleX : containerWidth;
        var styleHeight = _modifyCanvasSize ? designHeight * scaleY : containerHeight;
        _canvas$1.width = width;
        _canvas$1.height = height;
        _canvas$1.style.display = 'block';
        _canvas$1.style.width = styleWidth + 'px';
        _canvas$1.style.height = styleHeight + 'px';
    }

    var Texture = (function (_super) {
        __extends(Texture, _super);
        function Texture() {
            var _this = _super.call(this) || this;
            _this.bounds = new Bounds();
            return _this;
        }
        Texture.prototype.setFrame = function (frame) {
            var x = frame.x, y = frame.y, w = frame.w, h = frame.h;
            this.bounds.setTo(x, y, w, h);
        };
        Texture.prototype.setImg = function (img) {
            this.img = img;
        };
        Object.defineProperty(Texture.prototype, "width", {
            get: function () {
                return this.bounds.width;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Texture.prototype, "height", {
            get: function () {
                return this.bounds.height;
            },
            enumerable: true,
            configurable: true
        });
        Texture.prototype.getCacheCanvas = function () {
            var _a = this.bounds, width = _a.width, height = _a.height;
            var canvas = this._cacheCanvas;
            if (!canvas) {
                canvas = this._cacheCanvas = createCanvas();
            }
            canvas.width = width;
            canvas.height = height;
            var context = canvas.getContext('2d');
            this.drawToCanvas(context);
            return canvas;
        };
        Texture.prototype.drawToCanvas = function (context, dx, dy, sx, sy, dw, dh) {
            if (dx === void 0) { dx = 0; }
            if (dy === void 0) { dy = 0; }
            var _a = this.bounds, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
            context.drawImage(this.img, sx || x, sy || y, width, height, dx, dy, dw || width, dh || height);
        };
        Texture.prototype.destroy = function () {
            this.img = null;
            this.bounds = null;
            this.destroyCacheCanvas();
        };
        Texture.prototype.destroyCacheCanvas = function () {
            this._cacheCanvas = null;
        };
        return Texture;
    }(HashObject));
    function createTexture(img, frame) {
        var texture = new Texture();
        texture.setImg(img);
        texture.setFrame(frame || { x: 0, y: 0, w: img.width, h: img.height });
        return texture;
    }

    var Sheet = (function (_super) {
        __extends(Sheet, _super);
        function Sheet(img, frames) {
            var _this = _super.call(this) || this;
            _this._textureCache = {};
            if (img) {
                _this.img = img;
            }
            if (frames) {
                _this.frames = frames;
            }
            return _this;
        }
        Sheet.prototype.generateAll = function () {
            for (var key in this.frames) {
                this.generateTexture(key);
            }
        };
        Sheet.prototype.generateTexture = function (name, force) {
            if (force === void 0) { force = false; }
            var _a = this, img = _a.img, frames = _a.frames, _textureCache = _a._textureCache;
            if (!force && _textureCache[name]) {
                return _textureCache[name];
            }
            var frame = frames[name];
            if (frame) {
                return _textureCache[name] = createTexture(img, frame);
            }
        };
        Sheet.prototype.hasTexture = function (name) {
            return !!frames[name];
        };
        Sheet.prototype.getTexture = function (name) {
            var texture = this._textureCache[name];
            if (texture) {
                return texture;
            }
            else {
                return this.generateTexture(name);
            }
        };
        Sheet.prototype.getAllTextures = function () {
            return this._textureCache;
        };
        Sheet.prototype.destroy = function () {
            this.img = null;
            for (var key in this._textureCache) {
                this._textureCache[key].destroy();
                delete this._textureCache[key];
            }
        };
        return Sheet;
    }(HashObject));

    var animationMap = {};
    var animDataMap = {};
    var textureMap = {};
    function getFrameAnimation(name) {
        var animation = animationMap[name];
        if (!animation) {
            animation = animationMap[name] = new FrameAnimationImpl(name);
            animation.fillMcData(name);
        }
        return animation;
    }
    function putFrameAnim(img, data) {
        var mc = data.mc, res = data.res;
        var sheet = new Sheet(img, res);
        for (var key in mc) {
            var animData = animDataMap[key] = mc[key];
            animData.sheet = sheet;
        }
    }
    var FrameAnimationImpl = (function () {
        function FrameAnimationImpl(name) {
            this._name = name;
        }
        Object.defineProperty(FrameAnimationImpl.prototype, "name", {
            get: function () {
                return this._name;
            },
            enumerable: true,
            configurable: true
        });
        FrameAnimationImpl.prototype.fillMcData = function (name) {
            var animData = animDataMap[name];
            if (animData) {
                this._animData = animData;
            }
            else {
                console.warn("anim data [" + name + "] is not exist");
            }
        };
        Object.defineProperty(FrameAnimationImpl.prototype, "fps", {
            get: function () {
                return this._animData.frameRate;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(FrameAnimationImpl.prototype, "labels", {
            get: function () {
                return this._animData.labels;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(FrameAnimationImpl.prototype, "frameCount", {
            get: function () {
                return this._animData.frames.length;
            },
            enumerable: true,
            configurable: true
        });
        FrameAnimationImpl.prototype.getLabel = function (name) {
            var e_1, _a;
            var result;
            try {
                for (var _b = __values(this._animData.labels), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var label = _c.value;
                    if (label.name == name) {
                        result = label;
                        break;
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_1) throw e_1.error; }
            }
            return result;
        };
        FrameAnimationImpl.prototype.getFrame = function (frameIndex) {
            var _animData = this._animData;
            var texture, frameData;
            if (_animData) {
                var frames_1 = _animData.frames;
                frameData = frames_1[frameIndex];
                if (frameData) {
                    var res = frameData.res;
                    texture = textureMap[res];
                    if (!texture) {
                        texture = textureMap[res] = _animData.sheet.getTexture(res);
                    }
                }
            }
            return {
                texture: texture,
                data: frameData,
            };
        };
        FrameAnimationImpl.prototype.destroy = function () {
            this._animData = null;
        };
        return FrameAnimationImpl;
    }());

    var resCache = {};
    var resPath = '';
    var resLoaderType = {
        '.json': loadJson,
        '.json5': loadJson5,
        '.txt': loadTxt,
        '.png': loadTexture,
        '.jpg': loadTexture,
        '.svg': loadTexture,
        '.bimg': loadTextureFromBlob,
        '.sht': loadSheet,
        '.sht-disperse': loadSheetDisperse,
        '.fnt': loadFont,
        '.anim': loadAnim,
    };
    function setResPath(path) {
        resPath = path;
    }
    function loadResItems(items, progress) {
        var total = items.length;
        var count = 0;
        return Promise.all(items.map(function (item) {
            var uuid, url, config, ext;
            if (typeof item === 'string') {
                url = item;
            }
            else {
                url = item.url;
            }
            if (!url) {
                return Promise.resolve();
            }
            if (typeof item === 'string') {
                uuid = getUUIDFromUrl(url);
            }
            else {
                uuid = item.uuid || getUUIDFromUrl(url);
                ext = item.ext;
                config = item.config;
            }
            var loader = getLoader(ext, url);
            return loader(url, uuid, true, config).then(function (res) {
                count++;
                progress && progress(count / total);
                return res;
            });
        }));
    }
    function loadAny(url, uuid, cache, config, options, type) {
        if (cache === void 0) { cache = true; }
        if (options === void 0) { options = {}; }
        if (type === void 0) { type = 'arraybuffer'; }
        return __awaiter(this, void 0, void 0, function () {
            var response, result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, fetch(resolveUrl(url), options)];
                    case 1:
                        response = _a.sent();
                        switch (type) {
                            case 'json':
                                result = response.json();
                                break;
                            case 'text':
                                result = response.text();
                                break;
                            case 'arraybuffer':
                                result = response.arrayBuffer();
                                break;
                            case 'blob':
                                result = response.blob();
                                break;
                        }
                        return [4, result];
                    case 2: return [2, _a.sent()];
                }
            });
        });
    }
    function loadTxt(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        var p = loadAny(url, uuid, cache, config, undefined, 'text');
        if (cache) {
            p.then(function (data) {
                cacheRes(data, url, uuid);
                return data;
            });
        }
        return p;
    }
    function loadJson(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        var p = loadAny(url, uuid, cache, config, undefined, 'json');
        if (cache) {
            p.then(function (data) {
                cacheRes(data, url, uuid);
                return data;
            });
        }
        return p;
    }
    function loadJson5(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return __awaiter(this, void 0, void 0, function () {
            var txt, jsonData;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadTxt(url, uuid)];
                    case 1:
                        txt = _a.sent();
                        jsonData = window['eval']("(" + txt + ")");
                        cacheRes(jsonData, url, uuid);
                        return [2, jsonData];
                }
            });
        });
    }
    function loadSheet(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        var pngFile = url.substring(0, url.lastIndexOf('.')) + '.png';
        return Promise.all([
            loadJson(url, null, false),
            loadImage(pngFile, null, false),
        ]).then(function (result) {
            var e_1, _a;
            var data = result[0];
            var img = result[1];
            var sheet = new Sheet(img, data.frames);
            sheet.generateAll();
            if (cache) {
                cacheRes(sheet, url, uuid);
                if (config) {
                    try {
                        for (var _b = __values(config.textures), _c = _b.next(); !_c.done; _c = _b.next()) {
                            var textureConfig = _c.value;
                            var name_1 = textureConfig.name, uuid_1 = textureConfig.uuid;
                            var texture = sheet.getTexture(name_1);
                            cacheRes(texture, name_1, uuid_1);
                        }
                    }
                    catch (e_1_1) { e_1 = { error: e_1_1 }; }
                    finally {
                        try {
                            if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                        }
                        finally { if (e_1) throw e_1.error; }
                    }
                }
                else {
                    var textures = sheet.getAllTextures();
                    for (var key in textures) {
                        cacheRes(textures[key], key, key);
                    }
                }
            }
            return sheet;
        });
    }
    function loadSheetDisperse(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return __awaiter(this, void 0, void 0, function () {
            var e_2, _a, _b, _c, _d, name_2, uuid_2, subUrl, e_2_1;
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0:
                        _e.trys.push([0, 5, 6, 7]);
                        _b = __values(config.textures), _c = _b.next();
                        _e.label = 1;
                    case 1:
                        if (!!_c.done) return [3, 4];
                        _d = _c.value, name_2 = _d.name, uuid_2 = _d.uuid;
                        subUrl = url.replace('-disperse', '') + '/' + name_2 + '.png';
                        return [4, loadTexture(subUrl, uuid_2)];
                    case 2:
                        _e.sent();
                        _e.label = 3;
                    case 3:
                        _c = _b.next();
                        return [3, 1];
                    case 4: return [3, 7];
                    case 5:
                        e_2_1 = _e.sent();
                        e_2 = { error: e_2_1 };
                        return [3, 7];
                    case 6:
                        try {
                            if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                        }
                        finally { if (e_2) throw e_2.error; }
                        return [7];
                    case 7: return [2, null];
                }
            });
        });
    }
    function loadFont(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return loadSheet(url, null, false).then(function (sheet) {
            if (cache) {
                cacheRes(sheet, url, uuid);
            }
            return sheet;
        });
    }
    function findAnimConfig(animations, name) {
        var result;
        animations.some(function (item) {
            if (item.name === name) {
                result = item;
                return true;
            }
        });
        return result;
    }
    function loadAnim(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        var pngFile = url.substring(0, url.lastIndexOf('.')) + '.png';
        return Promise.all([
            loadJson(url, null, false),
            loadImage(pngFile, null, false),
        ]).then(function (result) {
            var data = result[0];
            var img = result[1];
            putFrameAnim(img, data);
            var animations = [];
            for (var name_3 in data.mc) {
                var animation = getFrameAnimation(name_3);
                if (cache) {
                    var uuid_3 = name_3;
                    if (config) {
                        var cfg = findAnimConfig(config.animations, name_3);
                        uuid_3 = cfg.uuid;
                    }
                    cacheRes(animation, name_3, uuid_3);
                }
                animations.push(animation);
            }
            return animations;
        });
    }
    function loadImage(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return new Promise(function (resolve, reject) {
            var img = new Image();
            if (EngineConfig.imgCrossOrigin) {
                img.setAttribute('crossOrigin', 'anonymous');
            }
            img.onload = function (e) {
                resolve(img);
            };
            img.onerror = function (e) {
                reject(e);
            };
            img.src = resolveUrl(url);
        });
    }
    function loadImageFromBlob(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return __awaiter(this, void 0, void 0, function () {
            var imgBlob, e_3;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _a.trys.push([0, 3, , 4]);
                        return [4, loadAny(url, uuid, false, config, undefined, 'blob')];
                    case 1:
                        imgBlob = _a.sent();
                        return [4, blobToImage(imgBlob)];
                    case 2: return [2, _a.sent()];
                    case 3:
                        e_3 = _a.sent();
                        console.log(e_3);
                        return [3, 4];
                    case 4: return [2];
                }
            });
        });
    }
    function loadTexture(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return __awaiter(this, void 0, void 0, function () {
            var img, texture;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadImage(url, uuid, false)];
                    case 1:
                        img = _a.sent();
                        texture = createTexture(img);
                        if (cache) {
                            cacheRes(texture, url, uuid);
                        }
                        return [2, texture];
                }
            });
        });
    }
    function loadTextureFromBlob(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return __awaiter(this, void 0, void 0, function () {
            var img, texture;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadImageFromBlob(url, uuid, false)];
                    case 1:
                        img = _a.sent();
                        texture = createTexture(img);
                        if (cache) {
                            cacheRes(texture, url, uuid);
                        }
                        return [2, texture];
                }
            });
        });
    }
    function resolveUrl(url) {
        if (url.indexOf('//') === 0 || url.indexOf('http:') === 0 || url.indexOf('https:') === 0) {
            return url;
        }
        return resPath + url;
    }
    function getLoader(ext, url) {
        ext = ext || url.substr(url.lastIndexOf('.'));
        return resLoaderType[ext] || loadAny;
    }
    function getUUIDFromUrl(url) {
        return url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.'));
    }
    function cacheRes(res, url, uuid) {
        uuid = uuid || getUUIDFromUrl(url);
        resCache[uuid] = res;
    }
    function addLoader(ext, loader) {
        resLoaderType[ext] = loader;
    }
    function getRes(uuid) {
        return resCache[uuid];
    }
    function destroyRes(uuidOrUuids) {
        if (Array.isArray(uuidOrUuids)) {
            while (uuidOrUuids.length > 0) {
                delete resCache[uuidOrUuids.pop()];
            }
        }
        else {
            delete resCache[uuidOrUuids];
        }
    }
    function getAllResUuids() {
        return Object.keys(resCache);
    }
    function fileOrBlobToDataURL(obj) {
        return new Promise(function (resolve, reject) {
            var a = new FileReader();
            a.readAsDataURL(obj);
            a.onload = function (e) {
                resolve(e.target['result']);
            };
            a.onerror = function (e) {
                reject(e);
            };
        });
    }
    function blobToImage(blob) {
        return __awaiter(this, void 0, void 0, function () {
            var dataUrl;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, fileOrBlobToDataURL(blob)];
                    case 1:
                        dataUrl = _a.sent();
                        return [2, new Promise(function (resolve, reject) {
                                var img = new Image();
                                if (EngineConfig.imgCrossOrigin) {
                                    img.setAttribute('crossOrigin', 'anonymous');
                                }
                                img.onload = function () {
                                    resolve(img);
                                };
                                img.onerror = function (e) {
                                    reject(e);
                                };
                                img.src = dataUrl;
                            })];
                }
            });
        });
    }

    var Scene = (function () {
        function Scene() {
            this.resourceGroups = {
                preload: [],
                delay: [],
            };
        }
        Scene.prototype.initByConfig = function (config) {
            this.config = config;
            this.name = config.name;
            var resourceGroups = config['resource-groups'];
            for (var key in resourceGroups) {
                this.resourceGroups[key] = resourceGroups[key];
            }
        };
        Scene.prototype.loadResGroup = function (name, progress) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0: return [4, loadResItems(this.resourceGroups[name], progress)];
                        case 1:
                            _a.sent();
                            return [2];
                    }
                });
            });
        };
        return Scene;
    }());

    var ScillaEvent = (function () {
        function ScillaEvent() {
            this._subscribers = [];
        }
        ScillaEvent.prototype.findListener = function (callback) {
            var _subscribers = this._subscribers;
            var result;
            for (var i = 0, li = _subscribers.length; i < li; i++) {
                var subscriber = _subscribers[i];
                if (subscriber.callback == callback) {
                    result = {
                        subscriber: subscriber,
                        index: i,
                    };
                    break;
                }
            }
            return result;
        };
        ScillaEvent.prototype.addListener = function (callback, thisObj, priority) {
            if (priority === void 0) { priority = 0; }
            var params = [];
            for (var _i = 3; _i < arguments.length; _i++) {
                params[_i - 3] = arguments[_i];
            }
            if (!callback) {
                return;
            }
            var _subscribers = this._subscribers;
            var listener = this.findListener(callback);
            if (!listener) {
                _subscribers.push({
                    callback: callback,
                    thisObj: thisObj,
                    priority: priority,
                    params: params,
                });
            }
        };
        ScillaEvent.prototype.once = function (callback, thisObj, priority) {
            if (priority === void 0) { priority = 0; }
            var params = [];
            for (var _i = 3; _i < arguments.length; _i++) {
                params[_i - 3] = arguments[_i];
            }
            if (!callback) {
                return;
            }
            var _subscribers = this._subscribers;
            var listener = this.findListener(callback);
            if (!listener) {
                _subscribers.push({
                    callback: callback,
                    thisObj: thisObj,
                    priority: priority,
                    params: params,
                    once: true,
                });
            }
        };
        ScillaEvent.prototype.removeListener = function (callback) {
            if (!callback) {
                return;
            }
            var _subscribers = this._subscribers;
            var listener = this.findListener(callback);
            if (listener) {
                _subscribers.splice(listener.index, 1);
            }
        };
        ScillaEvent.prototype.hasListener = function (callback) {
            return !!this.findListener(callback);
        };
        ScillaEvent.prototype.invoke = function () {
            var paramsNew = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                paramsNew[_i] = arguments[_i];
            }
            var e_1, _a;
            var _subscribers = this._subscribers;
            _subscribers.sort(function (a, b) {
                return a.priority - b.priority;
            });
            try {
                for (var _subscribers_1 = __values(_subscribers), _subscribers_1_1 = _subscribers_1.next(); !_subscribers_1_1.done; _subscribers_1_1 = _subscribers_1.next()) {
                    var subscriber = _subscribers_1_1.value;
                    if (subscriber) {
                        var callback = subscriber.callback, thisObj = subscriber.thisObj, once = subscriber.once, params = subscriber.params;
                        var allParams = params.concat(paramsNew);
                        try {
                            callback.apply(thisObj, allParams);
                        }
                        catch (e) {
                            console.log(e);
                        }
                        if (once) {
                            this.removeListener(callback);
                        }
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (_subscribers_1_1 && !_subscribers_1_1.done && (_a = _subscribers_1.return)) _a.call(_subscribers_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
        };
        return ScillaEvent;
    }());

    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
            window[vendors[x] + 'CancelRequestAnimationFrame'];
    }
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function (callback) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
            var id = window.setTimeout(function () {
                callback(currTime + timeToCall);
            }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function (id) {
            clearTimeout(id);
        };
    }

    var options = {
        fps: 60,
        designWidth: 750,
        designHeight: 1334,
        scaleMode: ScaleMode.FIXED_WIDTH,
    };
    var root;
    var _flush = 0, _currentFlush = 0;
    var tsStart;
    function setup(_options) {
        injectProp(options, _options);
        var canvas = options.canvas, designWidth = options.designWidth, designHeight = options.designHeight, scaleMode = options.scaleMode, modifyCanvasSize = options.modifyCanvasSize;
        var canvasElement = typeof canvas == 'object' ? canvas : document.getElementById(canvas);
        setupContext({
            canvas: canvasElement,
            touchHandler: {
                onTouchBegin: onTouchBegin$1,
                onTouchMove: onTouchMove$1,
                onTouchEnd: onTouchEnd$1,
            }
        });
        setupContext$1({
            canvas: canvasElement,
            designWidth: designWidth,
            designHeight: designHeight,
            scaleMode: scaleMode,
            modifyCanvasSize: modifyCanvasSize,
        });
        root = new Entity('root');
        root._restrict();
    }
    function start() {
        root.enabled = true;
        tsStart = Date.now();
        startTick();
    }
    function pause() {
        root.enabled = false;
    }
    function getRoot() {
        return root;
    }
    function startTick() {
        _flush = 60 / options.fps - 1 >> 0;
        if (_flush < 0) {
            _flush = 0;
        }
        requestAnimationFrame(flush);
    }
    function flush(tsNow) {
        if (_flush == 0) {
            onFrameTick(tsNow);
        }
        else {
            if (_currentFlush == 0) {
                onFrameTick(tsNow);
                _currentFlush = _flush;
            }
            else {
                _currentFlush--;
            }
        }
        requestAnimationFrame(flush);
    }
    function onFrameTick(tsNow) {
        clear();
        var ts = tsNow - tsStart;
        traverse(root, function (child) {
            if (!child.isFree && child.enabled) {
                child.onUpdate(ts);
            }
            else {
                return true;
            }
        }, -1, true, function (current) {
            current.afterUpdate();
        });
    }
    function onTouchBegin$1(event) {
        traversePostorder(root, function (child) {
            return child.onInteract(0, event);
        });
    }
    function onTouchMove$1(event) {
        traversePostorder(root, function (child) {
            return child.onInteract(1, event);
        });
    }
    function onTouchEnd$1(event) {
        traversePostorder(root, function (child) {
            return child.onInteract(2, event);
        });
    }

    var entityCache = {};
    var entityCacheConfig;
    var defMap = {};
    function registerDef(name, def) {
        defMap[name] = def;
        def.__class__ = name;
    }
    function getEntityCacheConfig(config) {
        return config['entity-cache'] ? config['entity-cache'].concat() : [];
    }
    function setupScene(scene, root) {
        scene.root = root;
        var config = scene.config;
        entityCacheConfig = getEntityCacheConfig(config);
        instantiateConfig(config.root, root);
        entityCache = {};
        return scene;
    }
    function destroyScene(scene) {
        var root = scene.root;
        root.removeAllComponents();
        root.removeChildren();
    }
    function instantiateConfig(config, root) {
        var entity = setupEntity(config, root);
        setupComponent(config, entity, true);
        injectComponent(config, entity, true);
        return entity;
    }
    function setupEntity(config, root, pid) {
        var entity = null;
        if (config) {
            var name_1 = config.name, uuid = config.uuid, children = config.children;
            if (pid !== undefined && uuid !== undefined) {
                uuid = pid + '_' + uuid;
            }
            entity = root || new Entity(name_1, uuid);
            if (entityCacheConfig.indexOf(uuid) >= 0) {
                entityCache[uuid] = entity;
            }
            if (children) {
                for (var i = 0, li = children.length; i < li; i++) {
                    var child = children[i];
                    var childEntity = setupEntity(child, null, pid);
                    entity.addChild(childEntity);
                }
            }
            if (!root) {
                entity.enabled = !config.disabled;
            }
        }
        return entity;
    }
    function setupComponent(config, root, includeSelf) {
        if (includeSelf === void 0) { includeSelf = false; }
        if (includeSelf) {
            instantiateComponents(root, config);
        }
        if (config && config.children) {
            for (var i = 0, li = root.children.length; i < li; i++) {
                var child = config.children[i];
                var entity = root.children[i];
                instantiateComponents(entity, child);
                setupComponent(child, entity);
            }
        }
    }
    function injectComponent(config, root, includeSelf, pid) {
        if (includeSelf === void 0) { includeSelf = false; }
        if (includeSelf) {
            injectComponents(root, config, pid);
        }
        if (config && config.children) {
            for (var i = 0, li = root.children.length; i < li; i++) {
                var child = config.children[i];
                var entity = root.children[i];
                injectComponents(entity, child, pid);
                injectComponent(child, entity, false, pid);
            }
        }
    }
    function instantiateComponents(entity, config) {
        var e_1, _a;
        if (config.components) {
            try {
                for (var _b = __values(config.components), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var component = _c.value;
                    instantiateComponent(entity, component);
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_1) throw e_1.error; }
            }
        }
    }
    function injectComponents(entity, config, pid) {
        if (config.components) {
            var components = entity.components;
            for (var i = 0, li = config.components.length; i < li; i++) {
                var component = config.components[i];
                var properties = component.properties;
                if (properties) {
                    injectProperties(components[i], properties, pid);
                }
            }
        }
    }
    function instantiateComponent(entity, config) {
        var script = config.script, properties = config.properties;
        var def = getDefByName(script);
        if (!def) {
            return;
        }
        var instance = new def();
        instance.enabled = !config.disabled;
        entity.addComponent(instance);
    }
    function getDefByName(name) {
        var def;
        def = defMap[name];
        if (!def) {
            console.warn('missing def:', name);
            return;
        }
        return def;
    }
    var skipKeys = ['_type_', '_constructor_'];
    function injectProperties(node, propertiesConfig, pid) {
        if (!node) {
            console.warn('node is null.');
            return;
        }
        for (var key in propertiesConfig) {
            if (skipKeys.indexOf(key) >= 0) {
                continue;
            }
            var propertyOfConfig = propertiesConfig[key];
            var propertyOfInstance = node[key];
            if (typeof propertyOfConfig === 'object') {
                if (propertyOfInstance instanceof ScillaEvent) {
                    injectEvent(propertyOfInstance, propertyOfConfig, pid);
                }
                else if (propertyOfConfig._type_ === 'raw') {
                    node[key] = propertyOfInstance = propertyOfConfig.data;
                }
                else {
                    if (Array.isArray(propertyOfConfig) && !propertyOfInstance) {
                        node[key] = propertyOfInstance = [];
                    }
                    node[key] = injectObject(propertyOfInstance, propertyOfConfig, pid);
                }
            }
            else {
                injectBaseType(node, key, propertyOfConfig, pid);
            }
        }
    }
    function injectObject(propertyOfInstance, propertyOfConfig, pid) {
        if (propertyOfInstance === undefined) {
            if (propertyOfConfig._type_) {
                var def = getDefByName(propertyOfConfig._type_);
                if (def) {
                    var constructorArgs = propertyOfConfig._constructor_;
                    if (constructorArgs && constructorArgs.length > 0) {
                        propertyOfInstance = def.constructor.apply(null, constructorArgs);
                    }
                    else {
                        propertyOfInstance = new def();
                    }
                }
            }
        }
        if (propertyOfInstance) {
            injectProperties(propertyOfInstance, propertyOfConfig, pid);
        }
        return propertyOfInstance;
    }
    function injectBaseType(node, key, propertyOfConfig, pid) {
        var propertyValue;
        if (typeof propertyOfConfig === 'string') {
            propertyValue = getLink(propertyOfConfig, pid);
        }
        else {
            propertyValue = propertyOfConfig;
        }
        node[key] = propertyValue;
    }
    function injectEvent(event, config, pid) {
        var e_2, _a;
        try {
            for (var config_1 = __values(config), config_1_1 = config_1.next(); !config_1_1.done; config_1_1 = config_1.next()) {
                var _b = config_1_1.value, entityName = _b.entity, componentIndex = _b.component, methodName = _b.method, param = _b.param;
                if (entityName && componentIndex >= 0 && methodName) {
                    var entity = getLink(entityName, pid);
                    var component = entity.components[componentIndex];
                    var method = component[methodName];
                    if (method) {
                        if (param == undefined) {
                            event.addListener(method, component, 0);
                        }
                        else {
                            event.addListener(method, component, 0, param);
                        }
                    }
                }
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (config_1_1 && !config_1_1.done && (_a = config_1.return)) _a.call(config_1);
            }
            finally { if (e_2) throw e_2.error; }
        }
    }
    function getLink(str, pid) {
        var result;
        if (str.indexOf('res|') == 0) {
            var uuid = str.substr(4);
            result = getRes(uuid);
        }
        else if (str.indexOf('entity|') == 0) {
            var uuid = transPrefabUUID(str.substr(7), pid);
            result = entityCache[uuid];
        }
        else {
            result = str;
        }
        return result;
    }
    function transPrefabUUID(uuid, pid) {
        return pid ? pid + '_' + uuid : uuid;
    }

    var currentScene;
    var resUUIDs;
    function launchScene(name, progress) {
        return __awaiter(this, void 0, void 0, function () {
            var scene;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadScene("scenes/" + name + ".scene", 'scene_' + name)];
                    case 1:
                        scene = _a.sent();
                        resUUIDs = getAllResUuids();
                        return [4, scene.loadResGroup('preload', progress)];
                    case 2:
                        _a.sent();
                        if (currentScene) {
                            unmountScene(currentScene);
                        }
                        currentScene = scene;
                        mountScene(scene);
                        scene.loadResGroup('delay', progress);
                        return [2];
                }
            });
        });
    }
    function mountScene(scene) {
        pause();
        setupScene(scene, getRoot());
        start();
    }
    function unmountScene(scene) {
        pause();
        destroyScene(scene);
        destroyRes(resUUIDs);
    }
    function loadScene(url, uuid, cache, config) {
        if (cache === void 0) { cache = false; }
        return __awaiter(this, void 0, void 0, function () {
            var sceneConfig, scene;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadJson5(url)];
                    case 1:
                        sceneConfig = _a.sent();
                        scene = new Scene();
                        scene.initByConfig(sceneConfig);
                        return [2, scene];
                }
            });
        });
    }
    function loadPrefab(url, uuid, cache, config) {
        if (cache === void 0) { cache = true; }
        return __awaiter(this, void 0, void 0, function () {
            var data;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadJson5(url, uuid, false)];
                    case 1:
                        data = _a.sent();
                        cacheRes(data, url, uuid);
                        return [2, data];
                }
            });
        });
    }
    addLoader('.pfb', loadPrefab);

    var all = {};
    function getGroup(name) {
        var group = all[name];
        if (!group) {
            throw new Error('group ' + name + ' not registered.');
        }
        return group;
    }
    function register(name, newFunc, initFunc) {
        all[name] = { name: name, newFunc: newFunc, initFunc: initFunc, pool: [] };
    }
    function get(name) {
        var params = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            params[_i - 1] = arguments[_i];
        }
        var group = getGroup(name);
        var newFunc = group.newFunc, initFunc = group.initFunc, pool = group.pool;
        var instance;
        if (pool.length == 0) {
            instance = newFunc();
        }
        else {
            instance = pool.pop();
        }
        initFunc.apply(void 0, __spread([instance], params));
        return instance;
    }

    var name = 'Vector2D';
    register(name, function () {
        return new Vector2D();
    }, function (instance, x, y) {
        instance.setXY(x, y);
    });
    function createVector2D(x, y) {
        if (x === void 0) { x = 0; }
        if (y === void 0) { y = 0; }
        return get(name, x, y);
    }
    var Vector2D = (function () {
        function Vector2D(x, y, onChange) {
            if (x === void 0) { x = 0; }
            if (y === void 0) { y = 0; }
            this.onChange = onChange;
            this._x = 0;
            this._y = 0;
            this.setXY(x, y);
        }
        Object.defineProperty(Vector2D, "zero", {
            get: function () {
                return zero;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Vector2D.prototype, "x", {
            get: function () {
                return this._x;
            },
            set: function (v) {
                if (this._x !== v) {
                    var old = this._x;
                    this._x = v;
                    this.onChange && this.onChange(v, 'x', old);
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Vector2D.prototype, "y", {
            get: function () {
                return this._y;
            },
            set: function (v) {
                if (this._y !== v) {
                    var old = this._y;
                    this._y = v;
                    this.onChange && this.onChange(v, 'y', old);
                }
            },
            enumerable: true,
            configurable: true
        });
        Vector2D.prototype.setXY = function (x, y) {
            if (x === void 0) { x = 0; }
            if (y === void 0) { y = 0; }
            this.x = x;
            this.y = y;
            return this;
        };
        Vector2D.prototype.copyFrom = function (v2) {
            this.x = v2.x;
            this.y = v2.y;
            return this;
        };
        Vector2D.prototype.clone = function () {
            return new Vector2D(this.x, this.y);
        };
        Vector2D.prototype.zero = function () {
            this.x = 0;
            this.y = 0;
            return this;
        };
        Object.defineProperty(Vector2D.prototype, "isZero", {
            get: function () {
                return this.x == 0 && this.y == 0;
            },
            enumerable: true,
            configurable: true
        });
        Vector2D.prototype.normalize = function () {
            var len = this.length;
            if (len == 0) {
                this.x = 1;
                return this;
            }
            this.x /= len;
            this.y /= len;
            return this;
        };
        Object.defineProperty(Vector2D.prototype, "isNormalized", {
            get: function () {
                return this.length == 1.0;
            },
            enumerable: true,
            configurable: true
        });
        Vector2D.prototype.truncate = function (max) {
            this.length = Math.min(max, this.length);
            return this;
        };
        Vector2D.prototype.reverse = function () {
            this.x = -this.x;
            this.y = -this.y;
            return this;
        };
        Vector2D.prototype.dotProd = function (v2) {
            return this.x * v2.x + this.y * v2.y;
        };
        Vector2D.prototype.crossProd = function (v2) {
            return this.x * v2.y - this.y * v2.x;
        };
        Vector2D.prototype.distSQ = function (v2) {
            var dx = v2.x - this.x;
            var dy = v2.y - this.y;
            return dx * dx + dy * dy;
        };
        Vector2D.prototype.distance = function (v2) {
            return Math.sqrt(this.distSQ(v2));
        };
        Vector2D.prototype.add = function (v2) {
            this.x += v2.x;
            this.y += v2.y;
            return this;
        };
        Vector2D.prototype.subtract = function (v2) {
            this.x -= v2.x;
            this.y -= v2.y;
            return this;
        };
        Vector2D.prototype.multiply = function (value) {
            this.x *= value;
            this.y *= value;
            return this;
        };
        Vector2D.prototype.divide = function (value) {
            this.x /= value;
            this.y /= value;
            return this;
        };
        Object.defineProperty(Vector2D.prototype, "angle", {
            get: function () {
                return this.radian * 180 / Math.PI;
            },
            set: function (value) {
                this.radian = value * Math.PI / 180;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Vector2D.prototype, "radian", {
            get: function () {
                return Math.atan2(this.y, this.x);
            },
            set: function (value) {
                var len = this.length;
                this.setXY(Math.cos(value) * len, Math.sin(value) * len);
            },
            enumerable: true,
            configurable: true
        });
        Vector2D.prototype.equals = function (v2) {
            return this.x == v2.x && this.y == v2.y;
        };
        Object.defineProperty(Vector2D.prototype, "length", {
            get: function () {
                return Math.sqrt(this.lengthSQ);
            },
            set: function (value) {
                var a = this.radian;
                this.setXY(Math.cos(a) * value, Math.sin(a) * value);
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Vector2D.prototype, "lengthSQ", {
            get: function () {
                return this.x * this.x + this.y * this.y;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Vector2D.prototype, "slope", {
            get: function () {
                return this.y / this.x;
            },
            enumerable: true,
            configurable: true
        });
        Vector2D.prototype.toString = function () {
            return "[Vector2D (x:" + this.x + ", y:" + this.y + ")]";
        };
        Vector2D.corner = function (v1, v2) {
            return Math.acos(v1.dotProd(v2) / (v1.length * v2.length));
        };
        return Vector2D;
    }());
    var zero = new Vector2D();

    function lerp(begin, end, t, allowOutOfBounds) {
        if (allowOutOfBounds === void 0) { allowOutOfBounds = false; }
        var type = typeof begin;
        if (type !== typeof end) {
            console.error('begin and end need same type');
        }
        if (!allowOutOfBounds) {
            t = Math.max(0, Math.min(1, t));
        }
        var sign = end - begin;
        sign = sign > 0 ? 1 : (sign < 0 ? -1 : 0);
        var distance = Math.abs(end - begin);
        return begin + distance * t * sign;
    }
    function lerpObj(begin, end, t, clazz, fields, allowOutOfBounds) {
        if (allowOutOfBounds === void 0) { allowOutOfBounds = false; }
        var e_1, _a;
        var type = typeof begin;
        if (type !== typeof end) {
            console.error('begin and end need same type');
        }
        var temp = new clazz();
        try {
            for (var fields_1 = __values(fields), fields_1_1 = fields_1.next(); !fields_1_1.done; fields_1_1 = fields_1.next()) {
                var field = fields_1_1.value;
                temp[field] = lerp(begin[field], end[field], t, allowOutOfBounds);
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (fields_1_1 && !fields_1_1.done && (_a = fields_1.return)) _a.call(fields_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        return temp;
    }
    function makeRandomInt(max, min) {
        if (min === void 0) { min = 0; }
        return Math.floor(Math.random() * (max - min)) + min;
    }

    var STATUS;
    (function (STATUS) {
        STATUS[STATUS["IDLE"] = 0] = "IDLE";
        STATUS[STATUS["PENDING"] = 1] = "PENDING";
        STATUS[STATUS["DO_SET"] = 2] = "DO_SET";
        STATUS[STATUS["DO_TO"] = 3] = "DO_TO";
        STATUS[STATUS["DO_WAIT"] = 4] = "DO_WAIT";
        STATUS[STATUS["DO_CALL"] = 5] = "DO_CALL";
    })(STATUS || (STATUS = {}));
    function createTween(target, override, options, plugins) {
        if (override === void 0) { override = false; }
        if (plugins === void 0) { plugins = []; }
        if (override) {
            killTweens(target);
        }
        var tween = new Tween(target, options);
        addTween(target, tween);
        return tween;
    }
    function killTweens(target) {
        var e_1, _a;
        var tweens = target['tweens'];
        if (tweens) {
            try {
                for (var tweens_1 = __values(tweens), tweens_1_1 = tweens_1.next(); !tweens_1_1.done; tweens_1_1 = tweens_1.next()) {
                    var tween = tweens_1_1.value;
                    tween.stop();
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (tweens_1_1 && !tweens_1_1.done && (_a = tweens_1.return)) _a.call(tweens_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            tweens.splice(0);
        }
    }
    function addTween(target, tween) {
        var tweens = target['tweens'];
        if (!tweens) {
            tweens = target['tweens'] = [];
        }
        tweens.push(tween);
    }
    var Tween = (function (_super) {
        __extends(Tween, _super);
        function Tween(target, options, plugins) {
            if (plugins === void 0) { plugins = []; }
            var _this = _super.call(this) || this;
            _this.queue = [];
            _this.loopCounting = 0;
            _this.status = STATUS.IDLE;
            _this.onUpdate = function (t) {
                _this.t = t;
                switch (_this.status) {
                    case STATUS.DO_TO:
                        var _a = _this, target = _a.target, startTime = _a.startTime, fromProps = _a.fromProps, toProps = _a.toProps, duration = _a.duration, ease = _a.ease, clazz = _a.clazz, fields = _a.fields;
                        var passTime = t - startTime;
                        var timeRatio = Math.min(1, passTime / duration);
                        var ratio = timeRatio;
                        if (ease) {
                            ratio = ease(ratio);
                        }
                        for (var key in fromProps) {
                            var toValue = toProps[key];
                            var fromValue = fromProps[key];
                            var currentValue = void 0;
                            if (timeRatio < 1) {
                                if (typeof toValue == 'object') {
                                    currentValue = lerpObj(fromValue, toValue, ratio, clazz, fields || Object.keys(toValue), true);
                                }
                                else {
                                    currentValue = lerp(fromValue, toValue, ratio, true);
                                }
                            }
                            else {
                                currentValue = toValue;
                            }
                            target[key] = currentValue;
                            if (timeRatio >= 1) {
                                _this._doNextAction();
                            }
                        }
                        break;
                    case STATUS.DO_WAIT:
                        var _b = _this, startTime = _b.startTime, duration = _b.duration;
                        var passTime = t - startTime;
                        if (passTime > duration) {
                            _this._doNextAction();
                        }
                        break;
                }
            };
            _this._doPlay = function (resetLoopCounting) {
                addTween(_this.target, _this);
                _this._start(resetLoopCounting);
            };
            _this._readyStart = function (t) {
                _this.t = t;
                _this._doStart();
            };
            _this._doNextAction = function () {
                if (_this.step < _this.queue.length) {
                    var action = _this.queue[_this.step++];
                    switch (action.action) {
                        case 'set':
                            _this._set(action.props);
                            break;
                        case 'to':
                            if (action.duration > 0) {
                                _this._to(action.props, action.duration, action.ease);
                            }
                            else {
                                _this._set(action.props);
                            }
                            break;
                        case 'wait':
                            _this._wait(action.duration);
                            break;
                        case 'call':
                            _this._call(action.func, action.thisObj, action.params);
                            break;
                    }
                }
                else {
                    if (_this.loop < 0) {
                        _this._doStart();
                    }
                    else if (_this.loopCounting < _this.loop) {
                        _this._doStart();
                    }
                    else {
                        _this.status = STATUS.IDLE;
                    }
                }
            };
            _this.target = target;
            _this.loop = options ? options.loop : 0;
            _this.autoPlay = options ? (options.hasOwnProperty('autoPlay') ? options.autoPlay : true) : true;
            _this.clazz = options ? options.clazz : null;
            _this.fields = options ? options.fields : null;
            _this.plugins = plugins;
            if (options && options.initFields && options.initFields.length > 0) {
                _this.initProps = _this.getInitProps(options.initFields);
            }
            return _this;
        }
        Tween.prototype.getInitProps = function (fields) {
            var e_2, _a;
            var props = {};
            try {
                for (var fields_1 = __values(fields), fields_1_1 = fields_1.next(); !fields_1_1.done; fields_1_1 = fields_1.next()) {
                    var field = fields_1_1.value;
                    if (field in this.target) {
                        props[field] = this.target[field];
                    }
                }
            }
            catch (e_2_1) { e_2 = { error: e_2_1 }; }
            finally {
                try {
                    if (fields_1_1 && !fields_1_1.done && (_a = fields_1.return)) _a.call(fields_1);
                }
                finally { if (e_2) throw e_2.error; }
            }
            return props;
        };
        Tween.prototype.set = function (props) {
            this.queue.push({ action: 'set', props: props });
            if (this.autoPlay) {
                this._start();
            }
            return this;
        };
        Tween.prototype.to = function (props, duration, ease) {
            this.queue.push({ action: 'to', props: props, duration: duration, ease: ease });
            if (this.autoPlay) {
                this._start();
            }
            return this;
        };
        Tween.prototype.wait = function (duration) {
            this.queue.push({ action: 'wait', duration: duration });
            if (this.autoPlay) {
                this._start();
            }
            return this;
        };
        Tween.prototype.call = function (func, thisObj, params) {
            this.queue.push({ action: 'call', func: func, thisObj: thisObj, params: params });
            if (this.autoPlay) {
                this._start();
            }
            return this;
        };
        Tween.prototype.play = function (override, delay, resetLoopCounting) {
            if (override === void 0) { override = false; }
            if (delay === void 0) { delay = 0; }
            if (resetLoopCounting === void 0) { resetLoopCounting = true; }
            if (override) {
                killTweens(this.target);
            }
            if (delay > 0) {
                setTimeout(this._doPlay, delay, resetLoopCounting);
            }
            else {
                this._doPlay(resetLoopCounting);
            }
        };
        Tween.prototype.stop = function () {
            this.status = STATUS.IDLE;
            this.target.cancelOnNextTick(this.onUpdate);
        };
        Tween.prototype._set = function (props) {
            this.status = STATUS.DO_SET;
            injectProp(this.target, props);
            this._doNextAction();
        };
        Tween.prototype._to = function (props, duration, ease) {
            this.status = STATUS.DO_TO;
            this.startTime = this.t;
            this.fromProps = {};
            for (var key in props) {
                this.fromProps[key] = this.target[key];
            }
            this.toProps = {};
            injectProp(this.toProps, props);
            this.ease = ease;
            this.duration = duration;
        };
        Tween.prototype._wait = function (duration) {
            this.status = STATUS.DO_WAIT;
            this.startTime = this.t;
            this.duration = duration;
        };
        Tween.prototype._call = function (func, thisObj, params) {
            this.status = STATUS.DO_CALL;
            func.apply(thisObj, params);
            this._doNextAction();
        };
        Tween.prototype._start = function (resetLoopCounting) {
            if (resetLoopCounting === void 0) { resetLoopCounting = true; }
            this.status = STATUS.PENDING;
            if (resetLoopCounting) {
                this.loopCounting = 0;
            }
            this.target.callOnNextTick(this._readyStart);
            this.target.callOnNextTick(this.onUpdate, false);
        };
        Tween.prototype._doStart = function () {
            if (this.status == STATUS.IDLE) {
                return;
            }
            this.step = 0;
            this.loopCounting++;
            if (this.loopCounting > 1 && this.initProps) {
                injectProp(this.target, this.initProps);
            }
            this._doNextAction();
        };
        return Tween;
    }(HashObject));

    var PI = Math.PI;
    var TwoPI = PI * 2;
    var DEG_TO_RAD = PI / 180;
    var matrixPool = [];
    var Matrix = (function () {
        function Matrix(a, b, c, d, tx, ty) {
            if (a === void 0) { a = 1; }
            if (b === void 0) { b = 0; }
            if (c === void 0) { c = 0; }
            if (d === void 0) { d = 1; }
            if (tx === void 0) { tx = 0; }
            if (ty === void 0) { ty = 0; }
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
            this.tx = tx;
            this.ty = ty;
        }
        Matrix.release = function (matrix) {
            if (!matrix) {
                return;
            }
            matrixPool.push(matrix);
        };
        Matrix.create = function () {
            var matrix = matrixPool.pop();
            if (!matrix) {
                matrix = new Matrix();
            }
            return matrix;
        };
        Matrix.prototype.clone = function () {
            var m = Matrix.create();
            m.setTo(this.a, this.b, this.c, this.d, this.tx, this.ty);
            return m;
        };
        Matrix.prototype.concat = function (other) {
            var a = this.a * other.a;
            var b = 0.0;
            var c = 0.0;
            var d = this.d * other.d;
            var tx = this.tx * other.a + other.tx;
            var ty = this.ty * other.d + other.ty;
            if (this.b !== 0.0 || this.c !== 0.0 || other.b !== 0.0 || other.c !== 0.0) {
                a += this.b * other.c;
                d += this.c * other.b;
                b += this.a * other.b + this.b * other.d;
                c += this.c * other.a + this.d * other.c;
                tx += this.ty * other.c;
                ty += this.tx * other.b;
            }
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
            this.tx = tx;
            this.ty = ty;
        };
        Matrix.prototype.copyFrom = function (other) {
            this.a = other.a;
            this.b = other.b;
            this.c = other.c;
            this.d = other.d;
            this.tx = other.tx;
            this.ty = other.ty;
            return this;
        };
        Matrix.prototype.identity = function () {
            this.a = this.d = 1;
            this.b = this.c = this.tx = this.ty = 0;
        };
        Matrix.prototype.invert = function () {
            this.$invertInto(this);
        };
        Matrix.prototype.$invertInto = function (target) {
            var a = this.a;
            var b = this.b;
            var c = this.c;
            var d = this.d;
            var tx = this.tx;
            var ty = this.ty;
            if (b == 0 && c == 0) {
                target.b = target.c = 0;
                if (a == 0 || d == 0) {
                    target.a = target.d = target.tx = target.ty = 0;
                }
                else {
                    a = target.a = 1 / a;
                    d = target.d = 1 / d;
                    target.tx = -a * tx;
                    target.ty = -d * ty;
                }
                return;
            }
            var determinant = a * d - b * c;
            if (determinant == 0) {
                target.identity();
                return;
            }
            determinant = 1 / determinant;
            var k = target.a = d * determinant;
            b = target.b = -b * determinant;
            c = target.c = -c * determinant;
            d = target.d = a * determinant;
            target.tx = -(k * tx + c * ty);
            target.ty = -(b * tx + d * ty);
        };
        Matrix.prototype.rotate = function (radian) {
            radian = +radian;
            if (radian !== 0) {
                var u = Math.cos(radian);
                var v = Math.sin(radian);
                var _a = this, a = _a.a, b = _a.b, c = _a.c, d = _a.d, tx = _a.tx, ty = _a.ty;
                this.a = a * u - b * v;
                this.b = a * v + b * u;
                this.c = c * u - d * v;
                this.d = c * v + d * u;
                this.tx = tx * u - ty * v;
                this.ty = tx * v + ty * u;
            }
        };
        Matrix.prototype.scale = function (sx, sy) {
            if (sx !== 1) {
                this.a *= sx;
                this.c *= sx;
                this.tx *= sx;
            }
            if (sy !== 1) {
                this.b *= sy;
                this.d *= sy;
                this.ty *= sy;
            }
        };
        Matrix.prototype.setTo = 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;
            return this;
        };
        Matrix.prototype.transformPoint = function (pointX, pointY, resultPoint) {
            var _a = this, a = _a.a, b = _a.b, c = _a.c, d = _a.d, tx = _a.tx, ty = _a.ty;
            var x = a * pointX + c * pointY + tx;
            var y = b * pointX + d * pointY + ty;
            if (resultPoint) {
                resultPoint.x = x;
                resultPoint.y = y;
                return resultPoint;
            }
            return { x: x, y: y };
        };
        Matrix.prototype.deltaTransformPoint = function (pointX, pointY, resultPoint) {
            var _a = this, a = _a.a, b = _a.b, c = _a.c, d = _a.d;
            var x = a * pointX + c * pointY;
            var y = b * pointX + d * pointY;
            if (resultPoint) {
                resultPoint.x = x;
                resultPoint.y = y;
                return resultPoint;
            }
            return { x: x, y: y };
        };
        Matrix.prototype.translate = function (dx, dy) {
            this.tx += dx;
            this.ty += dy;
        };
        Matrix.prototype.equals = function (other) {
            return this.a == other.a && this.b == other.b &&
                this.c == other.c && this.d == other.d &&
                this.tx == other.tx && this.ty == other.ty;
        };
        Matrix.prototype.prepend = function (a, b, c, d, tx, ty) {
            var tx1 = this.tx;
            if (a != 1 || b != 0 || c != 0 || d != 1) {
                var a1 = this.a;
                var c1 = this.c;
                this.a = a1 * a + this.b * c;
                this.b = a1 * b + this.b * d;
                this.c = c1 * a + this.d * c;
                this.d = c1 * b + this.d * d;
            }
            this.tx = tx1 * a + this.ty * c + tx;
            this.ty = tx1 * b + this.ty * d + ty;
            return this;
        };
        Matrix.prototype.append = function (a, b, c, d, tx, ty) {
            var a1 = this.a;
            var b1 = this.b;
            var c1 = this.c;
            var d1 = this.d;
            if (a != 1 || b != 0 || c != 0 || d != 1) {
                this.a = a * a1 + b * c1;
                this.b = a * b1 + b * d1;
                this.c = c * a1 + d * c1;
                this.d = c * b1 + d * d1;
            }
            this.tx = tx * a1 + ty * c1 + this.tx;
            this.ty = tx * b1 + ty * d1 + this.ty;
            return this;
        };
        Matrix.prototype.toString = function () {
            return "(a=" + this.a + ", b=" + this.b + ", c=" + this.c + ", d=" + this.d + ", tx=" + this.tx + ", ty=" + this.ty + ")";
        };
        Matrix.prototype.createBox = function (scaleX, scaleY, rotation, tx, ty) {
            if (rotation === void 0) { rotation = 0; }
            if (tx === void 0) { tx = 0; }
            if (ty === void 0) { ty = 0; }
            var self = this;
            if (rotation !== 0) {
                rotation = rotation / DEG_TO_RAD;
                var u = Math.cos(rotation);
                var v = Math.sin(rotation);
                self.a = u * scaleX;
                self.b = v * scaleY;
                self.c = -v * scaleX;
                self.d = u * scaleY;
            }
            else {
                self.a = scaleX;
                self.b = 0;
                self.c = 0;
                self.d = scaleY;
            }
            self.tx = tx;
            self.ty = ty;
        };
        Matrix.prototype.createGradientBox = function (width, height, rotation, tx, ty) {
            if (rotation === void 0) { rotation = 0; }
            if (tx === void 0) { tx = 0; }
            if (ty === void 0) { ty = 0; }
            this.createBox(width / 1638.4, height / 1638.4, rotation, tx + width / 2, ty + height / 2);
        };
        Matrix.prototype.$transformBounds = function (bounds) {
            var a = this.a;
            var b = this.b;
            var c = this.c;
            var d = this.d;
            var tx = this.tx;
            var ty = this.ty;
            var x = bounds.x;
            var y = bounds.y;
            var xMax = x + bounds.width;
            var yMax = y + bounds.height;
            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;
            }
            bounds.x = Math.floor(x0 < x2 ? x0 : x2);
            bounds.width = Math.ceil((x1 > x3 ? x1 : x3) - bounds.x);
            if (y0 > y1) {
                tmp = y0;
                y0 = y1;
                y1 = tmp;
            }
            if (y2 > y3) {
                tmp = y2;
                y2 = y3;
                y3 = tmp;
            }
            bounds.y = Math.floor(y0 < y2 ? y0 : y2);
            bounds.height = Math.ceil((y1 > y3 ? y1 : y3) - bounds.y);
        };
        Matrix.prototype.getDeterminant = function () {
            return this.a * this.d - this.b * this.c;
        };
        Matrix.prototype.$getScaleX = function () {
            var m = this;
            if (m.b == 0) {
                return m.a;
            }
            var result = Math.sqrt(m.a * m.a + m.b * m.b);
            return this.getDeterminant() < 0 ? -result : result;
        };
        Matrix.prototype.$getScaleY = function () {
            var m = this;
            if (m.c == 0) {
                return m.d;
            }
            var result = Math.sqrt(m.c * m.c + m.d * m.d);
            return this.getDeterminant() < 0 ? -result : result;
        };
        Matrix.prototype.$getSkewX = function () {
            if (this.d < 0) {
                return Math.atan2(this.d, this.c) + (PI / 2);
            }
            else {
                return Math.atan2(this.d, this.c) - (PI / 2);
            }
        };
        Matrix.prototype.$getSkewY = function () {
            if (this.a < 0) {
                return Math.atan2(this.b, this.a) - PI;
            }
            else {
                return Math.atan2(this.b, this.a);
            }
        };
        Matrix.prototype.$updateScaleAndRotation = function (scaleX, scaleY, skewX, skewY) {
            if ((skewX == 0 || skewX == TwoPI) && (skewY == 0 || skewY == TwoPI)) {
                this.a = scaleX;
                this.b = this.c = 0;
                this.d = scaleY;
                return;
            }
            skewX = skewX / DEG_TO_RAD;
            skewY = skewY / DEG_TO_RAD;
            var u = Math.cos(skewX);
            var v = Math.sin(skewX);
            if (skewX == skewY) {
                this.a = u * scaleX;
                this.b = v * scaleX;
            }
            else {
                this.a = Math.cos(skewY) * scaleX;
                this.b = Math.sin(skewY) * scaleX;
            }
            this.c = -v * scaleY;
            this.d = u * scaleY;
        };
        Matrix.prototype.$preMultiplyInto = function (other, target) {
            var a = other.a * this.a;
            var b = 0.0;
            var c = 0.0;
            var d = other.d * this.d;
            var tx = other.tx * this.a + this.tx;
            var ty = other.ty * this.d + this.ty;
            if (other.b !== 0.0 || other.c !== 0.0 || this.b !== 0.0 || this.c !== 0.0) {
                a += other.b * this.c;
                d += other.c * this.b;
                b += other.a * this.b + other.b * this.d;
                c += other.c * this.a + other.d * this.c;
                tx += other.ty * this.c;
                ty += other.tx * this.b;
            }
            target.a = a;
            target.b = b;
            target.c = c;
            target.d = d;
            target.tx = tx;
            target.ty = ty;
        };
        return Matrix;
    }());

    function fieldChanged(onChange) {
        return function (target, key) {
            var privateKey = '_' + key;
            Object.defineProperty(target, key, {
                enumerable: true,
                get: function () {
                    return this[privateKey];
                },
                set: function (v) {
                    var oldValue = this[privateKey];
                    if (oldValue !== v) {
                        this[privateKey] = v;
                        onChange.apply(this, [v, key, oldValue]);
                    }
                }
            });
        };
    }
    var dirtyFieldDetector = fieldChanged(function (value, key, oldValue) {
        this['dirty'] = true;
    });
    var dirtyFieldTrigger = fieldChanged(function (value, key, oldValue) {
        this['onModify'] && this['onModify'](value, key, oldValue);
    });

    var Size = (function () {
        function Size(width, height) {
            if (width === void 0) { width = NaN; }
            if (height === void 0) { height = NaN; }
            this.width = width;
            this.height = height;
        }
        Size.prototype.setNaN = function () {
            this.width = NaN;
            this.height = NaN;
        };
        Size.prototype.isEmpty = function () {
        };
        Size.prototype.set = function (width, height) {
            if (width !== undefined) {
                this.width = width;
            }
            if (height !== undefined) {
                this.height = height;
            }
        };
        Size.prototype.clone = function () {
            return new Size(this.width, this.height);
        };
        Size.prototype.copyFrom = function (target) {
            this.width = target.width;
            this.height = target.height;
        };
        Size.prototype.onModify = function (value, key, oldValue) {
            this.onChange && this.onChange(value, key, oldValue);
        };
        __decorate([
            dirtyFieldTrigger
        ], Size.prototype, "width", void 0);
        __decorate([
            dirtyFieldTrigger
        ], Size.prototype, "height", void 0);
        return Size;
    }());

    var FontStyle;
    (function (FontStyle) {
        FontStyle["NORMAL"] = "normal";
        FontStyle["ITALIC"] = "italic";
        FontStyle["OBLIQUE"] = "oblique";
    })(FontStyle || (FontStyle = {}));
    var FontVariant;
    (function (FontVariant) {
        FontVariant["NORMAL"] = "normal";
        FontVariant["SMALL_CAPS"] = "small-caps";
    })(FontVariant || (FontVariant = {}));
    var FontWeight;
    (function (FontWeight) {
        FontWeight["NORMAL"] = "normal";
        FontWeight["BOLD"] = "bold";
        FontWeight["BOLDER"] = "bolder";
        FontWeight["LIGHTER"] = "lighter";
    })(FontWeight || (FontWeight = {}));
    var TextStyle = (function () {
        function TextStyle() {
            this.fontStyle = FontStyle.NORMAL;
            this.fontVariant = FontVariant.NORMAL;
            this.fontWeight = FontWeight.NORMAL;
            this.fontSize = 25;
            this.fontFamily = 'Arial';
        }
        TextStyle.prototype.onModify = function (value, key, oldValue) {
            this.onChange && this.onChange(value, key, oldValue, 'textStyle');
        };
        __decorate([
            dirtyFieldTrigger
        ], TextStyle.prototype, "fontStyle", void 0);
        __decorate([
            dirtyFieldTrigger
        ], TextStyle.prototype, "fontVariant", void 0);
        __decorate([
            dirtyFieldTrigger
        ], TextStyle.prototype, "fontWeight", void 0);
        __decorate([
            dirtyFieldTrigger
        ], TextStyle.prototype, "fontSize", void 0);
        __decorate([
            dirtyFieldTrigger
        ], TextStyle.prototype, "fontFamily", void 0);
        return TextStyle;
    }());

    var has = Object.prototype.hasOwnProperty, prefix = '~';
    function Events() { }
    if (Object.create) {
        Events.prototype = Object.create(null);
        if (!new Events().__proto__)
            prefix = '';
    }
    function EE(fn, context, once) {
        this.fn = fn;
        this.context = context;
        this.once = once || false;
    }
    function addListener(emitter, event, fn, context, once) {
        if (typeof fn !== 'function') {
            throw new TypeError('The listener must be a function');
        }
        var listener = new EE(fn, context || emitter, once), evt = prefix ? prefix + event : event;
        if (!emitter._events[evt])
            emitter._events[evt] = listener, emitter._eventsCount++;
        else if (!emitter._events[evt].fn)
            emitter._events[evt].push(listener);
        else
            emitter._events[evt] = [emitter._events[evt], listener];
        return emitter;
    }
    function clearEvent(emitter, evt) {
        if (--emitter._eventsCount === 0)
            emitter._events = new Events();
        else
            delete emitter._events[evt];
    }
    var EventEmitter = (function () {
        function EventEmitter() {
            this._events = new Events();
            this._eventsCount = 0;
            this.off = this.removeListener;
            this.addListener = this.on;
        }
        Object.defineProperty(EventEmitter, "prefixed", {
            get: function () {
                return prefix;
            },
            enumerable: true,
            configurable: true
        });
        EventEmitter.prototype.eventNames = function () {
            var names = [], events, name;
            if (this._eventsCount === 0)
                return names;
            for (name in (events = this._events)) {
                if (has.call(events, name))
                    names.push(prefix ? name.slice(1) : name);
            }
            return names;
        };
        EventEmitter.prototype.listeners = function (event) {
            var evt = prefix ? prefix + event : event, handlers = this._events[evt];
            if (!handlers)
                return [];
            if (handlers.fn)
                return [handlers.fn];
            for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
                ee[i] = handlers[i].fn;
            }
            return ee;
        };
        EventEmitter.prototype.listenerCount = function (event) {
            var evt = prefix ? prefix + event : event, listeners = this._events[evt];
            if (!listeners)
                return 0;
            if (listeners.fn)
                return 1;
            return listeners.length;
        };
        EventEmitter.prototype.emit = function (event, a1, a2, a3, a4, a5) {
            var evt = prefix ? prefix + event : event;
            if (!this._events[evt])
                return false;
            var listeners = this._events[evt], len = arguments.length, args, i;
            if (listeners.fn) {
                if (listeners.once)
                    this.removeListener(event, listeners.fn, undefined, true);
                switch (len) {
                    case 1: return listeners.fn.call(listeners.context), true;
                    case 2: return listeners.fn.call(listeners.context, a1), true;
                    case 3: return listeners.fn.call(listeners.context, a1, a2), true;
                    case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
                    case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
                    case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
                }
                for (i = 1, args = new Array(len - 1); i < len; i++) {
                    args[i - 1] = arguments[i];
                }
                listeners.fn.apply(listeners.context, args);
            }
            else {
                var length = listeners.length, j;
                for (i = 0; i < length; i++) {
                    if (listeners[i].once)
                        this.removeListener(event, listeners[i].fn, undefined, true);
                    switch (len) {
                        case 1:
                            listeners[i].fn.call(listeners[i].context);
                            break;
                        case 2:
                            listeners[i].fn.call(listeners[i].context, a1);
                            break;
                        case 3:
                            listeners[i].fn.call(listeners[i].context, a1, a2);
                            break;
                        case 4:
                            listeners[i].fn.call(listeners[i].context, a1, a2, a3);
                            break;
                        default:
                            if (!args)
                                for (j = 1, args = new Array(len - 1); j < len; j++) {
                                    args[j - 1] = arguments[j];
                                }
                            listeners[i].fn.apply(listeners[i].context, args);
                    }
                }
            }
            return true;
        };
        EventEmitter.prototype.on = function (event, fn, context) {
            return addListener(this, event, fn, context, false);
        };
        EventEmitter.prototype.once = function (event, fn, context) {
            return addListener(this, event, fn, context, true);
        };
        EventEmitter.prototype.removeListener = function (event, fn, context, once) {
            var evt = prefix ? prefix + event : event;
            if (!this._events[evt])
                return this;
            if (!fn) {
                clearEvent(this, evt);
                return this;
            }
            var listeners = this._events[evt];
            if (listeners.fn) {
                if (listeners.fn === fn &&
                    (!once || listeners.once) &&
                    (!context || listeners.context === context)) {
                    clearEvent(this, evt);
                }
            }
            else {
                for (var i = 0, events = [], length = listeners.length; i < length; i++) {
                    if (listeners[i].fn !== fn ||
                        (once && !listeners[i].once) ||
                        (context && listeners[i].context !== context)) {
                        events.push(listeners[i]);
                    }
                }
                if (events.length)
                    this._events[evt] = events.length === 1 ? events[0] : events;
                else
                    clearEvent(this, evt);
            }
            return this;
        };
        EventEmitter.prototype.removeAllListeners = function (event) {
            var evt;
            if (event) {
                evt = prefix ? prefix + event : event;
                if (this._events[evt])
                    clearEvent(this, evt);
            }
            else {
                this._events = new Events();
                this._eventsCount = 0;
            }
            return this;
        };
        return EventEmitter;
    }());

    var Ease;
    (function (Ease) {
        Ease["quadIn"] = "quadIn";
        Ease["quadOut"] = "quadOut";
        Ease["quadInOut"] = "quadInOut";
        Ease["cubicIn"] = "cubicIn";
        Ease["cubicOut"] = "cubicOut";
        Ease["cubicInOut"] = "cubicInOut";
        Ease["quartIn"] = "quartIn";
        Ease["quartOut"] = "quartOut";
        Ease["quartInOut"] = "quartInOut";
        Ease["quintIn"] = "quintIn";
        Ease["quintOut"] = "quintOut";
        Ease["quintInOut"] = "quintInOut";
        Ease["sineIn"] = "sineIn";
        Ease["sineOut"] = "sineOut";
        Ease["sineInOut"] = "sineInOut";
        Ease["backIn"] = "backIn";
        Ease["backOut"] = "backOut";
        Ease["backInOut"] = "backInOut";
        Ease["circIn"] = "circIn";
        Ease["circOut"] = "circOut";
        Ease["circInOut"] = "circInOut";
        Ease["bounceIn"] = "bounceIn";
        Ease["bounceOut"] = "bounceOut";
        Ease["bounceInOut"] = "bounceInOut";
        Ease["elasticIn"] = "elasticIn";
        Ease["elasticOut"] = "elasticOut";
        Ease["elasticInOut"] = "elasticInOut";
    })(Ease || (Ease = {}));
    function get$1(amount) {
        if (amount < -1) {
            amount = -1;
        }
        if (amount > 1) {
            amount = 1;
        }
        return function (t) {
            if (amount == 0) {
                return t;
            }
            if (amount < 0) {
                return t * (t * -amount + 1 + amount);
            }
            return t * ((2 - t) * amount + (1 - amount));
        };
    }
    function getPowIn(pow) {
        return function (t) {
            return Math.pow(t, pow);
        };
    }
    function getPowOut(pow) {
        return function (t) {
            return 1 - Math.pow(1 - t, pow);
        };
    }
    function getPowInOut(pow) {
        return function (t) {
            if ((t *= 2) < 1)
                return 0.5 * Math.pow(t, pow);
            return 1 - 0.5 * Math.abs(Math.pow(2 - t, pow));
        };
    }
    var quadIn = getPowIn(2);
    var quadOut = getPowOut(2);
    var quadInOut = getPowInOut(2);
    var cubicIn = getPowIn(3);
    var cubicOut = getPowOut(3);
    var cubicInOut = getPowInOut(3);
    var quartIn = getPowIn(4);
    var quartOut = getPowOut(4);
    var quartInOut = getPowInOut(4);
    var quintIn = getPowIn(5);
    var quintOut = getPowOut(5);
    var quintInOut = getPowInOut(5);
    function sineIn(t) {
        return 1 - Math.cos(t * Math.PI / 2);
    }
    function sineOut(t) {
        return Math.sin(t * Math.PI / 2);
    }
    function sineInOut(t) {
        return -0.5 * (Math.cos(Math.PI * t) - 1);
    }
    function getBackIn(amount) {
        return function (t) {
            return t * t * ((amount + 1) * t - amount);
        };
    }
    var backIn = getBackIn(1.7);
    function getBackOut(amount) {
        return function (t) {
            return (--t * t * ((amount + 1) * t + amount) + 1);
        };
    }
    var backOut = getBackOut(1.7);
    function getBackInOut(amount) {
        amount *= 1.525;
        return function (t) {
            if ((t *= 2) < 1)
                return 0.5 * (t * t * ((amount + 1) * t - amount));
            return 0.5 * ((t -= 2) * t * ((amount + 1) * t + amount) + 2);
        };
    }
    var backInOut = getBackInOut(1.7);
    function circIn(t) {
        return -(Math.sqrt(1 - t * t) - 1);
    }
    function circOut(t) {
        return Math.sqrt(1 - (--t) * t);
    }
    function circInOut(t) {
        if ((t *= 2) < 1) {
            return -0.5 * (Math.sqrt(1 - t * t) - 1);
        }
        return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
    }
    function bounceIn(t) {
        return 1 - bounceOut(1 - t);
    }
    function bounceOut(t) {
        if (t < 1 / 2.75) {
            return (7.5625 * t * t);
        }
        else if (t < 2 / 2.75) {
            return (7.5625 * (t -= 1.5 / 2.75) * t + 0.75);
        }
        else if (t < 2.5 / 2.75) {
            return (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375);
        }
        else {
            return (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375);
        }
    }
    function bounceInOut(t) {
        if (t < 0.5)
            return bounceIn(t * 2) * .5;
        return bounceOut(t * 2 - 1) * 0.5 + 0.5;
    }
    function getElasticIn(amplitude, period) {
        var pi2 = Math.PI * 2;
        return function (t) {
            if (t == 0 || t == 1)
                return t;
            var s = period / pi2 * Math.asin(1 / amplitude);
            return -(amplitude * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * pi2 / period));
        };
    }
    var elasticIn = getElasticIn(1, 0.3);
    function getElasticOut(amplitude, period) {
        var pi2 = Math.PI * 2;
        return function (t) {
            if (t == 0 || t == 1)
                return t;
            var s = period / pi2 * Math.asin(1 / amplitude);
            return (amplitude * Math.pow(2, -10 * t) * Math.sin((t - s) * pi2 / period) + 1);
        };
    }
    var elasticOut = getElasticOut(1, 0.3);
    function getElasticInOut(amplitude, period) {
        var pi2 = Math.PI * 2;
        return function (t) {
            var s = period / pi2 * Math.asin(1 / amplitude);
            if ((t *= 2) < 1)
                return -0.5 * (amplitude * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * pi2 / period));
            return amplitude * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * pi2 / period) * 0.5 + 1;
        };
    }
    var elasticInOut = getElasticInOut(1, 0.3 * 1.5);

    var ease = /*#__PURE__*/Object.freeze({
        get Ease () { return Ease; },
        get: get$1,
        getPowIn: getPowIn,
        getPowOut: getPowOut,
        getPowInOut: getPowInOut,
        quadIn: quadIn,
        quadOut: quadOut,
        quadInOut: quadInOut,
        cubicIn: cubicIn,
        cubicOut: cubicOut,
        cubicInOut: cubicInOut,
        quartIn: quartIn,
        quartOut: quartOut,
        quartInOut: quartInOut,
        quintIn: quintIn,
        quintOut: quintOut,
        quintInOut: quintInOut,
        sineIn: sineIn,
        sineOut: sineOut,
        sineInOut: sineInOut,
        getBackIn: getBackIn,
        backIn: backIn,
        getBackOut: getBackOut,
        backOut: backOut,
        getBackInOut: getBackInOut,
        backInOut: backInOut,
        circIn: circIn,
        circOut: circOut,
        circInOut: circInOut,
        bounceIn: bounceIn,
        bounceOut: bounceOut,
        bounceInOut: bounceInOut,
        getElasticIn: getElasticIn,
        elasticIn: elasticIn,
        getElasticOut: getElasticOut,
        elasticOut: elasticOut,
        getElasticInOut: getElasticInOut,
        elasticInOut: elasticInOut
    });

    var dirtyFieldTrigger$1 = dirtyFieldTrigger;
    var Renderer = (function (_super) {
        __extends(Renderer, _super);
        function Renderer() {
            var _this = _super.call(this) || this;
            _this.onVector2DModify = function () {
                _this.makeDirty();
            };
            _this.dirty = true;
            _this._useCacheMode = false;
            _this.alpha = 1;
            _this.anchor = new Vector2D(0.5, 0.5);
            _this.bounds = new Bounds();
            _this.cacheCanvas = null;
            _this._anchorOffset = new Vector2D();
            _this._context = getContext();
            _this._margin = 0;
            _this._debugDrawColor = "hsl(" + makeRandomInt(360) + ", " + makeRandomInt(100) + "%, 60%)";
            return _this;
        }
        Object.defineProperty(Renderer.prototype, "useCacheMode", {
            get: function () {
                return this.getUseCacheMode();
            },
            set: function (value) {
                this._useCacheMode = value;
            },
            enumerable: true,
            configurable: true
        });
        Renderer.prototype.getUseCacheMode = function () {
            return this._useCacheMode;
        };
        Object.defineProperty(Renderer.prototype, "context", {
            get: function () {
                return this.cacheCanvasContext || this._context;
            },
            enumerable: true,
            configurable: true
        });
        Renderer.prototype.makeDirty = function () {
            this.dirty = true;
        };
        Renderer.prototype.onModify = function (value, key, oldValue) {
            _super.prototype.onModify.call(this, value, key, oldValue);
            this.makeDirty();
            switch (key) {
                case 'anchor':
                    value.onChange = this.onVector2DModify;
                    break;
            }
        };
        Renderer.prototype.onAwake = function () {
            _super.prototype.onAwake.call(this);
            if (!this.transform) {
                console.warn('renderer need a transform component');
            }
        };
        Renderer.prototype.onUpdate = function (t) {
            if (this.dirty) {
                if (this.entity.name == 'label_status') {
                    console.log();
                }
                if (this.useCacheMode) {
                    this.readyCacheCanvas();
                }
                this.measureBounds();
                if (this.useCacheMode) {
                    this.updateCacheCanvas();
                }
            }
            this.transformToLocal();
            this.render();
            if (EngineConfig.drawRenderRect) {
                var _a = this, _context = _a._context, _debugDrawColor = _a._debugDrawColor, _b = _a.bounds, width = _b.width, height = _b.height, _c = _a._anchorOffset, x_1 = _c.x, y = _c.y, _d = _a.transform.pivot, px = _d.x, py = _d.y;
                _context.globalAlpha = 0.9;
                _context.strokeStyle = _debugDrawColor;
                _context.fillStyle = _debugDrawColor;
                _context.beginPath();
                _context.rect(0, 0, width, height);
                _context.stroke();
                _context.beginPath();
                _context.arc(width * px, height * py, 3, 0, 2 * Math.PI);
                _context.fill();
            }
        };
        Renderer.prototype.readyCacheCanvas = function () {
            var canvas = this.cacheCanvas;
            if (!canvas) {
                canvas = this.cacheCanvas = createCanvas();
                this.cacheCanvasContext = canvas.getContext('2d');
            }
        };
        Renderer.prototype.updateCacheCanvas = function () {
            var canvas = this.cacheCanvas;
            var _a = this.bounds, width = _a.width, height = _a.height;
            canvas.width = width + this._margin * 2;
            canvas.height = height + this._margin * 2;
        };
        Renderer.prototype.render = function () {
            this.beforeDraw();
            this.drawClip();
            if (this.dirty) {
                if (this.useCacheMode) {
                    this.draw();
                }
                this.dirty = false;
            }
            if (this.useCacheMode) {
                this.drawCache();
            }
            else {
                this.draw();
            }
        };
        Renderer.prototype.beforeDraw = function () {
            this.applyAlpha();
        };
        Renderer.prototype.transformToLocal = function () {
            var _a = this, transform = _a.transform, _b = _a._anchorOffset, ax = _b.x, ay = _b.y;
            if (transform && transform.enabled) {
                var _c = transform.getMatrix(true), a = _c.a, b = _c.b, c = _c.c, d = _c.d, tx = _c.tx, ty = _c.ty;
                var offX = ax * a + ay * c;
                var offY = ax * b + ay * d;
                this._context.setTransform(a, b, c, d, tx - offX, ty - offY);
            }
            else {
                this._context.setTransform(1, 0, 0, 1, -ax, -ay);
            }
        };
        Renderer.prototype.applyAlpha = function () {
            this._context.globalAlpha = this.alpha * this.transform.renderAlpha;
        };
        Renderer.prototype.drawCache = function () {
            if (this.cacheCanvas.width > 0 && this.cacheCanvas.height > 0) {
                this._context.drawImage(this.cacheCanvas, -this._margin, -this._margin);
            }
        };
        Renderer.prototype.drawClip = function () {
        };
        Renderer.prototype.draw = function () {
        };
        Renderer.prototype.measureBounds = function () {
            var _a = this, _b = _a.anchor, x = _b.x, y = _b.y, bounds = _a.bounds, _c = _a.bounds, width = _c.width, height = _c.height;
            var anchorOffsetX = this._anchorOffset.x = width * x;
            var anchorOffsetY = this._anchorOffset.y = height * y;
            bounds.x = -anchorOffsetX;
            bounds.y = -anchorOffsetY;
        };
        Renderer.prototype.hitTest = function (x, y) {
            return this.bounds.contains(x, y);
        };
        __decorate([
            dirtyFieldTrigger$1
        ], Renderer.prototype, "anchor", void 0);
        return Renderer;
    }(ScillaComponent));

    var dirtyFieldDetector$1 = dirtyFieldDetector, dirtyFieldTrigger$2 = dirtyFieldTrigger;
    var MATRIX_ORDER;
    (function (MATRIX_ORDER) {
        MATRIX_ORDER[MATRIX_ORDER["SCALE_ROTATE"] = 0] = "SCALE_ROTATE";
        MATRIX_ORDER[MATRIX_ORDER["ROTATE_SCALE"] = 1] = "ROTATE_SCALE";
    })(MATRIX_ORDER || (MATRIX_ORDER = {}));
    var Transform = (function (_super) {
        __extends(Transform, _super);
        function Transform() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.onVector2DModify = function (value, key, oldValue) {
                _this.makeDirty(value, key, oldValue);
            };
            _this.position = new Vector2D(0);
            _this.alpha = 1;
            _this._width = NaN;
            _this._height = NaN;
            _this.scale = new Vector2D(1, 1);
            _this.pivot = new Vector2D(0.5, 0.5);
            _this.rotation = 0;
            _this.order = MATRIX_ORDER.SCALE_ROTATE;
            _this._localMatrix = Matrix.create();
            _this._globalMatrix = Matrix.create();
            _this._globalPivotMatrix = Matrix.create();
            return _this;
        }
        Object.defineProperty(Transform.prototype, "renderAlpha", {
            get: function () {
                return this._renderAlpha;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Transform.prototype, "width", {
            get: function () {
                var renderer = this.entity.getComponent(Renderer);
                return renderer ? renderer.bounds.width : (isNaN(this._width) ? 0 : this._width);
            },
            set: function (value) {
                if (this._width != value) {
                    this._width = value;
                    this.makeDirty(value, 'width');
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Transform.prototype, "explicitWidth", {
            get: function () {
                return this._width;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Transform.prototype, "height", {
            get: function () {
                var renderer = this.entity.getComponent(Renderer);
                return renderer ? renderer.bounds.height : (isNaN(this._height) ? 0 : this._height);
            },
            set: function (value) {
                if (this._height != value) {
                    this._height = value;
                    this.makeDirty(value, 'height');
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Transform.prototype, "explicitHeight", {
            get: function () {
                return this._height;
            },
            enumerable: true,
            configurable: true
        });
        Transform.prototype.makeDirty = function (value, key, oldValue) {
            var e_1, _a;
            this.dirty = true;
            switch (key) {
                case 'width':
                case 'height':
                    var renderers = this.entity.getComponents(Renderer);
                    try {
                        for (var renderers_1 = __values(renderers), renderers_1_1 = renderers_1.next(); !renderers_1_1.done; renderers_1_1 = renderers_1.next()) {
                            var renderer = renderers_1_1.value;
                            renderer.makeDirty();
                        }
                    }
                    catch (e_1_1) { e_1 = { error: e_1_1 }; }
                    finally {
                        try {
                            if (renderers_1_1 && !renderers_1_1.done && (_a = renderers_1.return)) _a.call(renderers_1);
                        }
                        finally { if (e_1) throw e_1.error; }
                    }
                    break;
            }
        };
        Transform.prototype.onModify = function (value, key, oldValue) {
            _super.prototype.onModify.call(this, value, key, oldValue);
            this.makeDirty(value, key, oldValue);
            switch (key) {
                case 'position':
                case 'scale':
                    value.onChange = this.onVector2DModify;
                    break;
            }
        };
        Transform.prototype.updateLocalMatrix = function () {
            var _a = this, _b = _a.position, x = _b.x, y = _b.y, _c = _a.scale, sx = _c.x, sy = _c.y, rotation = _a.rotation;
            var matrix = this._localMatrix;
            matrix.identity();
            if (this.order = MATRIX_ORDER.ROTATE_SCALE) {
                matrix.scale(sx, sy);
                matrix.rotate(rotation * Math.PI / 180);
            }
            else {
                matrix.rotate(rotation * Math.PI / 180);
                matrix.scale(sx, sy);
            }
            matrix.translate(x, y);
        };
        Transform.prototype.updateGlobalMatrix = function () {
            var _a = this, entity = _a.entity, _globalMatrix = _a._globalMatrix, _localMatrix = _a._localMatrix, _globalPivotMatrix = _a._globalPivotMatrix, _b = _a.pivot, px = _b.x, py = _b.y, width = _a.width, height = _a.height;
            _globalMatrix.copyFrom(_localMatrix);
            if (entity.parent) {
                var parentTransform = entity.parent.getComponent(Transform);
                if (parentTransform) {
                    this._renderAlpha = parentTransform._renderAlpha * this.alpha;
                    _globalMatrix.concat(parentTransform.getMatrix());
                }
            }
            else {
                this._renderAlpha = this.alpha;
            }
            _globalPivotMatrix.copyFrom(_globalMatrix);
            _globalPivotMatrix.translate(-(px - 0.5) * width, -(py - 0.5) * height);
        };
        Transform.prototype.getMatrix = function (withPivot) {
            if (withPivot === void 0) { withPivot = false; }
            return withPivot ? this._globalPivotMatrix : this._globalMatrix;
        };
        Transform.prototype.onUpdate = function (t) {
            if (this.dirty) {
                this.updateLocalMatrix();
                this.dirty = false;
            }
            this.updateGlobalMatrix();
            _super.prototype.onUpdate.call(this, t);
        };
        __decorate([
            dirtyFieldTrigger$2
        ], Transform.prototype, "position", void 0);
        __decorate([
            dirtyFieldTrigger$2
        ], Transform.prototype, "alpha", void 0);
        __decorate([
            dirtyFieldTrigger$2
        ], Transform.prototype, "scale", void 0);
        __decorate([
            dirtyFieldTrigger$2
        ], Transform.prototype, "pivot", void 0);
        __decorate([
            dirtyFieldDetector$1
        ], Transform.prototype, "rotation", void 0);
        return Transform;
    }(ScillaComponent));

    var CameraController = (function (_super) {
        __extends(CameraController, _super);
        function CameraController() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.viewportAnchor = createVector2D();
            _this.maxScale = 1.2;
            return _this;
        }
        CameraController.prototype.onCreate = function () {
            _super.prototype.onCreate.call(this);
        };
        CameraController.prototype.onAwake = function () {
            _super.prototype.onAwake.call(this);
            var _a = this, target = _a.target, viewportAnchor = _a.viewportAnchor;
            this.stageSize = getStageSize();
            if (target) {
                this.targetPosition = target.getComponent(Transform).position;
            }
            this.followPosition = createVector2D();
            if (viewportAnchor) {
                var _b = this.stageSize, width = _b.width, height = _b.height;
                var _c = this.viewportAnchor, x_1 = _c.x, y = _c.y;
                this.transform.position.setXY(width * x_1, height * y);
            }
        };
        CameraController.prototype.onUpdate = function (t) {
            _super.prototype.onUpdate.call(this, t);
            if (!this.targetPosition) {
                return;
            }
            var _a = this, _b = _a.transform, scale = _b.scale, position = _b.position, _c = _a.stageSize, width = _c.width, height = _c.height, _d = _a.targetPosition, x = _d.x, y = _d.y, length = _d.length, maxScale = _a.maxScale;
            var newScale = maxScale - length * maxScale / 2048;
            scale.setXY(newScale, newScale);
            this.followPosition.setXY(width / 2, height / 2).subtract(this.targetPosition);
            position.copyFrom(lerpObj(position, this.followPosition, 0.1, Vector2D, ['x', 'y']));
        };
        CameraController.prototype.onSleep = function () {
            _super.prototype.onSleep.call(this);
        };
        CameraController.prototype.onDestroy = function () {
            _super.prototype.onDestroy.call(this);
        };
        return CameraController;
    }(ScillaComponent));

    var dirtyFieldDetector$2 = dirtyFieldDetector;
    var FillMode;
    (function (FillMode) {
        FillMode[FillMode["NORMAL"] = 0] = "NORMAL";
        FillMode[FillMode["SLICED"] = 1] = "SLICED";
        FillMode[FillMode["TILED"] = 2] = "TILED";
    })(FillMode || (FillMode = {}));
    var TextureRenderer = (function (_super) {
        __extends(TextureRenderer, _super);
        function TextureRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.fillMode = FillMode.NORMAL;
            _this.filters = [];
            return _this;
        }
        Object.defineProperty(TextureRenderer.prototype, "hasFilters", {
            get: function () {
                return this.filters && this.filters.length > 0;
            },
            enumerable: true,
            configurable: true
        });
        TextureRenderer.prototype.draw = function () {
            _super.prototype.draw.call(this);
            this.drawImage();
            this.applyFilters();
        };
        TextureRenderer.prototype.applyFilters = function () {
            var e_1, _a;
            if (!this.hasFilters)
                return;
            var _b = this, texture = _b.texture, filters = _b.filters, context = _b.context;
            var _c = texture.bounds, textureWidth = _c.width, textureHeight = _c.height;
            var imageData = context.getImageData(0, 0, textureWidth, textureHeight);
            try {
                for (var filters_1 = __values(filters), filters_1_1 = filters_1.next(); !filters_1_1.done; filters_1_1 = filters_1.next()) {
                    var filter = filters_1_1.value;
                    filter.drawFilter(imageData);
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (filters_1_1 && !filters_1_1.done && (_a = filters_1.return)) _a.call(filters_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            context.putImageData(imageData, 0, 0);
        };
        TextureRenderer.prototype.drawImage = function () {
            if (!this.texture) {
                return;
            }
            var _a = this, texture = _a.texture, fillMode = _a.fillMode, context = _a.context, _b = _a.bounds, width = _b.width, height = _b.height;
            var _c = texture.bounds, x = _c.x, y = _c.y, textureWidth = _c.width, textureHeight = _c.height;
            switch (fillMode) {
                case FillMode.NORMAL:
                    texture.drawToCanvas(context);
                    break;
                case FillMode.SLICED:
                    break;
                case FillMode.TILED:
                    var textureCanvas = texture.getCacheCanvas();
                    var pattern = context.createPattern(textureCanvas, 'repeat');
                    context.rect(0, 0, width, height);
                    context.fillStyle = pattern;
                    context.fill();
                    break;
            }
        };
        TextureRenderer.prototype.measureBounds = function () {
            if (!this.dirty) {
                return;
            }
            var _a = this, bounds = _a.bounds, _b = _a.transform, tWidth = _b.explicitWidth, tHeight = _b.explicitHeight;
            if (this.texture) {
                var _c = this.texture, textureWidth = _c.width, textureHeight = _c.height;
                bounds.width = isNaN(tWidth) ? textureWidth : tWidth;
                bounds.height = isNaN(tHeight) ? textureHeight : tHeight;
            }
            else {
                bounds.width = isNaN(tWidth) ? 0 : tWidth;
                bounds.height = isNaN(tHeight) ? 0 : tHeight;
            }
            _super.prototype.measureBounds.call(this);
        };
        __decorate([
            dirtyFieldDetector$2
        ], TextureRenderer.prototype, "texture", void 0);
        __decorate([
            dirtyFieldDetector$2
        ], TextureRenderer.prototype, "fillMode", void 0);
        __decorate([
            dirtyFieldDetector$2
        ], TextureRenderer.prototype, "filters", void 0);
        return TextureRenderer;
    }(Renderer));

    var GraphicRenderer = (function (_super) {
        __extends(GraphicRenderer, _super);
        function GraphicRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.fillColor = '#42bce4';
            _this.borderColor = '#0899d0';
            _this.borderWidth = 0;
            _this.isUsedToMask = false;
            _this.maskVisible = false;
            return _this;
        }
        GraphicRenderer.prototype.getUseCacheMode = function () {
            return this._useCacheMode && !this.isUsedToMask;
        };
        GraphicRenderer.prototype.getRenderSize = function () {
            return { width: 0, height: 0 };
        };
        GraphicRenderer.prototype.beforeDraw = function () {
            _super.prototype.beforeDraw.call(this);
            this.applyStyle();
            this.context.beginPath();
        };
        GraphicRenderer.prototype.draw = function () {
            _super.prototype.draw.call(this);
            if (this.isUsedToMask) {
                this._context.clip();
                this.maskVisible && this.fillAndStoke();
            }
            else {
                this.fillAndStoke();
            }
        };
        GraphicRenderer.prototype.applyStyle = function () {
            var _a = this, context = _a.context, fillColor = _a.fillColor, borderColor = _a.borderColor, borderWidth = _a.borderWidth;
            context.fillStyle = fillColor;
            if (borderWidth > 0) {
                context.strokeStyle = borderColor;
                context.lineWidth = borderWidth;
            }
        };
        GraphicRenderer.prototype.fillAndStoke = function () {
            var _a = this, context = _a.context, borderWidth = _a.borderWidth;
            context.fill();
            if (borderWidth > 0) {
                context.stroke();
            }
        };
        GraphicRenderer.prototype.drawClip = function () {
            this.isUsedToMask && this.context.save();
        };
        GraphicRenderer.prototype.afterUpdate = function () {
            this.isUsedToMask && this.context.restore();
        };
        GraphicRenderer.prototype.measureBounds = function () {
            if (this.entity.name == 'content') {
                console.log();
            }
            if (!this.dirty) {
                return;
            }
            this._margin = this.borderWidth;
            var _a = this, bounds = _a.bounds, _b = _a.transform, tWidth = _b.explicitWidth, tHeight = _b.explicitHeight;
            var _c = this.getRenderSize(), sWidth = _c.width, sHeight = _c.height;
            bounds.width = isNaN(tWidth) ? sWidth : tWidth;
            bounds.height = isNaN(tHeight) ? sHeight : tHeight;
            _super.prototype.measureBounds.call(this);
        };
        return GraphicRenderer;
    }(Renderer));

    var dirtyFieldDetector$3 = dirtyFieldDetector;
    var RectRenderer = (function (_super) {
        __extends(RectRenderer, _super);
        function RectRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.width = 100;
            _this.height = 100;
            _this.cornerRadius = 0;
            return _this;
        }
        RectRenderer.prototype.getRenderSize = function () {
            var _a = this, width = _a.width, height = _a.height;
            return { width: width, height: height };
        };
        RectRenderer.prototype.draw = function () {
            var PI = Math.PI;
            var _a = this, context = _a.context, r = _a.cornerRadius, _b = _a.bounds, width = _b.width, height = _b.height, _margin = _a._margin, _useCacheMode = _a._useCacheMode;
            var offset = _useCacheMode ? _margin : 0;
            if (r) {
                context.moveTo(offset + r, offset + 0);
                context.lineTo(offset + width - r, offset + 0);
                context.arc(offset + width - r, offset + r, r, PI * 3 / 2, PI * 2);
                context.lineTo(offset + width, offset + height - r);
                context.arc(offset + width - r, offset + height - r, r, 0, PI / 2);
                context.lineTo(offset + r, offset + height);
                context.arc(offset + r, offset + height - r, r, PI / 2, PI);
                context.lineTo(offset + 0, offset + r);
                context.arc(offset + r, offset + r, r, PI, PI * 3 / 2);
            }
            else {
                context.rect(offset, offset, width, height);
            }
            _super.prototype.draw.call(this);
        };
        __decorate([
            dirtyFieldDetector$3
        ], RectRenderer.prototype, "width", void 0);
        __decorate([
            dirtyFieldDetector$3
        ], RectRenderer.prototype, "height", void 0);
        __decorate([
            dirtyFieldDetector$3
        ], RectRenderer.prototype, "cornerRadius", void 0);
        return RectRenderer;
    }(GraphicRenderer));

    var dirtyFieldTrigger$3 = dirtyFieldTrigger;
    var InteractComponent = (function (_super) {
        __extends(InteractComponent, _super);
        function InteractComponent() {
            var _this = _super.call(this) || this;
            _this.interactable = true;
            _this.touchInterrupt = false;
            _this.invertMatrix = Matrix.create();
            _this.localPos = {};
            _this.isOut = true;
            return _this;
        }
        InteractComponent.prototype._dealGlobalTouchBegin = function (e) {
            var interrupt = _super.prototype._dealGlobalTouchBegin.call(this, e);
            var hitOn = this.hitTest(e);
            if (hitOn) {
                this._touchBeginFlag = true;
                this.onTouchBegin(e);
                this._dealTouchOver(e);
            }
            return hitOn && interrupt;
        };
        InteractComponent.prototype._dealGlobalTouchMove = function (e) {
            var interrupt = _super.prototype._dealGlobalTouchMove.call(this, e);
            var hitOn = this.hitTest(e);
            if (hitOn) {
                this._dealTouchOver(e);
                this.onTouchMove(e);
            }
            else {
                this._dealTouchOut(e);
            }
            return hitOn && interrupt;
        };
        InteractComponent.prototype._dealGlobalTouchEnd = function (e) {
            var interrupt = _super.prototype._dealGlobalTouchEnd.call(this, e);
            var hitOn = this.hitTest(e);
            if (hitOn) {
                this.onTouchEnd(e);
                if (this._touchBeginFlag) {
                    this.onTouchTap(e);
                    this._touchBeginFlag = false;
                }
            }
            this.isOut = true;
            return hitOn && interrupt;
        };
        InteractComponent.prototype._dealTouchOver = function (e) {
            if (this.isOut) {
                this.isOut = false;
                this.onTouchOver(e);
            }
        };
        InteractComponent.prototype._dealTouchOut = function (e) {
            if (!this.isOut) {
                this.isOut = true;
                this.onTouchOut(e);
            }
        };
        InteractComponent.prototype.onTouchBegin = function (e) {
        };
        InteractComponent.prototype.onTouchMove = function (e) {
        };
        InteractComponent.prototype.onTouchOver = function (e) {
        };
        InteractComponent.prototype.onTouchOut = function (e) {
        };
        InteractComponent.prototype.onTouchEnd = function (e) {
        };
        InteractComponent.prototype.onTouchTap = function (e) {
        };
        InteractComponent.prototype.hitTest = function (e) {
            var e_1, _a;
            var matrix = this.transform.getMatrix();
            var invertMatrix = this.invertMatrix;
            invertMatrix.copyFrom(matrix);
            invertMatrix.invert();
            invertMatrix.transformPoint(e.x, e.y, this.localPos);
            var result = false;
            var renderers = this.entity.getComponents(Renderer);
            try {
                for (var renderers_1 = __values(renderers), renderers_1_1 = renderers_1.next(); !renderers_1_1.done; renderers_1_1 = renderers_1.next()) {
                    var renderer = renderers_1_1.value;
                    if (renderer.hitTest(this.localPos.x, this.localPos.y)) {
                        if (renderer.isUsedToMask) {
                            continue;
                        }
                        else {
                            result = true;
                            break;
                        }
                    }
                    else if (renderer.isUsedToMask) {
                        return false;
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (renderers_1_1 && !renderers_1_1.done && (_a = renderers_1.return)) _a.call(renderers_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            return result;
        };
        __decorate([
            dirtyFieldTrigger$3
        ], InteractComponent.prototype, "interactable", void 0);
        return InteractComponent;
    }(ScillaComponent));

    var TouchInterrupt = (function (_super) {
        __extends(TouchInterrupt, _super);
        function TouchInterrupt() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.touchInterrupt = true;
            return _this;
        }
        return TouchInterrupt;
    }(InteractComponent));

    var TouchZoom = (function (_super) {
        __extends(TouchZoom, _super);
        function TouchZoom() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.scaleOffset = createVector2D(0.1, 0.1);
            _this.duration = 200;
            _this.easeName = Ease.backOut;
            return _this;
        }
        TouchZoom.prototype.onAwake = function () {
            _super.prototype.onAwake.call(this);
            if (!this._zoomIn) {
                var _a = this, scaleOffset = _a.scaleOffset, duration = _a.duration, transform = _a.transform;
                var easeFunc = ease[this.easeName];
                var scaleFrom = transform.scale.clone();
                var scaleTo = transform.scale.clone().add(scaleOffset);
                this._zoomIn = createTween(transform, false, { autoPlay: false, clazz: Vector2D, fields: ['x', 'y'] })
                    .to({ scale: scaleTo }, duration, easeFunc);
                this._zoomOut = createTween(transform, false, { autoPlay: false, clazz: Vector2D, fields: ['x', 'y'] })
                    .to({ scale: scaleFrom }, duration, easeFunc);
            }
        };
        TouchZoom.prototype.onTouchBegin = function (e) {
            _super.prototype.onTouchOver.call(this, e);
            if (this.interactable) {
                this._touchBegin = true;
                this._zoomIn.play(true);
            }
        };
        TouchZoom.prototype.onGlobalTouchEnd = function (e) {
            _super.prototype.onGlobalTouchEnd.call(this, e);
            if (this._touchBegin) {
                this._touchBegin = false;
                this._zoomOut.play(true);
            }
            return false;
        };
        return TouchZoom;
    }(InteractComponent));

    var dirtyFieldDetector$4 = dirtyFieldDetector;
    var CircleRenderer = (function (_super) {
        __extends(CircleRenderer, _super);
        function CircleRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.radius = 50;
            _this.startAngle = 0;
            _this.endAngle = 360;
            _this.backToCenter = true;
            return _this;
        }
        CircleRenderer.prototype.getRenderSize = function () {
            var radius = this.radius;
            return { width: radius * 2, height: radius * 2 };
        };
        CircleRenderer.prototype.draw = function () {
            var _a = this, context = _a.context, _b = _a.bounds, width = _b.width, height = _b.height, startAngle = _a.startAngle, endAngle = _a.endAngle, backToCenter = _a.backToCenter, _margin = _a._margin, _useCacheMode = _a._useCacheMode;
            var offset = _useCacheMode ? _margin : 0;
            var radius = Math.min(width, height) / 2;
            var pos = offset + radius;
            if (startAngle == 0 && endAngle == 360) {
                context.arc(pos, pos, radius, 0, 2 * Math.PI);
            }
            else {
                if (backToCenter) {
                    context.moveTo(pos, pos);
                }
                context.arc(pos, pos, radius, startAngle * Math.PI / 180, endAngle * Math.PI / 180);
                if (backToCenter) {
                    context.lineTo(pos, pos);
                }
            }
            _super.prototype.draw.call(this);
        };
        __decorate([
            dirtyFieldDetector$4
        ], CircleRenderer.prototype, "radius", void 0);
        __decorate([
            dirtyFieldDetector$4
        ], CircleRenderer.prototype, "startAngle", void 0);
        __decorate([
            dirtyFieldDetector$4
        ], CircleRenderer.prototype, "endAngle", void 0);
        __decorate([
            dirtyFieldDetector$4
        ], CircleRenderer.prototype, "backToCenter", void 0);
        return CircleRenderer;
    }(GraphicRenderer));

    var FrameAnimationRenderer = (function (_super) {
        __extends(FrameAnimationRenderer, _super);
        function FrameAnimationRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.autoPlay = false;
            _this.fps = NaN;
            _this.onComplete = new ScillaEvent();
            _this.onLoopComplete = new ScillaEvent();
            return _this;
        }
        FrameAnimationRenderer.prototype.onAwake = function () {
            _super.prototype.onAwake.call(this);
            if (this.autoPlay) {
                this.play(0, -1);
            }
        };
        FrameAnimationRenderer.prototype.onUpdate = function (t) {
            if (this._playing) {
                var _a = this, frameAnimation = _a.frameAnimation, _startFrame = _a._startFrame, _endFrame = _a._endFrame, fps = _a.fps;
                if (this._startFlag) {
                    this._startFlag = false;
                    this._startTime = t;
                    this._loopCounting++;
                }
                var mFPS = isNaN(fps) ? frameAnimation.fps : fps;
                var passTime = t - this._startTime;
                var passFrameCount = Math.floor(passTime / (1000 / mFPS));
                var passFrameInRegion = passFrameCount % (_endFrame - _startFrame + 1);
                this._currentFrameIndex = _startFrame + passFrameInRegion;
                if (passFrameInRegion == 0 && passFrameCount > 0) {
                    this._currentFrameIndex = _endFrame;
                    this.onLoopEnd();
                }
            }
            _super.prototype.onUpdate.call(this, t);
        };
        FrameAnimationRenderer.prototype.onSleep = function () {
            _super.prototype.onSleep.call(this);
        };
        FrameAnimationRenderer.prototype.onLoopEnd = function () {
            if (this._loop < 0) {
                this._startFlag = true;
                this.onLoopComplete.invoke();
            }
            else if (this._loopCounting < this._loop) {
                this._startFlag = true;
                this.onLoopComplete.invoke();
            }
            else {
                this._playing = false;
                this.onComplete.invoke();
            }
        };
        FrameAnimationRenderer.prototype.play = function (frame, loop, force) {
            if (frame === void 0) { frame = 0; }
            if (loop === void 0) { loop = 0; }
            if (force === void 0) { force = true; }
            this._loop = loop;
            this._loopCounting = 0;
            if (!this.frameAnimation) {
                return;
            }
            var startFrame = 0, endFrame = this.frameAnimation.frameCount - 1;
            if (typeof frame == 'string') {
                var label = this.frameAnimation.getLabel(frame);
                if (label) {
                    startFrame = label.frame - 1;
                    endFrame = label.end;
                }
            }
            else {
                startFrame = frame;
            }
            this._startFrame = startFrame;
            this._endFrame = endFrame;
            this._currentFrameIndex = this._startFrame;
            this._startFlag = true;
            this._playing = true;
        };
        FrameAnimationRenderer.prototype.stop = function () {
            this._playing = false;
        };
        FrameAnimationRenderer.prototype.draw = function () {
            _super.prototype.draw.call(this);
            if (!this.frameAnimation) {
                return;
            }
            var _a = this, context = _a.context, frameAnimation = _a.frameAnimation, _currentFrameIndex = _a._currentFrameIndex, bounds = _a.bounds;
            var _b = frameAnimation.getFrame(_currentFrameIndex), texture = _b.texture, data = _b.data;
            if (texture) {
                var img = texture.img, _c = texture.bounds, x_1 = _c.x, y = _c.y, textureWidth = _c.width, textureHeight = _c.height;
                bounds.setTo(data.x, data.y, textureWidth, textureHeight);
                context.drawImage(img, x_1, y, textureWidth, textureHeight, data.x, data.y, textureWidth, textureHeight);
            }
        };
        return FrameAnimationRenderer;
    }(Renderer));

    var LineRenderer = (function (_super) {
        __extends(LineRenderer, _super);
        function LineRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.x0 = 0;
            _this.y0 = 0;
            _this.x1 = 0;
            _this.y1 = 0;
            return _this;
        }
        LineRenderer.prototype.draw = function () {
            _super.prototype.draw.call(this);
            var _a = this, context = _a.context, x0 = _a.x0, y0 = _a.y0, x1 = _a.x1, y1 = _a.y1;
            context.moveTo(x0, y0);
            context.lineTo(x1, y1);
        };
        LineRenderer.prototype.measureBounds = function () {
            var bounds = this.bounds;
            bounds.width = 0;
            bounds.height = 0;
            _super.prototype.measureBounds.call(this);
        };
        return LineRenderer;
    }(GraphicRenderer));

    var dirtyFieldDetector$5 = dirtyFieldDetector, dirtyFieldTrigger$4 = dirtyFieldTrigger;
    var TextAlign;
    (function (TextAlign) {
        TextAlign["LEFT"] = "left";
        TextAlign["CENTER"] = "center";
        TextAlign["RIGHT"] = "right";
    })(TextAlign || (TextAlign = {}));
    var VerticalAlign;
    (function (VerticalAlign) {
        VerticalAlign["TOP"] = "top";
        VerticalAlign["MIDDLE"] = "middle";
        VerticalAlign["BOTTOM"] = "bottom";
    })(VerticalAlign || (VerticalAlign = {}));
    var TextRenderer = (function (_super) {
        __extends(TextRenderer, _super);
        function TextRenderer() {
            var _this = _super !== null && _super.apply(this, arguments) || this;
            _this.text = '';
            _this.textFlow = null;
            _this.textAlign = TextAlign.CENTER;
            _this.verticalAlign = VerticalAlign.MIDDLE;
            _this.lineSpacing = 0;
            _this.letterSpacing = 0;
            _this._lineHeight = NaN;
            _this._bmpLineHeight = 0;
            _this.textStyle = new TextStyle();
            _this.useCacheMode = true;
            _this.measureCache = {};
            return _this;
        }
        TextRenderer.prototype.onModify = function (value, key, oldValue) {
            _super.prototype.onModify.call(this, value, key, oldValue);
            switch (key) {
                case 'textFlow':
                    if (value) {
                        this.updateTextFlow();
                    }
                    break;
                case 'textStyle':
                    value.onChange = this.makeDirty.bind(this);
                    this.makeDirty();
                    break;
            }
        };
        TextRenderer.prototype.updateTextFlow = function () {
            var e_1, _a;
            var text = '';
            if (this.textFlow) {
                try {
                    for (var _b = __values(this.textFlow), _c = _b.next(); !_c.done; _c = _b.next()) {
                        var item = _c.value;
                        text += item.text;
                    }
                }
                catch (e_1_1) { e_1 = { error: e_1_1 }; }
                finally {
                    try {
                        if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                    }
                    finally { if (e_1) throw e_1.error; }
                }
            }
            this._pureText = text;
            this.makeDirty();
        };
        Object.defineProperty(TextRenderer.prototype, "lineHeight", {
            get: function () {
                return isNaN(this._lineHeight) ? (this.isBmpMode ? this._bmpLineHeight : this.textStyle.fontSize * EngineConfig.lineHeightRatio) : this._lineHeight;
            },
            set: function (value) {
                if (this._lineHeight != value) {
                    this._lineHeight = value;
                    this.dirty = true;
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(TextRenderer.prototype, "pureText", {
            get: function () {
                return this.textFlow ? this._pureText : this.text;
            },
            enumerable: true,
            configurable: true
        });
        TextRenderer.prototype.getRenderSize = function () {
            return {
                width: this._textWidth,
                height: this._textHeight,
            };
        };
        TextRenderer.prototype.beforeDraw = function () {
            _super.prototype.beforeDraw.call(this);
            if (!this.isBmpMode) {
                this.applyTextStyle();
            }
        };
        TextRenderer.prototype.applyTextStyle = function () {
            var _a = this, context = _a.context, textStyle = _a.textStyle;
            var fontStyle = textStyle.fontStyle, fontVariant = textStyle.fontVariant, fontWeight = textStyle.fontWeight, fontSize = textStyle.fontSize, fontFamily = textStyle.fontFamily;
            context.font = fontStyle + " " + fontVariant + " " + fontWeight + " " + fontSize + "px " + fontFamily;
        };
        TextRenderer.prototype.fillAndStoke = function () {
            if (!this.pureText || this.pureText.length == 0) {
                return;
            }
            var _a = this, context = _a.context, measureCache = _a.measureCache, lineHeight = _a.lineHeight, lineSpacing = _a.lineSpacing, letterSpacing = _a.letterSpacing, rows = _a.rows, textAlign = _a.textAlign, verticalAlign = _a.verticalAlign, isBmpMode = _a.isBmpMode, _b = _a.transform, width = _b.width, height = _b.height;
            var rowCount = rows.length;
            var x = 0;
            switch (textAlign) {
                case "left":
                    x = 0;
                    break;
                case "right":
                    x = width;
                    break;
                case "center":
                default:
                    x = width / 2;
                    break;
            }
            var y = 0;
            var drawHeight = rowCount * lineHeight + lineSpacing * (rowCount - 1);
            switch (verticalAlign) {
                case "top":
                    y = 0;
                    break;
                case "bottom":
                    y = height - drawHeight;
                    break;
                case "middle":
                default:
                    y = (height - drawHeight) / 2;
                    break;
            }
            y += lineHeight;
            context.textAlign = letterSpacing == 0 && !this.textFlow ? textAlign : 'left';
            context.textBaseline = 'bottom';
            var offY = 0;
            for (var i = 0; i < rowCount; i++) {
                var _c = rows[i], text = _c.text, lineWidth = _c.lineWidth;
                if (letterSpacing == 0 && !isBmpMode && !this.textFlow) {
                    this.drawText(i, text, x, y + offY);
                }
                else {
                    var offX = 0;
                    switch (textAlign) {
                        case "left":
                            offX = 0;
                            break;
                        case "right":
                            offX = -lineWidth;
                            break;
                        case "center":
                        default:
                            offX = -lineWidth / 2;
                            break;
                    }
                    for (var j = 0, lj = text.length; j < lj; j++) {
                        var char = text[j];
                        this.drawText(j, char, x + offX, y + offY);
                        if (measureCache[char].width > 0) {
                            offX += measureCache[char].width + letterSpacing;
                        }
                    }
                }
                offY += lineHeight + lineSpacing;
            }
        };
        TextRenderer.prototype.getStyle = function (index) {
            var e_2, _a;
            if (!this.textFlow) {
                return null;
            }
            var targetItem;
            var count = 0;
            try {
                for (var _b = __values(this.textFlow), _c = _b.next(); !_c.done; _c = _b.next()) {
                    var item = _c.value;
                    count += item.text.length;
                    if (index < count) {
                        targetItem = item;
                        break;
                    }
                }
            }
            catch (e_2_1) { e_2 = { error: e_2_1 }; }
            finally {
                try {
                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
                }
                finally { if (e_2) throw e_2.error; }
            }
            return targetItem.style;
        };
        TextRenderer.prototype.drawText = function (index, text, x, y) {
            var _a = this, context = _a.context, borderWidth = _a.borderWidth, isBmpMode = _a.isBmpMode, fontRes = _a.fontRes;
            if (isBmpMode) {
                var texture = fontRes.getTexture(text);
                if (!texture) {
                    return;
                }
                var _b = texture.bounds, textureX = _b.x, textureY = _b.y, textureWidth = _b.width, textureHeight = _b.height;
                context.drawImage(texture.img, textureX, textureY, textureWidth, textureHeight, x, y, textureWidth, textureHeight);
            }
            else {
                var style = this.getStyle(index);
                if (style) {
                    if (style.hasOwnProperty('textColor')) {
                        context.fillStyle = style.textColor;
                    }
                }
                else {
                    context.fillStyle = this.fillColor;
                }
                context.fillText(text, x, y + 1);
                if (borderWidth > 0) {
                    context.strokeText(text, x, y + 1);
                }
            }
        };
        Object.defineProperty(TextRenderer.prototype, "isBmpMode", {
            get: function () {
                return !!this.fontRes;
            },
            enumerable: true,
            configurable: true
        });
        TextRenderer.prototype.measureText = function (text) {
            var e_3, _a, e_4, _b;
            var result;
            if (this.measureCache.hasOwnProperty(text)) {
                result = this.measureCache[text];
            }
            else {
                var _c = this, context = _c.context, letterSpacing = _c.letterSpacing, isBmpMode = _c.isBmpMode, fontRes = _c.fontRes, lineHeight = _c.lineHeight;
                if (isBmpMode) {
                    if (text.length == 1) {
                        var texture = fontRes.getTexture(text);
                        result = {
                            width: texture ? texture.width : 0,
                            height: texture ? texture.height : 0,
                        };
                    }
                    else {
                        var totalWidth = 0, totalHeight = 0;
                        try {
                            for (var text_1 = __values(text), text_1_1 = text_1.next(); !text_1_1.done; text_1_1 = text_1.next()) {
                                var char = text_1_1.value;
                                var measureResult = this.measureText(char);
                                totalWidth += measureResult.width;
                                if (measureResult.height > totalHeight) {
                                    totalHeight = measureResult.height;
                                }
                            }
                        }
                        catch (e_3_1) { e_3 = { error: e_3_1 }; }
                        finally {
                            try {
                                if (text_1_1 && !text_1_1.done && (_a = text_1.return)) _a.call(text_1);
                            }
                            finally { if (e_3) throw e_3.error; }
                        }
                        result = {
                            width: totalWidth,
                            height: totalHeight,
                        };
                    }
                }
                else {
                    result = {
                        width: context.measureText(text).width,
                        height: lineHeight,
                    };
                }
                result.width += letterSpacing * (text.length - 1);
                if (text.length == 1) {
                    this.measureCache[text] = result;
                }
                if (letterSpacing != 0 && text.length > 1 || this.textFlow) {
                    try {
                        for (var text_2 = __values(text), text_2_1 = text_2.next(); !text_2_1.done; text_2_1 = text_2.next()) {
                            var char = text_2_1.value;
                            this.measureCache[char] = this.measureText(char);
                        }
                    }
                    catch (e_4_1) { e_4 = { error: e_4_1 }; }
                    finally {
                        try {
                            if (text_2_1 && !text_2_1.done && (_b = text_2.return)) _b.call(text_2);
                        }
                        finally { if (e_4) throw e_4.error; }
                    }
                }
            }
            return result;
        };
        TextRenderer.prototype.splitText = function () {
            var e_5, _a;
            var _b = this, text = _b.pureText, letterSpacing = _b.letterSpacing, lineSpacing = _b.lineSpacing, lineHeight = _b.lineHeight, isBmpMode = _b.isBmpMode, _c = _b.transform, explicitWidth = _c.explicitWidth, explicitHeight = _c.explicitHeight;
            this.measureCache = {};
            var textWidth = 0, textHeight = 0, maxHeight = 0;
            var rows = [], measureResult;
            if (text && text.length > 0) {
                if (isNaN(explicitWidth)) {
                    var lines = text.split('\n');
                    try {
                        for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
                            var line = lines_1_1.value;
                            measureResult = this.measureText(line);
                            var mw = measureResult.width;
                            if (mw > textWidth) {
                                textWidth = mw;
                            }
                            if (isBmpMode) {
                                var mh = measureResult.height;
                                if (mh > maxHeight) {
                                    maxHeight = mh;
                                }
                            }
                            rows.push({
                                text: line,
                                lineWidth: mw,
                            });
                        }
                    }
                    catch (e_5_1) { e_5 = { error: e_5_1 }; }
                    finally {
                        try {
                            if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
                        }
                        finally { if (e_5) throw e_5.error; }
                    }
                    if (!isBmpMode) {
                        maxHeight = lineHeight;
                    }
                    this._bmpLineHeight = maxHeight;
                }
                else {
                    var chars = text.split('');
                    var lineWidth = 0, charWidth = 0, index = 0;
                    var line = '';
                    for (var i = 0, li = chars.length; i < li; i++) {
                        var char = chars[i];
                        if (char == '\n') {
                            rows.push({
                                text: line,
                                lineWidth: lineWidth,
                            });
                            line = '';
                            lineWidth = 0;
                            index = 0;
                        }
                        else {
                            measureResult = this.measureText(char);
                            if (measureResult.width == 0) {
                                continue;
                            }
                            charWidth = measureResult.width;
                            var mh = measureResult.height;
                            if (mh > maxHeight) {
                                maxHeight = mh;
                            }
                            if (index > 0 && lineWidth + charWidth + (index == 0 ? 0 : letterSpacing) > explicitWidth) {
                                rows.push({
                                    text: line,
                                    lineWidth: lineWidth,
                                });
                                line = '';
                                lineWidth = 0;
                                index = 0;
                            }
                            line += char;
                            lineWidth += charWidth + (index == 0 ? 0 : letterSpacing);
                            index++;
                        }
                    }
                    this._bmpLineHeight = maxHeight;
                    rows.push({
                        text: line,
                        lineWidth: lineWidth,
                    });
                    textWidth = explicitWidth;
                }
                textHeight = isNaN(explicitHeight) ? (maxHeight * rows.length + lineSpacing * (rows.length - 1)) : explicitHeight;
            }
            else {
                textWidth = isNaN(explicitWidth) ? 0 : explicitWidth;
                textHeight = isNaN(explicitHeight) ? 0 : explicitHeight;
            }
            this.rows = rows;
            this._textWidth = textWidth;
            this._textHeight = textHeight;
            return {
                rows: rows,
                textWidth: textWidth,
                textHeight: textHeight,
            };
        };
        TextRenderer.prototype.measureBounds = function () {
            if (!this.dirty) {
                return;
            }
            if (!this.isBmpMode) {
                this.applyTextStyle();
            }
            this.splitText();
            _super.prototype.measureBounds.call(this);
        };
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "text", void 0);
        __decorate([
            dirtyFieldTrigger$4
        ], TextRenderer.prototype, "textFlow", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "textAlign", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "verticalAlign", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "lineSpacing", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "letterSpacing", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "fontRes", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "textStyle", void 0);
        __decorate([
            dirtyFieldDetector$5
        ], TextRenderer.prototype, "useCacheMode", void 0);
        return TextRenderer;
    }(GraphicRenderer));

    var Button = (function (_super) {
        __extends(Button, _super);
        function Button() {
            var _this = _super.call(this) || this;
            _this.touchInterrupt = true;
            return _this;
        }
        Object.defineProperty(Button.prototype, "touchZoom", {
            get: function () {
                return this.entity && this.entity.getComponent(TouchZoom);
            },
            enumerable: true,
            configurable: true
        });
        Button.prototype.onModify = function (value, key, oldValue) {
            _super.prototype.onModify.call(this, value, key, oldValue);
            if (key === 'interactable') {
                if (this.touchZoom) {
                    this.touchZoom.interactable = value;
                }
                try {
                    this.changeTexture();
                }
                catch (e) { }
            }
        };
        Button.prototype.onCreate = function () {
            _super.prototype.onCreate.call(this);
            this.onClick = new ScillaEvent();
        };
        Button.prototype.onAwake = function () {
            _super.prototype.onAwake.call(this);
            this.bgRenderer = this.entity.getComponent(TextureRenderer);
            this.changeTexture(this.upRes);
        };
        Button.prototype.onTouchBegin = function (e) {
            _super.prototype.onTouchBegin.call(this, e);
            this.touchBeginWithSelf = true;
            this.changeTexture(this.downRes);
        };
        Button.prototype.onTouchOver = function (e) {
            _super.prototype.onTouchOver.call(this, e);
            if (this.touchBeginWithSelf) {
                this.touchBeginWithSelf = true;
                this.changeTexture(this.downRes);
            }
            this.touchOut = false;
        };
        Button.prototype.onTouchOut = function (e) {
            _super.prototype.onTouchOut.call(this, e);
            if (this.touchBeginWithSelf) {
                this.changeTexture(this.upRes);
            }
            this.touchOut = true;
        };
        Button.prototype.onGlobalTouchEnd = function (e) {
            _super.prototype.onGlobalTouchEnd.call(this, e);
            if (this.touchBeginWithSelf && !this.touchOut) {
                this.onClick.invoke();
            }
            this.touchBeginWithSelf = false;
            this.changeTexture(this.upRes);
        };
        Button.prototype.changeTexture = function (res) {
            if (!this.bgRenderer) {
                return;
            }
            this.currentRes = res || this.upRes;
            if (this.interactable) {
                this.bgRenderer.texture = this.currentRes;
            }
            else {
                this.bgRenderer.texture = this.disabledRes;
            }
        };
        return Button;
    }(InteractComponent));

    registerDef('components/base/Transform', Transform);
    registerDef('components/other/CameraController', CameraController);
    registerDef('components/renderer/TextureRenderer', TextureRenderer);
    registerDef('components/renderer/RectRenderer', RectRenderer);
    registerDef('components/animation/TouchZoom', TouchZoom);
    registerDef('components/ui/Button', Button);
    registerDef('components/renderer/TextRenderer', TextRenderer);

    var options$1 = {};
    function inject(data) {
        injectProp(options$1, data);
    }

    modifyEngineConfig({
        lineHeightRatio: 1.2,
        entityEnabled: false,
        awakeComponentWhenAdded: false,
        sleepComponentWhenRemoved: false,
        drawRenderRect: false,
    });
    function startup(containerElement, options, onProgress) {
        return __awaiter(this, void 0, void 0, function () {
            var manifest, canvas, config;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4, loadJson('manifest.json')];
                    case 1:
                        manifest = _a.sent();
                        inject(manifest);
                        inject(options);
                        setResPath('assets/');
                        canvas = document.createElement('canvas');
                        containerElement.appendChild(canvas);
                        config = {
                            canvas: canvas,
                        };
                        if (options.config) {
                            injectProp(config, options.config);
                        }
                        setup(config);
                        launchScene('main', onProgress).catch(function (e) {
                            console.log(e);
                        });
                        return [2];
                }
            });
        });
    }

    exports.startup = startup;

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=bundle.js.map
