Show:

File: libs/Sprite.js

var __extends = (this && this.__extends) || (function () {
    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);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
/**
 * @module annie
 */
var annie;
(function (annie) {
    /**
     * 显示对象的容器类,可以将其他显示对象放入其中,是annie引擎的核心容器类.
     * Sprite 类是基本显示列表构造块:一个可显示图形并且也可包含子项的显示列表节点。
     * Sprite 对象与影片剪辑类似,但没有时间轴。Sprite 是不需要时间轴的对象的相应基类。
     * 例如,Sprite 将是通常不使用时间轴的用户界面 (UI) 组件的逻辑基类
     * @class annie.Sprite
     * @extends annie.DisplayObject
     * @public
     * @since 1.0.0
     */
    var Sprite = /** @class */ (function (_super) {
        __extends(Sprite, _super);
        /**
         * 构造函数
         * @method Sprite
         * @public
         * @since 1.0.0
         */
        function Sprite() {
            var _this = _super.call(this) || this;
            /**
             * 容器类所有动画的播放速度,默认是1.如果有嵌套的话,速度相乘;
             * @property mcSpeed
             * @public
             * @type {number}
             * @since 3.1.5
             * @default 1
             *
             */
            _this.mcSpeed = 1;
            _this._cMcSpeed = 1;
            /**
             * 是否可以让children接收鼠标事件
             * 鼠标事件将不会往下冒泡
             * @property mouseChildren
             * @type {boolean}
             * @default true
             * @public
             * @since 1.0.0
             */
            _this.mouseChildren = true;
            /**
             * 显示对象的child列表
             * @property children
             * @type {Array}
             * @public
             * @since 1.0.0
             * @default []
             * @readonly
             */
            _this.children = [];
            var s = _this;
            s._instanceType = "annie.Sprite";
            s.hitTestWithPixel = true;
            return _this;
        }
        Sprite.prototype.destroy = function () {
            var s = this;
            //让子级也destroy
            for (var i = 0; i < s.children.length; i++) {
                s.children[i].destroy();
            }
            if (s.parent instanceof annie.Sprite)
                Sprite._removeFormParent(s.parent, s);
            s.children = null;
            s._hitArea = null;
            _super.prototype.destroy.call(this);
        };
        /**
         * 添加一个显示对象到Sprite
         * @method addChild
         * @param {annie.DisplayObject} child
         * @public
         * @since 1.0.0
         * @return {void}
         */
        Sprite.prototype.addChild = function (child) {
            this.addChildAt(child, this.children.length);
        };
        /**
         * 从Sprite中移除一个child
         * @method removeChild
         * @public
         * @since 1.0.0
         * @param {annie.DisplayObject} child
         * @return {void}
         */
        Sprite.prototype.removeChild = function (child) {
            var s = this;
            var len = s.children.length;
            for (var i = 0; i < len; i++) {
                if (s.children[i] == child) {
                    s.removeChildAt(i);
                    break;
                }
            }
        };
        //全局遍历查找
        Sprite._getElementsByName = function (rex, root, isOnlyOne, isRecursive, resultList) {
            var len = root.children.length;
            if (len > 0) {
                var name_1;
                var child = void 0;
                for (var i = 0; i < len; i++) {
                    child = root.children[i];
                    name_1 = child.name;
                    if (name_1 && name_1 != "") {
                        if (rex.test(name_1)) {
                            resultList[resultList.length] = child;
                            if (isOnlyOne) {
                                return;
                            }
                        }
                    }
                    if (isRecursive) {
                        if (child instanceof annie.Sprite) {
                            Sprite._getElementsByName(rex, child, isOnlyOne, isRecursive, resultList);
                        }
                    }
                }
            }
        };
        /**
         * 通过给displayObject设置的名字来获取一个child,可以使用正则匹配查找
         * @method getChildByName
         * @param {string} name 对象的具体名字或是一个正则表达式
         * @param {boolean} isOnlyOne 默认为true,如果为true,只返回最先找到的对象,如果为false则会找到所有匹配的对象数组
         * @param {boolean} isRecursive false,如果为true,则会递归查找下去,而不只是查找当前对象中的child,child里的child也会找,依此类推
         * @return {string|Array} 返回一个对象,或者一个对象数组,没有找到则返回空
         * @public
         * @since 1.0.0
         */
        Sprite.prototype.getChildByName = function (name, isOnlyOne, isRecursive) {
            if (isOnlyOne === void 0) { isOnlyOne = true; }
            if (isRecursive === void 0) { isRecursive = false; }
            if (!name)
                return null;
            var s = this;
            var rex;
            if (typeof (name) == "string") {
                rex = new RegExp("^" + name + "$");
            }
            else {
                rex = name;
            }
            var elements = [];
            Sprite._getElementsByName(rex, s, isOnlyOne, isRecursive, elements);
            var len = elements.length;
            if (len == 0) {
                return null;
            }
            else if (len == 1) {
                return elements[0];
            }
            else {
                return elements;
            }
        };
        /**
         * 添加一个child到Sprite中并指定添加到哪个层级
         * @method addChildAt
         * @param {annie.DisplayObject} child
         * @param {number} index 从0开始
         * @public
         * @since 1.0.0
         * @return {void}
         */
        Sprite.prototype.addChildAt = function (child, index) {
            if (!(child instanceof annie.DisplayObject))
                return;
            var s = this;
            var len;
            var cp = child.parent;
            if (cp instanceof annie.Sprite) {
                Sprite._removeFormParent(cp, child);
                cp.a2x_uf = true;
            }
            len = s.children.length;
            if (index >= len) {
                s.children[len] = child;
            }
            else if (index == 0) {
                s.children.unshift(child);
            }
            else {
                s.children.splice(index, 0, child);
            }
            if (cp != s) {
                child._cp = true;
                child.parent = s;
                if (s._isOnStage && !child._isOnStage) {
                    child.stage = s.stage;
                    child._onAddEvent();
                }
            }
            s.a2x_uf = true;
        };
        Sprite._removeFormParent = function (cp, child) {
            var cpc = cp.children;
            var len = cpc.length;
            for (var i = 0; i < len; i++) {
                if (cpc[i] == child) {
                    cpc.splice(i, 1);
                    break;
                }
            }
        };
        /**
         * 获取Sprite中指定层级一个child
         * @method getChildAt
         * @param {number} index 从0开始
         * @public
         * @since 1.0.0
         * @return {annie.DisplayObject}
         */
        Sprite.prototype.getChildAt = function (index) {
            if ((this.children.length - 1) >= index) {
                return this.children[index];
            }
            else {
                return null;
            }
        };
        /**
         * 获取Sprite中一个child所在的层级索引,找到则返回索引数,未找到则返回-1
         * @method getChildIndex
         * @param {annie.DisplayObject} child 子对象
         * @public
         * @since 1.0.2
         * @return {number}
         */
        Sprite.prototype.getChildIndex = function (child) {
            var s = this;
            var len = s.children.length;
            for (var i = 0; i < len; i++) {
                if (s.children[i] == child) {
                    return i;
                }
            }
            return -1;
        };
        /**
         * 交换两个显示对象的层级
         * @method swapChild
         * @param child1 显示对象,或者显示对象的索引
         * @param child2 显示对象,或者显示对象的索引
         * @since 2.0.0
         * @return {boolean}
         */
        Sprite.prototype.swapChild = function (child1, child2) {
            var s = this;
            var id1 = -1;
            var id2 = -1;
            var childCount = s.children.length;
            if (typeof (child1) == "number") {
                id1 = child1;
            }
            else {
                id1 = s.getChildIndex(child1);
            }
            if (typeof (child2) == "number") {
                id2 = child2;
            }
            else {
                id2 = s.getChildIndex(child2);
            }
            if (id1 == id2 || id1 < 0 || id1 >= childCount || id2 < 0 || id2 >= childCount) {
                return false;
            }
            else {
                var temp = s.children[id1];
                s.children[id1] = s.children[id2];
                s.children[id2] = temp;
                return true;
            }
        };
        /**
         * 移除指定层级上的孩子
         * @method removeChildAt
         * @param {number} index 从0开始
         * @public
         * @since 1.0.0
         * @return {void}
         */
        Sprite.prototype.removeChildAt = function (index) {
            var s = this;
            var child;
            var len = s.children.length - 1;
            if (len < 0)
                return;
            if (index == len) {
                child = s.children.pop();
            }
            else if (index == 0) {
                child = s.children.shift();
            }
            else {
                child = s.children.splice(index, 1)[0];
            }
            if (s._isOnStage && child._isOnStage) {
                child._onRemoveEvent(false);
                child.stage = null;
            }
            child.parent = null;
            s.a2x_uf = true;
        };
        /**
         * 如果对容器缓存为位图过,则会更新缓存,没事别乱调用
         * @method updateCache
         * @since 3.2.0
         * @return {void}
         */
        Sprite.prototype.updateCache = function () {
            this.a2x_uf = true;
        };
        /**
         * 移除Sprite上的所有child
         * @method removeAllChildren
         * @public
         * @since 1.0.0
         * @return {void}
         */
        Sprite.prototype.removeAllChildren = function () {
            var s = this;
            var len = s.children.length;
            for (var i = len - 1; i >= 0; i--) {
                s.removeChildAt(0);
            }
        };
        Sprite.prototype.hitTestPoint = function (hitPoint, isGlobalPoint) {
            if (isGlobalPoint === void 0) { isGlobalPoint = false; }
            var s = this;
            if (!s._visible || !s.mouseEnable)
                return null;
            if (s._isCache) {
                return _super.prototype.hitTestPoint.call(this, hitPoint, isGlobalPoint);
            }
            var p = hitPoint;
            if (!isGlobalPoint) {
                p = s.localToGlobal(hitPoint, new annie.Point());
            }
            var len = s.children.length;
            var hitDisplayObject;
            var child;
            var maskObjList = {};
            //这里特别注意是从上往下遍历
            for (var i = len - 1; i >= 0; i--) {
                child = s.children[i];
                if (child._isUseToMask > 0)
                    continue;
                if (child.mask != void 0) {
                    if (maskObjList[child.mask._instanceId] == void 0) {
                        //看看点是否在遮罩内
                        if (child.mask.hitTestPoint(p, true)) {
                            //如果都不在遮罩里面,那还检测什么直接检测下一个
                            maskObjList[child.mask._instanceId] = true;
                        }
                        else {
                            maskObjList[child.mask._instanceId] = false;
                        }
                    }
                    if (maskObjList[child.mask._instanceId] == false) {
                        continue;
                    }
                }
                hitDisplayObject = child.hitTestPoint(p, true);
                if (hitDisplayObject) {
                    return hitDisplayObject;
                }
            }
            return null;
        };
        Sprite.prototype.getBounds = function () {
            var s = this;
            var rect = s._bounds;
            rect.x = 0;
            rect.y = 0;
            rect.width = 0;
            rect.height = 0;
            var children = s.children, len = children.length;
            if (len > 0) {
                for (var i = 0; i < len; i++) {
                    if (children[i].visible && children[i]._isUseToMask == 0)
                        children[i].getDrawRect();
                    annie.Rectangle.createFromRects(rect, annie.DisplayObject._transformRect);
                }
            }
            return rect;
        };
        Sprite.prototype._updateMatrix = function (isOffCanvas) {
            if (isOffCanvas === void 0) { isOffCanvas = false; }
            var s = this;
            if (s._visible) {
                _super.prototype._updateMatrix.call(this, isOffCanvas);
                var children = s.children;
                var len = children.length;
                for (var i = 0; i < len; i++) {
                    children[i]._updateMatrix(isOffCanvas);
                }
                //所有未缓存的信息还是一如既往的更新,保持信息同步
                if (s.a2x_uf) {
                    s.a2x_uf = false;
                    if (s._isCache) {
                        //更新缓存
                        annie.createCache(s);
                        s._updateSplitBounds();
                        s._checkDrawBounds();
                    }
                }
                if (!isOffCanvas) {
                    s.a2x_ua = false;
                    s.a2x_um = false;
                }
            }
        };
        Sprite.prototype._render = function (renderObj) {
            var s = this;
            if (s._isCache && s.parent) {
                //这里为什么要加上s.parent判断呢,因为离屏渲染也是走的这个方法,显然离屏渲染就是为了生成缓存的,当然就不能直接走缓存这个逻辑
                _super.prototype._render.call(this, renderObj);
            }
            else {
                var len = s.children.length;
                if (s._visible && s._cAlpha > 0 && len > 0) {
                    var children = s.children;
                    var ro = renderObj;
                    var maskObj = void 0;
                    var child = void 0;
                    for (var i = 0; i < len; i++) {
                        child = children[i];
                        if (child._isUseToMask > 0) {
                            continue;
                        }
                        if (maskObj instanceof annie.DisplayObject) {
                            if (child.mask instanceof annie.DisplayObject && child.mask.parent == child.parent) {
                                if (child.mask != maskObj) {
                                    ro.endMask();
                                    maskObj = child.mask;
                                    ro.beginMask(maskObj);
                                }
                            }
                            else {
                                ro.endMask();
                                maskObj = null;
                            }
                        }
                        else {
                            if (child.mask instanceof annie.DisplayObject && child.mask.parent == child.parent) {
                                maskObj = child.mask;
                                ro.beginMask(maskObj);
                            }
                        }
                        child._render(ro);
                    }
                    if (maskObj instanceof annie.DisplayObject) {
                        ro.endMask();
                    }
                }
            }
        };
        Sprite.prototype._onRemoveEvent = function (isReSetMc) {
            var s = this;
            var child = null;
            //这里用concat 隔离出一个新的children是非常重要的一步
            var children = s.children.concat();
            var len = children.length;
            for (var i = len - 1; i >= 0; i--) {
                child = children[i];
                if (child instanceof annie.DisplayObject && child._isOnStage) {
                    child._onRemoveEvent(isReSetMc);
                    child.stage = null;
                }
            }
            _super.prototype._onRemoveEvent.call(this, isReSetMc);
        };
        Sprite.prototype._onAddEvent = function () {
            var s = this;
            var child = null;
            //这里用concat 隔离出一个新的children是非常重要的一步
            var children = s.children.concat();
            var len = children.length;
            for (var i = len - 1; i >= 0; i--) {
                child = children[i];
                if (child instanceof annie.DisplayObject && !child._isOnStage) {
                    child.stage = s.stage;
                    child._onAddEvent();
                }
            }
            _super.prototype._onAddEvent.call(this);
        };
        Sprite.prototype._onUpdateFrame = function (mcSpeed, isOffCanvas) {
            if (mcSpeed === void 0) { mcSpeed = 1; }
            if (isOffCanvas === void 0) { isOffCanvas = false; }
            var s = this;
            s._cMcSpeed = s.mcSpeed * mcSpeed;
            _super.prototype._onUpdateFrame.call(this, s._cMcSpeed, isOffCanvas);
            var child = null;
            var children = s.children.concat();
            var len = children.length;
            for (var i = len - 1; i >= 0; i--) {
                child = children[i];
                if (child) {
                    child._onUpdateFrame(s._cMcSpeed, isOffCanvas);
                }
            }
        };
        return Sprite;
    }(annie.DisplayObject));
    annie.Sprite = Sprite;
})(annie || (annie = {}));