UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

473 lines (430 loc) 14.2 kB
////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2014-present, Egret Technology. // All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of the Egret nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ////////////////////////////////////////////////////////////////////////////////////// namespace egret.sys { /** * @private */ export let $START_TIME: number = 0; /** * @private * 是否要广播Event.RENDER事件的标志。 */ export let $invalidateRenderFlag: boolean = false; /** * @private * 需要立即刷新屏幕的标志 */ export let $requestRenderingFlag: boolean = false; /** * Egret心跳计时器 */ export class SystemTicker { /** * @private */ public constructor() { if (DEBUG && ticker) { $error(1008, "egret.sys.SystemTicker"); } $START_TIME = Date.now(); this.frameDeltaTime = 1000 / this.$frameRate; this.lastCount = this.frameInterval = Math.round(60000 / this.$frameRate); } /** * @private */ private playerList: Player[] = []; /** * @private * 注册一个播放器实例并运行 */ $addPlayer(player: Player): void { if (this.playerList.indexOf(player) != -1) { return; } if (DEBUG) { egret_stages.push(player.stage); } this.playerList = this.playerList.concat(); this.playerList.push(player); } /** * @private * 停止一个播放器实例的运行。 */ $removePlayer(player: Player): void { let index = this.playerList.indexOf(player); if (index !== -1) { if (DEBUG) { let i = egret_stages.indexOf(player.stage); egret_stages.splice(i, 1); } this.playerList = this.playerList.concat(); this.playerList.splice(index, 1); } } /** * @private */ private callBackList: Function[] = []; /** * @private */ private thisObjectList: any[] = []; /** * @private */ $startTick(callBack: (timeStamp: number) => boolean, thisObject: any): void { let index = this.getTickIndex(callBack, thisObject); if (index != -1) { return; } this.concatTick(); this.callBackList.push(callBack); this.thisObjectList.push(thisObject); } /** * @private */ $stopTick(callBack: (timeStamp: number) => boolean, thisObject: any): void { let index = this.getTickIndex(callBack, thisObject); if (index == -1) { return; } this.concatTick(); this.callBackList.splice(index, 1); this.thisObjectList.splice(index, 1); } /** * @private */ private getTickIndex(callBack: Function, thisObject: any): number { let callBackList = this.callBackList; let thisObjectList = this.thisObjectList; for (let i = callBackList.length - 1; i >= 0; i--) { if (callBackList[i] == callBack && thisObjectList[i] == thisObject) {//这里不能用===,因为有可能传入undefined和null. return i; } } return -1; } /** * @private * */ private concatTick(): void { this.callBackList = this.callBackList.concat(); this.thisObjectList = this.thisObjectList.concat(); } /** * @private * 全局帧率 */ $frameRate: number = 30; /** * @private */ private frameInterval: number; /** * @private */ private frameDeltaTime: number; /** * @private */ private lastTimeStamp: number = 0; /** * @private * 设置全局帧率 */ $setFrameRate(value: number): boolean { value = +value || 0; if (value <= 0) { return false; } if (this.$frameRate == value) { return false; } this.$frameRate = value; if (value > 60) { value = 60; } //todo if (Capabilities.runtimeType == RuntimeType.NATIVE) { egret_native.setFrameRate(value); value = 60; } this.frameDeltaTime = 1000 / value; //这里用60*1000来避免浮点数计算不准确的问题。 this.lastCount = this.frameInterval = Math.round(60000 / value); return true; } /** * @private */ private lastCount: number; /** * @private * ticker 花销的时间 */ private costEnterFrame: number = 0; /** * @private * 是否被暂停 */ private isPaused: boolean = false; /** * Pause the ticker. * @version Egret 5.0.2 * @platform Web,Native * @language en_US */ /** * 暂停心跳 * @version Egret 5.0.2 * @platform Web,Native * @language zh_CN */ public pause(): void { this.isPaused = true; } /** * Resume the ticker. * @version Egret 5.0.2 * @platform Web,Native * @language en_US */ /** * 恢复心跳 * @version Egret 5.0.2 * @platform Web,Native * @language zh_CN */ public resume(): void { this.isPaused = false; } /** * @private * 执行一次刷新 */ public update(): void { let t1 = egret.getTimer(); let callBackList = this.callBackList; let thisObjectList = this.thisObjectList; let length = callBackList.length; let requestRenderingFlag = $requestRenderingFlag; let timeStamp = egret.getTimer(); let contexts = lifecycle.contexts; for (let c of contexts) { if (c.onUpdate) { c.onUpdate(); } } if (this.isPaused) { this.lastTimeStamp = timeStamp; return; } this.callLaterAsyncs(); for (let i = 0; i < length; i++) { if (callBackList[i].call(thisObjectList[i], timeStamp)) { requestRenderingFlag = true; } } let t2 = egret.getTimer(); let deltaTime = timeStamp - this.lastTimeStamp; this.lastTimeStamp = timeStamp; if (deltaTime >= this.frameDeltaTime) { this.lastCount = this.frameInterval; } else { this.lastCount -= 1000; if (this.lastCount > 0) { if (requestRenderingFlag) { this.render(false, this.costEnterFrame + t2 - t1); } return; } this.lastCount += this.frameInterval; } this.render(true, this.costEnterFrame + t2 - t1); let t3 = egret.getTimer(); this.broadcastEnterFrame(); let t4 = egret.getTimer(); this.costEnterFrame = t4 - t3; } /** * @private * 执行一次屏幕渲染 */ private render(triggerByFrame: boolean, costTicker: number): void { let playerList = this.playerList; let length = playerList.length; if (length == 0) { return; } this.callLaters(); if ($invalidateRenderFlag) { this.broadcastRender(); $invalidateRenderFlag = false; } for (let i = 0; i < length; i++) { playerList[i].$render(triggerByFrame, costTicker); } $requestRenderingFlag = false; } /** * @private * 广播EnterFrame事件。 */ private broadcastEnterFrame(): void { let list: any[] = DisplayObject.$enterFrameCallBackList; let length = list.length; if (length == 0) { return; } list = list.concat(); for (let i = 0; i < length; i++) { list[i].dispatchEventWith(Event.ENTER_FRAME); } } /** * @private * 广播Render事件。 */ private broadcastRender(): void { let list = DisplayObject.$renderCallBackList; let length = list.length; if (length == 0) { return; } list = list.concat(); for (let i = 0; i < length; i++) { list[i].dispatchEventWith(Event.RENDER); } } /** * @private */ private callLaters(): void { let functionList: any[]; let thisList: any[]; let argsList: any[]; if ($callLaterFunctionList.length > 0) { functionList = $callLaterFunctionList; $callLaterFunctionList = []; thisList = $callLaterThisList; $callLaterThisList = []; argsList = $callLaterArgsList; $callLaterArgsList = []; } if (functionList) { let length: number = functionList.length; for (let i: number = 0; i < length; i++) { let func: Function = functionList[i]; if (func != null) { func.apply(thisList[i], argsList[i]); } } } } /** * @private */ private callLaterAsyncs(): void { if ($callAsyncFunctionList.length > 0) { let locCallAsyncFunctionList = $callAsyncFunctionList; let locCallAsyncThisList = $callAsyncThisList; let locCallAsyncArgsList = $callAsyncArgsList; $callAsyncFunctionList = []; $callAsyncThisList = []; $callAsyncArgsList = []; for (let i: number = 0; i < locCallAsyncFunctionList.length; i++) { let func: Function = locCallAsyncFunctionList[i]; if (func != null) { func.apply(locCallAsyncThisList[i], locCallAsyncArgsList[i]); } } } } } } module egret { export namespace lifecycle { export type LifecyclePlugin = (context: LifecycleContext) => void; /** * @private */ export let stage: egret.Stage; /** * @private */ export let contexts: LifecycleContext[] = []; let isActivate = true; export class LifecycleContext { pause() { if (isActivate) { isActivate = false; stage.dispatchEvent(new Event(Event.DEACTIVATE)); if (onPause) { onPause(); } } } resume() { if (!isActivate) { isActivate = true; stage.dispatchEvent(new Event(Event.ACTIVATE)); if (onResume) { onResume(); } } } onUpdate?: () => void; } export let onResume: () => void; export let onPause: () => void; export function addLifecycleListener(plugin: LifecyclePlugin) { let context = new LifecycleContext(); contexts.push(context); plugin(context); } } /** * 心跳计时器单例 */ export let ticker: sys.SystemTicker = new sys.SystemTicker(); } /** * @private */ declare let egret_stages: egret.Stage[]; if (DEBUG) { egret_stages = []; }