import { GameObject, SupportComponent } from '@gedit/runtime-render'; import { PluginPureHook, BlockPair } from '@gedit/runtime-compiler'; import { local } from './local'; import { global } from './global'; export namespace code { export const prod = false; /** * 部分类型的渲染实体需要变化 * @param type 渲染类型 * @returns 实体渲染类型 */ function translate(type: SupportComponent): string { switch (type) { case SupportComponent.frames: return SupportComponent.sprite; case SupportComponent.group: return 'container'; default: return type; } } export function create(cmp: GameObject): string { return `this.${cmp.hidden ? 'make' : 'add'}.${translate(cmp.displayType)}`; } export function createAnimation(): string { return 'this.scene.scene.anims.create'; } type Param = number | boolean | string; interface Config { [key: string]: Param | Config; } export type MayParamOrConfig = Param | Config; interface CompilingData { properties: Map; functions: Map; ctorParams: Param[]; local: boolean; comments: boolean; } export class ComponentPrinter { private _param(p: Param): string { return typeof p === 'string' ? `'${p}'` : p.toString(); } private _params(ps: Param[]): void { this.ctx.print(`${ps.map(p => this._param(p)).join(', ')}`); } private _local(): void { this.ctx.print(`const ${local.COMPONENT} = `); } private _addInstance(): void { this.ctx.println( `${global.GAME_OBJECT_MAP}.set(${this._param(this.object.id)}, ${ local.COMPONENT });` ); } private _comments(): void { const { displayType, name } = this.object; this.ctx.comment(`@type ${displayType}\n@name ${name}`); } private _ctor(params: Param[]): void { // this.add.sprite this.ctx.print(`${create(this.object)}`); // (...) properties this.ctx.print('('); this._params(params); this.ctx.println(')'); } private _object( config: Config, key?: string, first: boolean = true, ): void { const ctx = this.ctx; if (key) { ctx.print(`${key}: `); } if (Array.isArray(config)) { ctx.push(BlockPair.bracket); this._object(config, key, false); } else { ctx.push(); Object.keys(config).forEach(str => { const value = config[str]; if ( typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string' ) { ctx.println(`${str}: ${this._param(value)},`); } else { this._object(value, str, false); } }); } ctx.pop(false); if (!first) { ctx.println(','); } } private _setProperties( props: Map, needLocal: boolean ): void { if (props.size === 0) { return; } if (needLocal) { this.ctx.print(`${local.COMPONENT}`); } let first = needLocal ? true : false; props.forEach((params, key) => { this.ctx.print( `${first ? '' : ' '}.set${key.replace(/^\S/, s => s.toUpperCase() )}(` ); this._params(params); this.ctx.println(')'); first = false; }); } private _callFunction(funcName: string, config: Config): void { this.ctx.print(`.${funcName}(`); this._object(config); this.ctx.println(');'); } private _data: CompilingData; constructor(protected ctx: PluginPureHook, protected object: T) { this._data = { properties: new Map(), functions: new Map(), ctorParams: [], local: false, comments: false, }; } ctor(...params: Param[]): ComponentPrinter { this._data.ctorParams = params; return this; } local(): ComponentPrinter { this._data.local = true; return this; } comments(): ComponentPrinter { this._data.comments = true; return this; } tranform(): ComponentPrinter { // todo return this; } isolate(callback: () => void): void { this.ctx.push(); callback(); this.ctx.pop(); } ref(): E { const raw = this._data; // @ts-ignore const proxy: E = new Proxy(raw, { get: (target, prop) => { if (typeof prop !== 'string') { throw new Error('type error'); } if (prop.indexOf('set') === 0) { const propKey = prop .replace('set', '') .replace(/^\S/, s => s.toLowerCase()); return (...args: Param[]) => { target.properties.set(propKey, args); return proxy; }; } else { return (config: Config) => { target.functions.set(prop, config); return proxy; }; } }, }); return proxy; } flush(): void { const { local: needLocal, ctorParams, properties, functions, comments } = this._data; if (comments) { this._comments(); } if (needLocal) { this._local(); } this._ctor(ctorParams); if (needLocal) { this._addInstance(); } this._setProperties(properties, needLocal); functions.forEach((func, name) => { this.ctx.print(`${local.COMPONENT}`); this._callFunction(name, func); }); } } export function print( ctx: PluginPureHook, component: T ): ComponentPrinter { return new ComponentPrinter(ctx, component); } }