@senspark/ee
Version:
utility library for cocos creator
160 lines (129 loc) • 4.66 kB
text/typescript
import assert = require('assert');
import { DialogManager } from './DialogManager';
const { ccclass, disallowMultiple, menu } = cc._decorator;
type DialogEvent = (dialog: Dialog) => void;
type Transition = cc.FiniteTimeAction;
export enum DialogEventType {
WillShow,
DidShow,
WillHide,
DidHide,
}
export class Dialog extends cc.Component {
private active: boolean;
/** Used to run transtitions. */
private actor: cc.Node;
private showingTransitions: Transition[];
private hidingTransitions: Transition[];
private eventDictionary: { [key: number]: DialogEvent[] };
protected manager?: DialogManager;
public constructor() {
super();
this.active = false;
this.actor = new cc.Node();
this.showingTransitions = [];
this.hidingTransitions = [];
this.eventDictionary = {};
}
public onLoad(): void {
this.node.addChild(this.actor);
}
public getContainer(): cc.Node {
return this.node.parent;
}
/** Shows this dialog using the specified dialog manager. */
public show(manager: DialogManager): void {
const container = new cc.Node();
container.setContentSize(cc.winSize);
container.addChild(this.node);
container.addComponent(cc.BlockInputEvents);
this.manager = manager;
manager.pushDialog(this);
}
/** Hides this dialog using the current dialog manager. */
public hide(): void {
const manager = this.manager;
assert(manager !== undefined);
if (manager !== undefined) {
manager.popDialog(this);
}
}
/** Attempts to show the specified dialog using the current dialog manager. */
public showDialog(dialog: Dialog): void {
const manager = this.manager;
if (manager === undefined) {
assert(false, 'The current dialog is not active.');
return;
}
dialog.show(manager);
}
/** Checks whether this dialog is active. */
public isActive(): boolean {
return this.active;
}
/** Sets this dialog to be active. */
public setActive(active: boolean): void {
this.active = active;
}
/** Adds a will-show event. */
public onWillShow(event: DialogEvent): this {
return this.addEvent(DialogEventType.WillShow, event);
}
/** Adds a did-show event. */
public onDidShow(event: DialogEvent): this {
return this.addEvent(DialogEventType.DidShow, event);
}
/** Adds a will-hide event. */
public onWillHide(event: DialogEvent): this {
return this.addEvent(DialogEventType.WillHide, event);
}
/** Adds a did-hide event. */
public onDidHide(event: DialogEvent): this {
return this.addEvent(DialogEventType.DidHide, event);
}
/** Adds a showing transition. */
public addShowingTransition(transition: Transition): this {
this.showingTransitions.push(transition);
return this;
}
/** Adds a hiding transition. */
public addHidingTransition(transition: Transition): this {
this.hidingTransitions.push(transition);
return this;
}
public playShowingTransition(callback: () => void): void {
this.playTransition(this.showingTransitions, callback);
}
public playHidingTransition(callback: () => void): void {
this.playTransition(this.hidingTransitions, callback);
}
private playTransition(actions: Transition[], callback: () => void): void {
assert(this.actor.getNumberOfRunningActions() === 0);
this.actor.stopAllActions();
const transitions = [] as Transition[];
actions.forEach(action => transitions.push(...[
cc.delayTime(0), // Add dummy action to prevent callback runs twice.
cc.targetedAction(this.node, action),
]));
transitions.push(cc.callFunc(callback));
this.actor.runAction(actions.length === 0
? cc.callFunc(callback)
: cc.sequence(transitions));
}
public addEvent(type: DialogEventType, event: DialogEvent): this {
const events = this.getEvents(type);
events.push(event);
return this;
}
/** Processes all events for the specified event type. */
public processEvent(type: DialogEventType): void {
const events = this.getEvents(type);
events.forEach(event => event(this));
}
private getEvents(type: DialogEventType): DialogEvent[] {
return this.eventDictionary[type] = this.eventDictionary[type] || [];
}
}