Для кого: авторы модулей, расширяющих engine через EngineExtension и ExtensionsService.
Что получите: lifecycle расширения, свой Stencil, типизированный getModule, сквозной пример.
Предварительные знания: Быстрый старт, Как создавать библиотеки.
Внешние расширения — модули, наследующие EngineExtension. Каждое расширение получает собственный экземпляр Stencil и ссылку на eulerEngine. Регистрация — через ExtensionsService и eulerEngine.registerExtensionService().
import { EngineExtension, ExternalModuleOptions } from "@engine/index"
import { Library } from "@engine/services/Stencil/libs/Library"
import { MyShape } from "./shapes/MyShape"
const myLib = new Library("Моя библиотека", [MyShape])
export class MyExtension extends EngineExtension {
constructor(options: ExternalModuleOptions) {
super(options)
}
loadStencil() {
this.stencil.register(myLib)
this.stencil.loadLibs()
}
doSomething() {
this.eulerEngine.render()
}
dispose(): void {
super.dispose() // dispose stencil
}
}
EngineExtension создаёт this.stencil = new Stencil(eulerEngine) — отдельный от глобального eulerEngine.services.Stencil (если он включён).
import { MyExtension } from "./MyExtension"
export const ExtensionClasses = {
MyExtension,
} as const
as const обязателен для точной типизации ключей.
import * as ExtensionClasses from "./index"
export const engineExtensionService =
EulerGraph.registerExternalModules<typeof ExtensionClasses>(ExtensionClasses)
const myExt = engineExtensionService.getModule("MyExtension")
// MyExtension | undefined
myExt?.doSomething()
ExtensionsService.T из текущей сессии регистрации.// Идеальное автодополнение: mockService «знает» только про моки,
// а engineExtensionService — только про боевые модули.
const mockService =
EulerGraph.registerExternalModules<typeof MockClasses>(MockClasses)
const engineExtensionService =
EulerGraph.registerExternalModules<typeof ExtensionClasses>(ExtensionClasses)
| Этап | Действие |
|---|---|
| Старт host | registerExtensionService → registerModules |
| После Stencil host | extension.loadStencil() |
| Shutdown | engineExtensionService.dispose() — dispose всех модулей |
| Модуль | super.dispose() — освобождает stencil |
Класс shape должен иметь static readonly typeName и быть в Library, которую регистрирует extension stencil:
export class GaugeShape extends CellParametric {
static readonly typeName: string = "GaugeShape"
// ...
}
Library.register → eulerGraph.registerElement для каждого shape. См. typeName и сериализация cell-классов.
Классы фигур для Stencil должны объявлять static readonly typeName — см. typeName и сериализация cell-классов.
Имена модулей в Map совпадают с ключами ExtensionClasses. Свойство name экземпляра перезаписывается при регистрации — не полагайтесь на значение внутри класса.
ExtensionsService.dispose() освобождает все зарегистрированные модули.
getRegisteredModulesNames() — список ключей для отладки.
Extension Stencil и global Stencil — разные экземпляры; библиотеки extension регистрируйте через extension.stencil, не путайте с eulerEngine.services.Stencil.
src/renderer/src/external_modules/ — инициализация engineExtensionServicesrc/engine/services/ExtensionsService/EngineExtension.ts