{"version":3,"file":"SystemManager.js","sources":["../../src/system/SystemManager.ts"],"sourcesContent":["import { Runner } from '@pixi/runner';\nimport { EventEmitter } from '@pixi/utils';\n\nimport type { IRenderer } from '../IRenderer';\nimport type { ISystem, ISystemConstructor } from './ISystem';\n\ninterface ISystemConfig<R>\n{\n    runners: string[],\n    systems: Record<string, ISystemConstructor<R>>\n    priority: string[];\n}\n\n/**\n * The SystemManager is a class that provides functions for managing a set of systems\n * This is a base class, that is generic (no render code or knowledge at all)\n * @memberof PIXI\n */\nexport class SystemManager<R=IRenderer> extends EventEmitter\n{\n    /** a collection of runners defined by the user */\n    readonly runners: {[key: string]: Runner} = {};\n\n    private _systemsHash: Record<string, ISystem> = {};\n\n    /**\n     * Set up a system with a collection of SystemClasses and runners.\n     * Systems are attached dynamically to this class when added.\n     * @param config - the config for the system manager\n     */\n    setup(config: ISystemConfig<R>): void\n    {\n        this.addRunners(...config.runners);\n\n        // Remove keys that aren't available\n        const priority = (config.priority ?? []).filter((key) => config.systems[key]);\n\n        // Order the systems by priority\n        const orderByPriority = [\n            ...priority,\n            ...Object.keys(config.systems)\n                .filter((key) => !priority.includes(key))\n        ];\n\n        for (const i of orderByPriority)\n        {\n            this.addSystem(config.systems[i], i);\n        }\n    }\n\n    /**\n     * Create a bunch of runners based of a collection of ids\n     * @param runnerIds - the runner ids to add\n     */\n    addRunners(...runnerIds: string[]): void\n    {\n        runnerIds.forEach((runnerId) =>\n        {\n            this.runners[runnerId] = new Runner(runnerId);\n        });\n    }\n\n    /**\n     * Add a new system to the renderer.\n     * @param ClassRef - Class reference\n     * @param name - Property name for system, if not specified\n     *        will use a static `name` property on the class itself. This\n     *        name will be assigned as s property on the Renderer so make\n     *        sure it doesn't collide with properties on Renderer.\n     * @returns Return instance of renderer\n     */\n    addSystem(ClassRef: ISystemConstructor<R>, name: string): this\n    {\n        const system = new ClassRef(this as any as R);\n\n        if ((this as any)[name])\n        {\n            throw new Error(`Whoops! The name \"${name}\" is already in use`);\n        }\n\n        (this as any)[name] = system;\n\n        this._systemsHash[name] = system;\n\n        for (const i in this.runners)\n        {\n            this.runners[i].add(system);\n        }\n\n        /**\n         * Fired after rendering finishes.\n         * @event PIXI.Renderer#postrender\n         */\n\n        /**\n         * Fired before rendering starts.\n         * @event PIXI.Renderer#prerender\n         */\n\n        /**\n         * Fired when the WebGL context is set.\n         * @event PIXI.Renderer#context\n         * @param {WebGLRenderingContext} gl - WebGL context.\n         */\n\n        return this;\n    }\n\n    /**\n     * A function that will run a runner and call the runners function but pass in different options\n     * to each system based on there name.\n     *\n     * E.g. If you have two systems added called `systemA` and `systemB` you could call do the following:\n     *\n     * ```js\n     * system.emitWithCustomOptions(init, {\n     *     systemA: {...optionsForA},\n     *     systemB: {...optionsForB},\n     * });\n     * ```\n     *\n     * `init` would be called on system A passing `optionsForA` and on system B passing `optionsForB`.\n     * @param runner - the runner to target\n     * @param options - key value options for each system\n     */\n    emitWithCustomOptions(runner: Runner, options: Record<string, unknown>): void\n    {\n        const systemHashKeys = Object.keys(this._systemsHash);\n\n        runner.items.forEach((system) =>\n        {\n            // I know this does not need to be a performant function so it.. isn't!\n            // its only used for init and destroy.. we can refactor if required..\n            const systemName = systemHashKeys.find((systemId) => this._systemsHash[systemId] === system);\n\n            system[runner.name](options[systemName]);\n        });\n    }\n\n    /** destroy the all runners and systems. Its apps job to */\n    destroy(): void\n    {\n        Object.values(this.runners).forEach((runner) =>\n        {\n            runner.destroy();\n        });\n\n        this._systemsHash = {};\n    }\n\n    // TODO implement!\n    // removeSystem(ClassRef: ISystemConstructor, name: string): void\n    // {\n\n    // }\n}\n"],"names":["EventEmitter","Runner","runner"],"mappings":";;AAkBO,MAAM,sBAAmCA,MAAAA,aAChD;AAAA,EADO,cAAA;AAAA,UAAA,GAAA,SAAA,GAGH,KAAS,UAAmC,IAE5C,KAAQ,eAAwC;EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjD,MAAM,QACN;AACS,SAAA,WAAW,GAAG,OAAO,OAAO;AAGjC,UAAM,YAAY,OAAO,YAAY,CAAI,GAAA,OAAO,CAAC,QAAQ,OAAO,QAAQ,GAAG,CAAC,GAGtE,kBAAkB;AAAA,MACpB,GAAG;AAAA,MACH,GAAG,OAAO,KAAK,OAAO,OAAO,EACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,SAAS,GAAG,CAAC;AAAA,IAAA;AAGhD,eAAW,KAAK;AAEZ,WAAK,UAAU,OAAO,QAAQ,CAAC,GAAG,CAAC;AAAA,EAE3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,WACd;AACc,cAAA,QAAQ,CAAC,aACnB;AACI,WAAK,QAAQ,QAAQ,IAAI,IAAIC,cAAO,QAAQ;AAAA,IAAA,CAC/C;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UAAU,UAAiC,MAC3C;AACU,UAAA,SAAS,IAAI,SAAS,IAAgB;AAE5C,QAAK,KAAa,IAAI;AAElB,YAAM,IAAI,MAAM,qBAAqB,IAAI,qBAAqB;AAGjE,SAAa,IAAI,IAAI,QAEtB,KAAK,aAAa,IAAI,IAAI;AAE1B,eAAW,KAAK,KAAK;AAEjB,WAAK,QAAQ,CAAC,EAAE,IAAI,MAAM;AAmBvB,WAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,sBAAsBC,SAAgB,SACtC;AACI,UAAM,iBAAiB,OAAO,KAAK,KAAK,YAAY;AAE7C,IAAAA,QAAA,MAAM,QAAQ,CAAC,WACtB;AAGU,YAAA,aAAa,eAAe,KAAK,CAAC,aAAa,KAAK,aAAa,QAAQ,MAAM,MAAM;AAE3F,aAAOA,QAAO,IAAI,EAAE,QAAQ,UAAU,CAAC;AAAA,IAAA,CAC1C;AAAA,EACL;AAAA;AAAA,EAGA,UACA;AACI,WAAO,OAAO,KAAK,OAAO,EAAE,QAAQ,CAACA,YACrC;AACI,MAAAA,QAAO,QAAQ;AAAA,IAAA,CAClB,GAED,KAAK,eAAe;EACxB;AAAA;AAAA;AAAA;AAAA;AAOJ;;"}