import { ScriptReference, ScriptContext, ScriptManager } from './script'; import { GameConfig, GameObjectData } from '@gedit/render-engine'; import { MaybePromise } from '@gedit/utils'; import { OutputType } from './external'; export interface PluginEnable { spine: boolean; dragonbones: boolean; } export interface PluginContext { width: number; height: number; element: string; engine: string; config: GameConfig; newLine: boolean; plugins: PluginEnable; toBrowserUrl: (url: string) => Promise, type: OutputType; scripts: ScriptManager; store: Map; } export interface PluginHookThisArgs { ctx: PluginContext; output: string; addScript: (id?: Symbol | string) => Symbol; getScript: (id: Symbol | string) => ScriptReference; getScriptContext: (id: Symbol | string) => ScriptContext; useScript: (id: Symbol | string) => void; // addExport: (scriptExt: ScriptExport) => void; setValue: (key: string | number, value: D) => void; getValue: (key: string | number) => D; print: (str: string) => void; println: (str: string) => void; echo: (v: string) => void; undo: () => void; push: (type?: BlockPair, newLine?: boolean) => void; pop: (newLine?: boolean) => void; identifier: (...args: string[]) => string; func: (name: string) => void; comment: (comments: string) => void; } export type PluginPureHook = PluginHookThisArgs; export interface Plugin { onParse?: (this: PluginHookThisArgs) => MaybePromise; onParsed?: (this: PluginHookThisArgs) => MaybePromise; onCompile?: (this: PluginHookThisArgs) => MaybePromise; onCompiled?: (this: PluginHookThisArgs) => MaybePromise; onPrint?: (this: PluginHookThisArgs) => MaybePromise; onPrinted?: (this: PluginHookThisArgs) => MaybePromise; } export function initContext(): PluginContext { return { width: 0, height: 0, element: '', engine: '', config: {} as any, newLine: true, type: OutputType.html, plugins: { spine: false, dragonbones: false, }, toBrowserUrl: async s => s, scripts: new ScriptManager(), store: new Map(), }; } export type MaybeArg = string | number | object | GameObjectData | undefined; export enum BlockPair { // { } braces = 1, // [ ] bracket, // ( ) Parentheses, // space Space, } export function onion( funcs: (Function | undefined | null)[], ctx: PluginContext = initContext(), ): (...args: MaybeArg[]) => Promise { const { scripts, store } = ctx; return async (...args: MaybeArg[]) => { for (const func of funcs) { if (!func) { continue; } const thisArgs: PluginHookThisArgs = { ctx, get output(): string { return scripts.main.printer.output; }, addScript: (id?: Symbol) => scripts.addScript(id), getScript: (id: Symbol) => scripts.getScript(id).ref, getScriptContext: (id: Symbol) => scripts.getScript(id), useScript: (id: Symbol) => scripts.changeToScript(id), setValue: (key: string, value: D) => store.set(key, value), getValue: (key: string) => store.get(key) as D, print: (v: string) => scripts.current.printer.echo(v), println: (v: string) => scripts.current.printer.echo(v + '\n'), echo: (v: string) => scripts.current.printer.echo(v), undo: () => scripts.current.printer.undo(), push: (type?: BlockPair, newLine?: boolean) => scripts.current.printer.push(type, newLine), pop: (newLine?: boolean) => scripts.current.printer.pop(newLine), func: (name: string) => scripts.current.spec.func(name), comment: (comments: string) => scripts.current.spec.comment(comments), identifier: (...iargs: string[]) => scripts.current.identifier(...iargs), }; await func.call(thisArgs, ...args); scripts.resetToMain(); } }; }