Show:

File: libs/Stage.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) {
    /**
     * Stage 表示显示 canvas 内容的整个区域,所有显示对象的顶级显示容器
     * @class annie.Stage
     * @extends annie.Sprite
     * @public
     * @since 1.0.0
     */
    var Stage = /** @class */ (function (_super) {
        __extends(Stage, _super);
        /**
         * 显示对象入口函数
         * @method Stage
         * @param {string} rootDivId
         * @param {number} desW 舞台宽
         * @param {number} desH 舞台高
         * @param {number} fps 刷新率
         * @param {string} scaleMode 缩放模式 StageScaleMode
         * @param {number} renderType 渲染模式0:canvas 1:webGl 2:dom
         * @public
         * @since 1.0.0
         */
        function Stage(rootDivId, desW, desH, frameRate, scaleMode, renderType) {
            if (rootDivId === void 0) { rootDivId = "annieEngine"; }
            if (desW === void 0) { desW = 640; }
            if (desH === void 0) { desH = 1040; }
            if (frameRate === void 0) { frameRate = 30; }
            if (scaleMode === void 0) { scaleMode = "fixedHeight"; }
            if (renderType === void 0) { renderType = 0; }
            var _this = _super.call(this) || this;
            /**
             * annie.Stage舞台初始化完成后会触发的事件
             * @event annie.Event.ON_INIT_STAGE
             * @since 1.0.0
             */
            /**
             * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
             * annie.Stage舞台尺寸发生变化时触发
             * @event annie.Event.RESIZE
             * @since 1.0.0
             */
            /**
             * annie引擎暂停或者恢复暂停时触发,这个事件只能在annie.globalDispatcher中监听
             * @event annie.Event.ON_RUN_CHANGED
             * @since 1.0.0
             */
            /**
             * annie.Stage 的多点触碰事件。这个事件只能在annie.Stage对象上侦听
             * @event annie.TouchEvent.ON_MULTI_TOUCH
             * @type {string}
             */
            /**
             * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
             * 是否阻止ios端双击后页面会往上弹的效果,因为如果阻止了,可能有些html元素出现全选框后无法取消
             * 所以需要自己灵活设置,默认阻止.
             * @property iosTouchendPreventDefault
             * @type {boolean}
             * @default true
             * @since 1.0.4
             * @public
             */
            _this.iosTouchendPreventDefault = true;
            /**
             * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
             * 是否禁止引擎所在的DIV的鼠标事件或触摸事件的默认行为,默认为true是禁止的。
             * @property isPreventDefaultEvent
             * @since 1.0.9
             * @default true
             * @type {boolean}
             */
            _this.isPreventDefaultEvent = true;
            /**
             * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
             * 整个引擎的最上层的div元素,
             * 承载canvas的那个div html元素
             * @property rootDiv
             * @public
             * @since 1.0.0
             * @type {Html Div}
             * @default null
             */
            _this.rootDiv = null;
            /**
             * 当前stage所使用的渲染器
             * 渲染器有两种,一种是canvas 一种是webGl
             * @property renderObj
             * @public
             * @since 1.0.0
             * @type {IRender}
             * @default null
             */
            _this.renderObj = null;
            /**
             * 渲染模式值 只读 CANVAS:0, webGl: 1
             * @property renderType
             * @readonly
             * @public
             * @since 1.0.0
             * @type {number}
             * @default 0
             * @readonly
             */
            _this.renderType = 0;
            _this._viewRect = new annie.Rectangle();
            /**
             * 开启或关闭多点手势事件 目前仅支持两点 旋转 缩放
             * @property isMultiTouch
             * @since 1.0.3
             * @type {boolean}
             */
            _this.isMultiTouch = false;
            /**
             * 开启或关闭多个手指的鼠标事件
             * @property isMultiMouse
             * @since 1.1.3
             * @type {boolean}
             */
            _this.isMultiMouse = false;
            /**
             * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
             * 当设备尺寸更新,或者旋转后是否自动更新舞台方向
             * 默认不开启
             * @property autoSteering
             * @public
             * @since 1.0.0
             * @type {boolean}
             * @default false
             */
            _this.autoSteering = false;
            /**
             * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
             * 当设备尺寸更新,或者旋转后是否自动更新舞台尺寸
             * 默认不开启
             * @property autoResize
             * @public
             * @since 1.0.0
             * @type {boolean}
             * @default false
             */
            _this.autoResize = false;
            /**
             * 舞台的尺寸宽,也就是我们常说的设计尺寸
             * @property desWidth
             * @public
             * @since 1.0.0
             * @default 320
             * @type {number}
             * @readonly
             */
            _this.desWidth = 0;
            /**
             * 舞台的尺寸高,也就是我们常说的设计尺寸
             * @property desHeight
             * @public
             * @since 1.0.0
             * @default 240
             * @type {number}
             * @readonly
             */
            _this.desHeight = 0;
            /**
             * 舞台在当前设备中的真实高
             * @property divHeight
             * @public
             * @since 1.0.0
             * @default 320
             * @type {number}
             * @readonly
             */
            _this.divHeight = 0;
            /**
             * 舞台在当前设备中的真实宽
             * @property divWidth
             * @public
             * @since 1.0.0
             * @default 240
             * @readonly
             * @type {number}
             */
            _this.divWidth = 0;
            /**
             * 舞台的背景色
             * 默认为""就是透明背景
             * 可能设置一个颜色值改变舞台背景
             * @property bgColor
             * @public
             * @since 1.0.0
             * @type {string} #FFFFFF" 或 RGB(255,255,255) 或 RGBA(255,255,255,255)
             */
            _this.bgColor = "";
            _this._isFullScreen = true;
            _this._scaleMode = "onScale";
            //原始为60的刷新速度时的计数器
            _this._flush = 0;
            // 当前的刷新次数计数器
            _this._currentFlush = 0;
            _this._lastDpList = {};
            //这个是鼠标事件的MouseEvent对象池,因为如果用户有监听鼠标事件,如果不建立对象池,那每一秒将会new Fps个数的事件对象,影响性能
            _this._ml = [];
            //这个是事件中用到的Point对象池,以提高性能
            _this._mp = [];
            // 鼠标按下事件的对象池
            _this._mouseDownPoint = {};
            //html的鼠标或单点触摸对应的引擎事件类型名
            _this._mouseEventTypes = {
                mousedown: "onMouseDown",
                mouseup: "onMouseUp",
                mousemove: "onMouseMove",
                touchstart: "onMouseDown",
                touchmove: "onMouseMove",
                touchend: "onMouseUp",
                touchcancel: "onMouseUp"
            };
            //stageMousePoint
            _this.sp = new annie.Point();
            //localPoint;
            _this.lp = new annie.Point();
            _this.muliPoints = [];
            //当document有鼠标或触摸事件时调用
            _this._mP1 = new annie.Point();
            //当document有鼠标或触摸事件时调用
            _this._mP2 = new annie.Point();
            _this.mouseEvent = null;
            _this._isMouseClickCanvas = true;
            /**
             * 当舞台尺寸发生改变时,如果stage autoResize 为 true,则此方法会自己调用;
             * 如果设置stage autoResize 为 false 你需要手动调用此方法以更新界面.
             * 不管autoResize 的状态是什么,你只要侦听 了stage 的 annie.Event.RESIZE 事件
             * 都可以接收到舞台变化的通知。
             * @method resize
             * @public
             * @since 1.0.0
             * @return {void}
             */
            _this.resize = function () {
                var s = this;
                var whObj = s.getRootDivWH(s.rootDiv);
                if (s.divWidth == 0 || s.divHeight == 0) {
                    if (whObj.w == 0 || whObj.h == 0)
                        return;
                    s.a2x_um = true;
                    s.divHeight = whObj.h;
                    s.divWidth = whObj.w;
                    s.renderObj.reSize(whObj.w * annie.devicePixelRatio, whObj.h * annie.devicePixelRatio);
                    s.setAlign();
                    s.dispatchEvent("onInitStage");
                }
                else if (s.autoResize) {
                    if (s.divWidth != whObj.w || s.divHeight != whObj.h) {
                        s.a2x_um = true;
                        s.divHeight = whObj.h;
                        s.divWidth = whObj.w;
                        s.renderObj.reSize(whObj.w * annie.devicePixelRatio, whObj.h * annie.devicePixelRatio);
                        s.setAlign();
                        s.dispatchEvent("onResize");
                    }
                }
            };
            if (annie.debug && !Stage._isLoadedVConsole) {
                Stage._isLoadedVConsole = true;
                var script_1 = document.createElement("script");
                script_1.onload = function () {
                    new VConsole();
                    script_1.onload = null;
                };
                document.head.appendChild(script_1);
                script_1.src = "libs/vconsole.min.js";
            }
            var s = _this;
            s.a2x_ua = true;
            s.a2x_um = true;
            s._instanceType = "annie.Stage";
            s.stage = s;
            s._isOnStage = true;
            s.name = rootDivId;
            var div = document.getElementById(rootDivId);
            s.renderType = renderType;
            s.desWidth = desW;
            s.desHeight = desH;
            s.rootDiv = div;
            s.setFrameRate(frameRate);
            s._scaleMode = scaleMode;
            s.anchorX = desW >> 1;
            s.anchorY = desH >> 1;
            //webgl 直到对2d的支持非常成熟了再考虑开启
            if (renderType == 0) {
                //canvas
                s.renderObj = new annie.CanvasRender(s);
            }
            else {
                //webgl
                //s.renderObj = new WebGLRender(s);
            }
            s.renderObj.init(document.createElement('canvas'));
            var rc = div;
            s.mouseEvent = s._onMouseEvent.bind(s);
            rc.addEventListener("mousedown", s.mouseEvent, false);
            rc.addEventListener('mousemove', s.mouseEvent, false);
            rc.addEventListener('mouseup', s.mouseEvent, false);
            rc.addEventListener("touchstart", s.mouseEvent, false);
            rc.addEventListener('touchmove', s.mouseEvent, false);
            rc.addEventListener('touchend', s.mouseEvent, false);
            rc.addEventListener('touchcancel', s.mouseEvent, false);
            //同时添加到主更新循环中
            Stage.addUpdateObj(s);
            return _this;
        }
        Object.defineProperty(Stage, "pause", {
            /**
             * 是否暂停
             * @property pause
             * @static
             * @type {boolean}
             * @public
             * @since 1.0.0
             * @default false
             */
            get: function () {
                return Stage._pause;
            },
            set: function (value) {
                var s = Stage;
                if (value != s._pause) {
                    s._pause = value;
                    if (value) {
                        //停止声音
                        annie.Sound.stopAllSounds();
                    }
                    else {
                        //恢复声音
                        annie.Sound.resumePlaySounds();
                    }
                    //触发事件
                    annie.globalDispatcher.dispatchEvent("onRunChanged", { pause: value });
                }
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(Stage.prototype, "scaleMode", {
            /**
             * 舞台的缩放模式
             * 默认为空就是无缩放的真实大小
             * "noBorder" 无边框模式
             * ”showAll" 显示所有内容
             * “fixedWidth" 固定宽
             * ”fixedHeight" 固定高
             * @property scaleMode
             * @public
             * @since 1.0.0
             * @default "onScale"
             * @type {string}
             * @example
             *      //动态更改stage的对齐方式示例
             *      //以下代码放到一个舞台的显示对象的构造函数中
             *      let s=this;
             *      s.addEventListener(annie.Event.ADD_TO_STAGE,function(e){
             *          let i=0;
             *          s.stage.addEventListener(annie.MouseEvent.CLICK,function(e){
             *              let aList=[annie.StageScaleMode.EXACT_FIT,annie.StageScaleMode.NO_BORDER,annie.StageScaleMode.NO_SCALE,annie.StageScaleMode.SHOW_ALL,annie.StageScaleMode.FIXED_WIDTH,annie.StageScaleMode.FIXED_HEIGHT]
             *              let state=e.currentTarget;
             *              state.scaleMode=aList[i];
             *              if(i>5){i=0;}
             *          }
             *      }
             *
             */
            get: function () {
                return this._scaleMode;
            },
            set: function (value) {
                var s = this;
                if (value != s._scaleMode) {
                    s._scaleMode = value;
                    s.setAlign();
                }
            },
            enumerable: true,
            configurable: true
        });
        Stage.prototype._render = function (renderObj) {
            renderObj.begin(this.bgColor);
            _super.prototype._render.call(this, renderObj);
            renderObj.end();
        };
        //刷新mouse或者touch事件
        Stage.prototype._initMouseEvent = function (event, cp, sp, identifier, timeStamp) {
            event._pd = false;
            event.clientX = cp.x;
            event.clientY = cp.y;
            event.stageX = sp.x;
            event.stageY = sp.y;
            event.timeStamp = timeStamp;
            event.identifier = identifier;
        };
        //循环刷新页面的函数
        Stage.prototype.flush = function () {
            var s = this;
            //看看是否有resize
            if (s._flush == 0) {
                s.resize();
                s._onUpdateFrame(1);
                s._updateMatrix();
                s._render(s.renderObj);
            }
            else {
                //将更新和渲染分放到两个不同的时间更新值来执行,这样可以减轻cpu同时执行的压力。
                if (s._currentFlush == 0) {
                    s._currentFlush = s._flush;
                    s.resize();
                }
                else {
                    if (s._currentFlush == s._flush) {
                        s._onUpdateFrame();
                        s._updateMatrix();
                        s._render(s.renderObj);
                    }
                    s._currentFlush--;
                }
            }
        };
        /**
         * 引擎的刷新率,就是一秒中执行多少次刷新
         * @method setFrameRate
         * @param {number} fps 最好是60的倍数如 1 2 3 6 10 12 15 20 30 60
         * @since 1.0.0
         * @public
         * @return {void}
         */
        Stage.prototype.setFrameRate = function (fps) {
            var s = this;
            s._flush = 60 / fps - 1 >> 0;
            if (s._flush < 0) {
                s._flush = 0;
            }
        };
        /**
         * 引擎的刷新率,就是一秒中执行多少次刷新
         * @method getFrameRate
         * @since 1.0.0
         * @public
         * @return {number}
         */
        Stage.prototype.getFrameRate = function () {
            return 60 / (this._flush + 1);
        };
        /**
         * <h4><font color="red">小游戏不支持 小程序不支持</font></h4>
         * 获取引擎所在的div宽高
         * @method getRootDivWH
         * @public
         * @since 1.0.0
         * @param {HTMLDivElement} div
         * @return {Object}
         */
        Stage.prototype.getRootDivWH = function (div) {
            var vW = 640;
            var vH = 960;
            if (div.style.width != "") {
                vW = parseInt(div.style.width);
                vH = parseInt(div.style.height);
                this._isFullScreen = false;
            }
            else {
                this._isFullScreen = true;
                vW = document.documentElement.clientWidth;
                vH = document.documentElement.clientHeight;
            }
            return { w: vW, h: vH };
        };
        Stage.prototype._onMouseEvent = function (e) {
            //检查是否有
            var s = this, c = s.renderObj.rootContainer, offSetX = 0, offSetY = 0;
            if (e.target.id == "_a2x_canvas") {
                s._isMouseClickCanvas = true;
                if (s.isPreventDefaultEvent) {
                    if ((e.type == "touchend") && (annie.osType == "ios") && (s.iosTouchendPreventDefault)) {
                        e.preventDefault();
                    }
                    if ((e.type == "touchmove") || (e.type == "touchstart" && annie.osType == "android")) {
                        e.preventDefault();
                    }
                }
            }
            else {
                s._isMouseClickCanvas = false;
            }
            if (!s._isFullScreen) {
                offSetX = c.getBoundingClientRect().left + c.scrollLeft;
                offSetY = c.getBoundingClientRect().top + c.scrollTop;
            }
            var sd = Stage._dragDisplay;
            if (s.isMultiTouch && e.targetTouches && e.targetTouches.length > 1) {
                if (e.targetTouches.length == 2) {
                    //求角度和距离
                    s._mP1.x = e.targetTouches[0].clientX - offSetX;
                    s._mP1.y = e.targetTouches[0].clientY - offSetY;
                    s._mP2.x = e.targetTouches[1].clientX - offSetX;
                    s._mP2.y = e.targetTouches[1].clientY - offSetY;
                    var angle = Math.atan2(s._mP1.y - s._mP2.y, s._mP1.x - s._mP2.x) / Math.PI * 180;
                    var dis = annie.Point.distance(s._mP1, s._mP2);
                    s.muliPoints.push({ p1: s._mP1, p2: s._mP2, angle: angle, dis: dis });
                    if (s.muliPoints.length >= 2) {
                        //如果有事件,抛事件
                        if (!(s._touchEvent instanceof annie.TouchEvent)) {
                            s._touchEvent = new annie.TouchEvent(annie.TouchEvent.ON_MULTI_TOUCH);
                            s._touchEvent.target = s;
                        }
                        var len = s.muliPoints.length;
                        s._touchEvent.rotate = (s.muliPoints[len - 1].angle - s.muliPoints[len - 2].angle) * 2;
                        s._touchEvent.scale = (s.muliPoints[len - 1].dis - s.muliPoints[len - 2].dis) / (s.divHeight > s.divWidth ? s.desWidth : s.desHeight) * 4;
                        s._touchEvent.clientPoint1.x = s.muliPoints[len - 1].p1.x * annie.devicePixelRatio;
                        s._touchEvent.clientPoint2.x = s.muliPoints[len - 1].p2.x * annie.devicePixelRatio;
                        s._touchEvent.clientPoint1.y = s.muliPoints[len - 1].p1.y * annie.devicePixelRatio;
                        s._touchEvent.clientPoint2.y = s.muliPoints[len - 1].p2.y * annie.devicePixelRatio;
                        s.dispatchEvent(s._touchEvent);
                        s.muliPoints.shift();
                    }
                }
                else {
                    s.muliPoints.length = 0;
                }
                s._mouseDownPoint = {};
                s._lastDpList = {};
                if (sd) {
                    Stage._lastDragPoint.x = Number.MAX_VALUE;
                    Stage._lastDragPoint.y = Number.MAX_VALUE;
                }
            }
            else {
                if (s.muliPoints.length > 0) {
                    s._touchEvent.rotate = 0;
                    s._touchEvent.scale = 0;
                    s._touchEvent.clientPoint1.x = 0;
                    s._touchEvent.clientPoint2.x = 0;
                    s._touchEvent.clientPoint1.y = 0;
                    s._touchEvent.clientPoint2.y = 0;
                    s.dispatchEvent(s._touchEvent);
                    s.muliPoints.length = 0;
                }
                //检查mouse或touch事件是否有,如果有的话,就触发事件函数
                if (annie.EventDispatcher._totalMEC > 0) {
                    var points = void 0;
                    var item = s._mouseEventTypes[e.type];
                    var events = [];
                    var event_1;
                    //clientPoint
                    var cp = void 0;
                    //事件个数
                    var eLen = void 0;
                    var identifier = void 0;
                    if (!e.changedTouches) {
                        e.identifier = "pc0";
                        points = [e];
                    }
                    else {
                        if (s.isMultiMouse) {
                            points = e.changedTouches;
                        }
                        else {
                            var fp = e.changedTouches[0];
                            if ((s._lastDpList[fp.identifier] != void 0) || (item == "onMouseDown" && !s._lastDpList.isStart)) {
                                s._lastDpList.isStart = true;
                                points = [fp];
                            }
                            else {
                                return;
                            }
                        }
                    }
                    var pLen = points.length;
                    for (var o = 0; o < pLen; o++) {
                        eLen = 0;
                        events.length = 0;
                        identifier = points[o].identifier;
                        if (s._mp.length > 0) {
                            cp = s._mp.shift();
                        }
                        else {
                            cp = new annie.Point();
                        }
                        cp.x = (points[o].clientX - offSetX) * annie.devicePixelRatio;
                        cp.y = (points[o].clientY - offSetY) * annie.devicePixelRatio;
                        s.globalToLocal(cp, s.sp);
                        if (sd && sd.stage && sd.parent) {
                            var x1 = sd.x, y1 = sd.y;
                            sd.parent.globalToLocal(cp, s.lp);
                            if (!Stage._isDragCenter) {
                                if (Stage._lastDragPoint.x != Number.MAX_VALUE) {
                                    x1 += s.lp.x - Stage._lastDragPoint.x;
                                    y1 += s.lp.y - Stage._lastDragPoint.y;
                                }
                                Stage._lastDragPoint.x = s.lp.x;
                                Stage._lastDragPoint.y = s.lp.y;
                            }
                            else {
                                x1 = s.lp.x;
                                y1 = s.lp.y;
                            }
                            s.lp.x = x1;
                            s.lp.y = y1;
                            if (Stage._dragBounds.width != Number.MIN_VALUE) {
                                if (x1 < Stage._dragBounds.x) {
                                    x1 = Stage._dragBounds.x;
                                }
                                else if (x1 > Stage._dragBounds.x + Stage._dragBounds.width) {
                                    x1 = Stage._dragBounds.x + Stage._dragBounds.width;
                                }
                                if (y1 < Stage._dragBounds.y) {
                                    y1 = Stage._dragBounds.y;
                                }
                                else if (y1 > Stage._dragBounds.y + Stage._dragBounds.height) {
                                    y1 = Stage._dragBounds.y + Stage._dragBounds.height;
                                }
                            }
                            sd.x = x1;
                            sd.y = y1;
                        }
                        if (s._ml[eLen] instanceof annie.MouseEvent) {
                            event_1 = s._ml[eLen];
                            event_1.type = item;
                        }
                        else {
                            event_1 = new annie.MouseEvent(item);
                            s._ml[eLen] = event_1;
                        }
                        events[events.length] = event_1;
                        s._initMouseEvent(event_1, cp, s.sp, identifier, e.timeStamp);
                        eLen++;
                        if (item == "onMouseDown") {
                            s._mouseDownPoint[identifier] = cp;
                            //清空上次存在的显示列表
                        }
                        else if (item == "onMouseUp") {
                            if (s._mouseDownPoint[identifier] instanceof annie.Point) {
                                if (annie.Point.distance(s._mouseDownPoint[identifier], cp) < 20) {
                                    //click事件
                                    //这个地方检查是所有显示对象列表里是否有添加对应的事件
                                    if (annie.EventDispatcher.getMouseEventCount("onMouseClick") > 0) {
                                        if (s._ml[eLen] instanceof annie.MouseEvent) {
                                            event_1 = s._ml[eLen];
                                            event_1.type = "onMouseClick";
                                        }
                                        else {
                                            event_1 = new annie.MouseEvent("onMouseClick");
                                            s._ml[eLen] = event_1;
                                        }
                                        events[events.length] = event_1;
                                        s._initMouseEvent(event_1, cp, s.sp, identifier);
                                        eLen++;
                                    }
                                }
                            }
                        }
                        if (eLen > 0) {
                            //证明有事件那么就开始遍历显示列表。就算有多个事件也不怕,因为坐标点相同,所以只需要遍历一次
                            var d_1 = s.hitTestPoint(cp, true);
                            var displayList = [];
                            if (d_1 instanceof annie.DisplayObject) {
                                //证明有点击到事件,然后从最底层追上来,看看一路是否有人添加过mouse或touch事件,还要考虑mousechildren和阻止事件方法
                                //找出真正的target,因为有些父级可能会mouseChildren=false;
                                do {
                                    if (d_1 instanceof annie.Sprite && d_1.mouseChildren == false) {
                                        //丢掉之前的层级,因为根本没用了
                                        displayList.length = 0;
                                    }
                                    displayList[displayList.length] = d_1;
                                    d_1 = d_1.parent;
                                } while (d_1 instanceof annie.DisplayObject);
                            }
                            else {
                                displayList[0] = s;
                            }
                            var len = displayList.length;
                            for (var i = len - 1; i >= 0; i--) {
                                d_1 = displayList[i];
                                for (var j = 0; j < eLen; j++) {
                                    if (!events[j]._pd && d_1.hasEventListener(events[j].type)) {
                                        events[j].currentTarget = d_1;
                                        events[j].target = displayList[0];
                                        d_1.globalToLocal(cp, s.lp);
                                        events[j].localX = s.lp.x;
                                        events[j].localY = s.lp.y;
                                        d_1.dispatchEvent(events[j]);
                                    }
                                }
                            }
                            //这里一定要反转一下,因为会影响mouseOut mouseOver
                            displayList.reverse();
                            for (var i = len - 1; i >= 0; i--) {
                                d_1 = displayList[i];
                                for (var j = 0; j < eLen; j++) {
                                    if (!events[j]._pd && d_1.hasEventListener(events[j].type, false)) {
                                        events[j].currentTarget = d_1;
                                        events[j].target = displayList[eLen - 1];
                                        d_1.globalToLocal(cp, s.lp);
                                        events[j].localX = s.lp.x;
                                        events[j].localY = s.lp.y;
                                        d_1.dispatchEvent(events[j], null, false);
                                    }
                                }
                            }
                            //最后要和上一次的遍历者对比下,如果不相同则要触发onMouseOver和onMouseOut
                            if (item != "onMouseDown") {
                                if (annie.EventDispatcher.getMouseEventCount("onMouseOver") > 0 || annie.EventDispatcher.getMouseEventCount("onMouseOut") > 0) {
                                    if (s._lastDpList[identifier] instanceof Array) {
                                        //从第二个开始,因为第一个对象始终是stage顶级对象
                                        var len1 = s._lastDpList[identifier].length;
                                        var len2 = displayList.length;
                                        len = len1 > len2 ? len1 : len2;
                                        var isDiff = false;
                                        var overEvent = void 0;
                                        var outEvent = void 0;
                                        for (var i = 1; i < len; i++) {
                                            if (!isDiff) {
                                                if (s._lastDpList[identifier][i] != displayList[i]) {
                                                    //好就是这里,需要确定哪些有onMouseOver,哪些有onMouseOut
                                                    isDiff = true;
                                                    if (s._ml[eLen] instanceof annie.MouseEvent) {
                                                        overEvent = s._ml[eLen];
                                                        overEvent.type = "onMouseOver";
                                                    }
                                                    else {
                                                        overEvent = new annie.MouseEvent("onMouseOver");
                                                        s._ml[eLen] = overEvent;
                                                    }
                                                    s._initMouseEvent(overEvent, cp, s.sp, identifier);
                                                    eLen++;
                                                    if (s._ml[eLen] instanceof annie.MouseEvent) {
                                                        outEvent = s._ml[eLen];
                                                        outEvent.type = "onMouseOut";
                                                    }
                                                    else {
                                                        outEvent = new annie.MouseEvent("onMouseOut");
                                                        s._ml[eLen] = outEvent;
                                                    }
                                                    s._initMouseEvent(outEvent, cp, s.sp, identifier);
                                                }
                                            }
                                            if (isDiff) {
                                                if (s._lastDpList[identifier][i]) {
                                                    //触发onMouseOut事件
                                                    d_1 = s._lastDpList[identifier][i];
                                                    if (!outEvent._pd && d_1.hasEventListener("onMouseOut")) {
                                                        outEvent.currentTarget = d_1;
                                                        outEvent.target = s._lastDpList[identifier][len1 - 1];
                                                        d_1.globalToLocal(cp, s.lp);
                                                        outEvent.localX = s.lp.x;
                                                        outEvent.localY = s.lp.y;
                                                        d_1.dispatchEvent(outEvent);
                                                    }
                                                }
                                                d_1 = displayList[i];
                                                if (d_1 instanceof annie.DisplayObject) {
                                                    //触发onMouseOver事件
                                                    if (!overEvent._pd && d_1.hasEventListener("onMouseOver")) {
                                                        overEvent.currentTarget = d_1;
                                                        overEvent.target = displayList[len2 - 1];
                                                        d_1.globalToLocal(cp, s.lp);
                                                        overEvent.localX = s.lp.x;
                                                        overEvent.localY = s.lp.y;
                                                        d_1.dispatchEvent(overEvent);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                s._mp[s._mp.length] = cp;
                            }
                            if (item == "onMouseUp") {
                                delete s._mouseDownPoint[identifier];
                                delete s._lastDpList[identifier];
                                s._lastDpList.isStart = false;
                                if (sd) {
                                    Stage._lastDragPoint.x = Number.MAX_VALUE;
                                    Stage._lastDragPoint.y = Number.MAX_VALUE;
                                }
                            }
                            else {
                                s._lastDpList[identifier] = displayList;
                            }
                        }
                    }
                }
            }
        };
        ;
        //设置舞台的对齐模式
        Stage.prototype.setAlign = function () {
            var s = this;
            var divH = s.divHeight * annie.devicePixelRatio;
            var divW = s.divWidth * annie.devicePixelRatio;
            var desH = s.desHeight;
            var desW = s.desWidth;
            s.anchorX = desW >> 1;
            s.anchorY = desH >> 1;
            //设备是否为竖屏
            var isDivH = divH >= divW;
            //内容是否为竖屏内容
            var isDesH = desH >= desW;
            var scaleY = 1;
            var scaleX = 1;
            s.x = (divW - desW) >> 1;
            s.y = (divH - desH) >> 1;
            if (s.autoSteering) {
                if (isDesH != isDivH) {
                    var d_2 = divH;
                    divH = divW;
                    divW = d_2;
                }
            }
            if (s._scaleMode != "noScale") {
                scaleY = divH / desH;
                scaleX = divW / desW;
                switch (s._scaleMode) {
                    case "noBorder":
                        if (scaleX > scaleY) {
                            scaleY = scaleX;
                        }
                        else {
                            scaleX = scaleY;
                        }
                        break;
                    case "showAll":
                        if (scaleX < scaleY) {
                            scaleY = scaleX;
                        }
                        else {
                            scaleX = scaleY;
                        }
                        break;
                    case "fixedWidth":
                        scaleY = scaleX;
                        break;
                    case "fixedHeight":
                        scaleX = scaleY;
                        break;
                }
            }
            s.scaleX = scaleX;
            s.scaleY = scaleY;
            if (s.autoSteering) {
                if (isDesH == isDivH) {
                    s.rotation = 0;
                }
                else {
                    if (desH > desW) {
                        s.rotation = -90;
                    }
                    else {
                        s.rotation = 90;
                    }
                }
            }
            else {
                s.rotation = 0;
            }
            s._viewRect.x = (desW - divW / scaleX) >> 1;
            s._viewRect.y = (desH - divH / scaleY) >> 1;
            s._viewRect.width = desW - s._viewRect.x * 2;
            s._viewRect.height = desH - s._viewRect.y * 2;
        };
        ;
        Object.defineProperty(Stage.prototype, "viewRect", {
            /**
             * 舞台在设备里截取后的可见区域,有些时候知道可见区域是非常重要的,因为这样你就可以根据舞台的可见区域做自适应了。
             * @property viewRect
             * @public
             * @readonly
             * @since 1.0.0
             * @type {annie.Rectangle}
             * @default {x:0,y:0,width:0,height:0}
             * @readonly
             * @example
             *      //始终让一个对象顶对齐,或者
             */
            get: function () {
                return this._viewRect;
            },
            enumerable: true,
            configurable: true
        });
        //刷新所有定时器
        Stage.flushAll = function () {
            if (!Stage._pause) {
                var len = Stage.allUpdateObjList.length;
                for (var i = len - 1; i >= 0; i--) {
                    Stage.allUpdateObjList[i] && Stage.allUpdateObjList[i].flush();
                }
            }
            requestAnimationFrame(Stage.flushAll);
        };
        /**
         * 添加一个刷新对象,这个对象里一定要有一个 flush 函数。
         * 因为一但添加,这个对象的 flush 函数会以stage的fps间隔调用
         * 如,你的stage是30fps 那么你这个对象的 flush 函数1秒会调用30次。
         * @method addUpdateObj
         * @param target 要循化调用 flush 函数的对象
         * @public
         * @static
         * @since
         * @return {void}
         */
        Stage.addUpdateObj = function (target) {
            var isHave = false;
            var len = Stage.allUpdateObjList.length;
            for (var i = 0; i < len; i++) {
                if (Stage.allUpdateObjList[i] == target) {
                    isHave = true;
                    break;
                }
            }
            if (!isHave) {
                Stage.allUpdateObjList.unshift(target);
            }
        };
        /**
         * 移除掉已经添加的循环刷新对象
         * @method removeUpdateObj
         * @param target
         * @public
         * @static
         * @since 1.0.0
         * @return {void}
         */
        Stage.removeUpdateObj = function (target) {
            var len = Stage.allUpdateObjList.length;
            for (var i = 0; i < len; i++) {
                if (Stage.allUpdateObjList[i] == target) {
                    Stage.allUpdateObjList.splice(i, 1);
                    break;
                }
            }
        };
        Stage.prototype.destroy = function () {
            _super.prototype.destroy.call(this);
            var s = this;
            Stage.removeUpdateObj(s);
            var rc = s.rootDiv;
            if (annie.osType != "pc") {
                rc.removeEventListener("touchstart", s.mouseEvent, false);
                rc.removeEventListener('touchmove', s.mouseEvent, false);
                rc.removeEventListener('touchend', s.mouseEvent, false);
                rc.removeEventListener('touchcancel', s.mouseEvent, false);
            }
            else {
                rc.removeEventListener("mousedown", s.mouseEvent, false);
                rc.removeEventListener('mousemove', s.mouseEvent, false);
                rc.removeEventListener('mouseup', s.mouseEvent, false);
            }
            rc.style.display = "none";
            if (rc.parentNode) {
                rc.parentNode.removeChild(rc);
            }
            s.renderObj = null;
        };
        Stage._pause = false;
        Stage._isLoadedVConsole = false;
        Stage._dragDisplay = null;
        Stage._dragBounds = new annie.Rectangle();
        Stage._lastDragPoint = new annie.Point();
        Stage._isDragCenter = false;
        /**
         * 要循环调用 flush 函数对象列表
         * @method allUpdateObjList
         * @static
         * @since 1.0.0
         * @type {Array}
         */
        Stage.allUpdateObjList = [];
        return Stage;
    }(annie.Sprite));
    annie.Stage = Stage;
})(annie || (annie = {}));