ci / release (push) Successful in 5m5s
ci-platforms / build (amd64, windows, windows-2022) (push) Skipped
ci-platforms / build (arm64, darwin, macos-15) (push) Skipped
ci-platforms / build (amd64, darwin, macos-15-intel) (push) Skipped
ci / checks (push) Successful in 4m41s
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 7m14s
The remaining editor strings and undo step names; component, field, enum, setting, diagnostic and Script API texts under schema.*, enum.*, setting.*, diag.* and api.*; the launcher, the in-game Settings View with a Language setting, the CLI and aego schema show --lang. Every documentation page has a .ru.md translation; the site has a full Russian tree with hreflang, a language switch and ru/llms.txt; aego docs check --lang ru. New doc.tutorial and doc.recipe icons. Fix: an animator restored by a rewind prepares its controller before the replayed step.
76 lines
5.0 KiB
Markdown
76 lines
5.0 KiB
Markdown
---
|
||
id: extensions
|
||
title: Нативные расширения
|
||
---
|
||
# Нативные расширения
|
||
|
||
Проект расширяет движок кодом на Go в `native/`. Он импортирует только `aego/sdk` и реализует `sdk.Module`:
|
||
|
||
type Module struct{}
|
||
|
||
func (Module) Info() sdk.ModuleInfo { return sdk.ModuleInfo{ID: "mygame", Requires: []string{"render2d"}} }
|
||
func (Module) Register(r *sdk.Registry) error { ... }
|
||
|
||
Подсистемы движка (`render2d`, `render3d`, `script`) регистрируются через тот же реестр, поэтому проект может всё, что могут они.
|
||
|
||
## Компоненты
|
||
|
||
Всё о компоненте объявляется одной цепочкой и хранится в его дескрипторе схемы:
|
||
|
||
sdk.Component[Spinner](r, sdk.Name("game.Spinner")).
|
||
Category("Game"). // Inspector section and Add Component group
|
||
Display("Spinner"). // card title, defaults to the humanized type name
|
||
Icon("cat.game"). // icon id from the engine atlas or from r.Icons
|
||
Default(func() Spinner { ... }). // values used by Add Component, Reset and templates
|
||
Requires("engine.SpriteRenderer").// Add Component is disabled until the node has it; templates add it
|
||
SceneUnique(). // at most one per scene
|
||
Script("Speed"). // fields visible to scripts; all fields when omitted, none with ScriptNone()
|
||
Proc0("Reset", fn, sdk.ScriptDoc("...")).
|
||
Template("Spinner", setup). // Create menu entry under the module's submenu; "" uses the type name
|
||
Err()
|
||
|
||
Методы для скриптов объявляются типизированными адаптерами: `Method0..Method2` для функций с результатом (`func(*sdk.ScriptCtx, *Spinner, args...) R`) и `Proc0..Proc2` для функций без него. Скрипты вызывают их как функции модуля `<module id>/<type>`: `import "mygame/spinner"`, затем `spinner.Reset(node)`. `ScriptMethod(name, fn)` с нетипизированной функцией по-прежнему работает в сборках для разработки через рефлексию, пишет предупреждение и не работает в сборках для выпуска.
|
||
|
||
Компонент добавляется одним файлом в модуле и одной строкой в его `Register`, как `registerSpinner(r)` в `examples/native-rotator`.
|
||
|
||
Ошибки регистрации собираются и выводятся вместе при запуске проекта, с id модуля в каждом сообщении.
|
||
|
||
## Системы
|
||
|
||
r.System(sdk.SystemDesc{ID: "mygame.spin", Phase: sdk.PhaseUpdate, System: spinSystem{}})
|
||
|
||
Id систем должны начинаться с id модуля. `FrameBegin`, `PollEvents` и `FrameEnd` зарезервированы за движком.
|
||
|
||
## Шаблоны без компонента
|
||
|
||
r.Template(sdk.TemplateDesc{ID: "mygame.enemy", Name: "Enemy", Category: "Actors", Setup: buildEnemy})
|
||
|
||
`Space` выбирает пространство узла (`sdk.SpaceAny` создаёт узел в пространстве сцены по умолчанию, `sdk.Kind3D` — 3D-узел).
|
||
|
||
## Привязки для скриптов
|
||
|
||
m := r.ScriptModule("mygame/combat")
|
||
sdk.Proc2(m, "Damage", func(c *sdk.ScriptCtx, target sdk.NodeHandle, amount int64) { ... })
|
||
|
||
## Импортёры
|
||
|
||
`sdk.RegisterImporter(r, imp)` добавляет импортёр ассетов. Он есть только в сборках для разработки.
|
||
|
||
## Инструменты редактора
|
||
|
||
Код редактора лежит в файлах с тегом `//go:build aego_editor` и подключается хуком:
|
||
|
||
func registerEditor(r *sdk.Registry) {
|
||
sdk.EditorHook(r, func(e *sdk.EditorRegistry) error {
|
||
e.Inspector("mygame.Health", sdk.InspectorFunc(drawHealth))
|
||
e.Panel(&questPanel{})
|
||
return e.Command(sdk.CommandDesc{...})
|
||
})
|
||
}
|
||
|
||
Положите пустую `registerEditor` в файл с `//go:build !aego_editor`. `EditorRegistry` также предлагает `Gizmo`, `Bounds` (форма компонента для выбора и кадрирования), `Overlay` (рисование на панели «Сцена») и `AssetDrop` (что создаёт брошенный ассет). Паника в любом из них отключает расширение, а редактор продолжает работать.
|
||
|
||
## Иконки
|
||
|
||
`r.Icons(fsys, "mygame.")` добавляет файлы `<id>@<size>x<scale>.png`. Каждый id, который использует `Icon`, должен быть в атласе движка или в зарегистрированном источнике.
|