You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
61 lines
1.6 KiB
61 lines
1.6 KiB
import { director, Director } from 'cc';
|
|
|
|
type PendingWait = {
|
|
framesLeft: number;
|
|
done: () => void;
|
|
};
|
|
|
|
/**
|
|
* 业务层帧等待:走 Director 帧事件,不受 Component.unscheduleAllCallbacks 影响;
|
|
* 支持并发排队,避免后一次 waitFrames 覆盖前一次回调。
|
|
*/
|
|
export class FrameFlowHost {
|
|
private _pending: PendingWait[] = [];
|
|
private _listening = false;
|
|
private readonly _onFrame: () => void;
|
|
|
|
constructor() {
|
|
this._onFrame = this._tick.bind(this);
|
|
}
|
|
|
|
waitFrames(frames: number, done: () => void): void {
|
|
if (frames <= 0) {
|
|
done();
|
|
return;
|
|
}
|
|
this._pending.push({ framesLeft: frames, done });
|
|
if (!this._listening) {
|
|
this._listening = true;
|
|
director.on(Director.EVENT_AFTER_UPDATE, this._onFrame, this);
|
|
}
|
|
}
|
|
|
|
dispose(): void {
|
|
if (this._listening) {
|
|
director.off(Director.EVENT_AFTER_UPDATE, this._onFrame, this);
|
|
this._listening = false;
|
|
}
|
|
this._pending.length = 0;
|
|
}
|
|
|
|
private _tick(): void {
|
|
if (this._pending.length === 0) {
|
|
this.dispose();
|
|
return;
|
|
}
|
|
const current = this._pending;
|
|
this._pending = [];
|
|
for (let i = 0; i < current.length; i++) {
|
|
const item = current[i];
|
|
item.framesLeft--;
|
|
if (item.framesLeft <= 0) {
|
|
item.done();
|
|
} else {
|
|
this._pending.push(item);
|
|
}
|
|
}
|
|
if (this._pending.length === 0) {
|
|
this.dispose();
|
|
}
|
|
}
|
|
}
|
|
|