19 KiB
02. UX редактора и повседневный workflow
Статус на 18.09.2026. Исследование и проектные решения, не описание реализованного движка. Канонические решения — ARCHITECTURE.md, порядок до и после MVP — PLAN.md. Сведения о других движках сохраняются как исследовательский контекст; прежние рекомендации, помеченные superseded, не задают стек Faset.
Принята собственная retained UI-система на C++: декларативные layout/styles, тёмная тема по умолчанию, schema-driven Inspector. ImGui используется для debug tools. Ни UI Toolkit Unity, ни Qt/web UI не являются выбранной основой. Описанные ниже расширенные инструменты — backlog; граница MVP определяется планом.
1. Основная UX-гипотеза
Пользователь движка не хочет «управлять ECS». Он хочет ответить на вопросы:
- где находится объект;
- из чего он состоит;
- почему он выглядит/движется именно так;
- что произойдет, если я изменю параметр;
- как вернуться назад;
- что попадет в экспорт.
Поэтому хороший UX строится вокруг объекта, намерения и обратной связи, а не вокруг внутренней терминологии engine.
2. Главный цикл: observe → edit → run → inspect → repeat
Время цикла — главный product metric личного движка:
1. Open project
2. Find/create scene
3. Add entity or prefab
4. Select it
5. Change one property
6. Press Play / run current scene
7. Observe game
8. Read editor/build diagnostics or debug the Player separately
9. Stop safely; edit scene remains independent
10. Save and export
Каждый шаг должен иметь одну очевидную точку входа. Если для добавления Sprite нужно вручную создать entity, зарегистрировать component type, загрузить texture и прописать renderer binding — это внутренний API, а не UX.
Метрики
Отслеживать без телеметрии пользователя, локально:
- first pixel: от Create Project до первого кадра;
- first interaction: до управляемого объекта;
- edit-to-visible: от изменения Inspector до результата;
- error-to-cause: от красной ошибки до исправления;
- clean export: от проекта до запускаемого build;
- recovery: насколько легко отменить ошибку.
Целевые значения для MVP лучше задать позже после baseline, но каждый релиз должен уменьшать хотя бы один цикл.
3. Информационная архитектура редактора
Стартовый layout:
┌ Project / Scene tabs / Play / Stop / Build ┐
├────────────┬──────────────────────────┬─────────────┤
│ Scene Tree │ Scene View │ Inspector │
│ │ 2D | 3D | Game | Debug │ │
├────────────┴──────────────────────────┴─────────────┤
│ Asset Browser | Console | Profiler | History │
└──────────────────────────────────────────────────────┘
Панели не должны быть обязательным лабиринтом: сохранить workspace per role (programmer, designer, debugger), tabs и reset layout. Главные действия доступны меню и keyboard shortcuts; mouse-only workflow недопустим.
Полезные концепции из Godot:
- Scene Tree и FileSystem дают две разные оси: composition и assets;
- Inspector автоматически показывает свойства выбранного объекта, поддерживает поиск, секции, revert и sub-resources (Inspector Dock);
- Project Settings группирует общие настройки, Input Map, Localization, Globals, Plugins и Import Defaults, имеет поиск и reset (Project Settings).
Новый движок должен повторить эти mental models, но сделать их более согласованными с command journal и automation tools.
4. Scene Tree и selection
Scene Tree — не просто список entity IDs. Он должен показывать:
- display name + stable ID по запросу;
- prefab/scene boundary;
- disabled/hidden/locked state;
- missing component/resource badges;
- parent/child transform relation;
- только authoring objects; runtime hierarchy не является частью MCP/Scene Tree MVP;
- search by name, type, tag, component, asset reference.
Selection — глобальный контекст editor. Выделение в Scene View, Tree, Asset Browser и Inspector синхронно. Multi-select должен позволять массовое изменение через transaction с preview.
Не полагаться только на hierarchy: для больших сцен нужен flat search/results view и reverse reference view «кто использует этот asset/entity». Hierarchy удобна для transform и чтения композиции, но не является полноценной базой данных.
5. Inspector: главный ergonomic leverage
Inspector строится по общей явной C++ metadata schema (TypeId/FieldId) для компонента, ресурса и editor-only данных.
Каждое поле имеет:
- label + tooltip с единицами измерения;
- valid range/enum и validation message;
- default, current и inherited value;
- source: template/scene/instance и provenance импортированной основы;
- reset/revert;
- copy path / copy value;
- searchable category;
- optional advanced section;
- link to references and documentation.
Важно отличать:
invalid value → не принять или показать inline error
valid but risky → принять, warning и explain
valid override → показать source и revert
Player state → отдельная сессия; source меняется только authoring-командой
Godot показывает revert icon для измененных относительно оригинала значений и умеет делать sub-resources unique (Inspector Dock). Unity Prefab Mode использует context/isolation и breadcrumb, чтобы автор понимал, редактирует ли asset или instance (Editing Prefab Mode). Для нового движка критичен аналогичный source breadcrumb:
Level01 > Player instance > Weapon prefab > Transform
6. Scene View и gizmos
Общие требования
- frame selected, focus, orbit/pan/zoom;
- snapping и привязки с понятным modifier;
- local/world pivot;
- визуальные bounds/colliders/nav/audio;
- solo/isolate, hide, lock;
- orthographic/perspective toggle;
- camera bookmarks;
- safe preview before commit;
- одинаковые shortcuts для 2D и 3D, где это возможно.
2D
- canvas coordinates, pixels/world units и origin видимы;
- zoom не меняет смысл snapping;
- tilemap, sprite pivot, nine-patch и z/layer order редактируются в контексте;
- draw order объясним: layer, z-index, material/order override.
3D
- transform gizmo и numeric entry;
- grid и axis labels;
- frustum/camera preview;
- selection outline и object bounds;
- light/physics probes как debug overlays, не как неявные runtime objects.
Hybrid
Переключатель должен быть не «2D editor против 3D editor», а режимом представления: 2D camera view, 3D perspective, game preview. Один world может иметь Sprite2D и Mesh3D.
7. Commands, undo/redo и история
Любое изменение через UI — команда:
SetProperty(documentId, objectAddress, componentId, fieldId, newValue, expectedRevision)
AddComponent(objectAddress, componentId, typeId, initialData)
Instantiate(prefabId, parentId, instanceId)
Delete(selection, reversiblePayload)
Команды группируются в transaction («переместить объект мышью» — один undo, а не сотни micro-steps). История содержит timestamp, source (Inspector, MCP, script, importer) и human-readable summary.
Требования:
- undo/redo работает в Scene Tree, Inspector, import settings и material editor;
- destructive action имеет preview/confirmation или reversible trash;
- изменения Player не попадают в edit history; обратный Apply из runtime не входит в MVP;
- autosave и recovery snapshot не уничтожают undo history;
- command journal экспортируется для воспроизведения bug.
8. Play Mode и hot reload
Принятый Play запускает отдельный Player со snapshot редактируемой сцены и статически собранным gameplay:
Edit document → validated snapshot → separate Player → Stop
↓ ↓
Further authoring edits temporary runtime state
Сцена может продолжать редактироваться независимо от snapshot запуска; для применения её новой версии к игре выполняется новый запуск. Начальный цикл C++: Stop → incremental build → Play. Редактор сохраняет контекст проекта и показывает ошибки компиляции с файлом и строкой. Кнопки MVP — Play, Stop, Restart, Pause и single-step; специальные runtime debugger UI относятся к дальнейшим инструментам. Управление сессией не предоставляет MCP доступ к runtime world.
MCP вызывает editor Play/Stop, импорт и build, читает authoring state и editor logs. Он не получает runtime hierarchy, значения компонентов Player, runtime mutation tools или MCP endpoint в игре. Отдельная диагностика Player не превращается в MCP bridge.
Историческое сравнение, superseded для MVP Faset: Godot поддерживает remote scene inspection, изменение параметров живой игры и reload (debugging overview). Ранее здесь предлагались live edits и Apply выбранных runtime changes обратно в source. Эти сценарии не входят в принятый первый цикл; универсальный state-preserving native hot reload также отложен.
Shader/data reload можно исследовать отдельно после надёжного жизненного цикла ресурсов. Lua — обязательный последующий этап, его reload требует собственного контракта.
9. Debugging UX: от симптома к причине
Следующие вопросы задают направление будущих локальных debug tools. Это исследовательский backlog после базовой диагностики MVP; runtime-инспекция не предоставляется через MCP.
«Почему объекта нет?»
Один action Explain Visibility показывает:
- entity active/disabled;
- parent visibility/layer;
- camera/frustum result;
- renderer extraction status;
- missing/failed asset;
- material/shader failure;
- draw pass and culling reason.
«Почему объект движется неправильно?»
Показать:
- owning systems;
- last writer per property;
- fixed vs variable tick;
- physics body mapping;
- incoming commands/events;
- transform parent chain;
- timeline of values.
«Почему frame slow?»
Показать hierarchy:
Frame 16.6 ms
Systems 4.1 ms
Physics 2.8 ms
Render extraction 1.2 ms
GPU passes 7.4 ms
Asset/IO 0.3 ms
Нужны toggles для collision shapes, bounds, nav, lights, overdraw/draw calls и entity IDs. Godot предоставляет debugger/profilers, remote inspection и визуализацию collision/navigation (debugging tools); Unity Frame Debugger умеет остановить кадр и пошагово показывать render events (Frame Debugger); Unreal Insights строит трассу CPU/gameplay/cook channels (Insights reference). Новому движку стоит взять эти идеи с единым correlation ID.
10. Asset Browser и project hygiene
Asset Browser должен показывать не только thumbnails:
- тип, размер, импортированный статус;
- dependency/reverse-dependency graph;
- source path и AssetId;
- importer settings;
- platform variants;
- cache status;
- errors/warnings;
- usages и open-in-context.
Drag-and-drop создает предсказуемый результат: texture в Sprite добавляет/заменяет компонент или resource, а не молча копирует файл. При rename сохраняется AssetId и обновляется registry path; устойчивые ссылки не переписываются ради нового имени. Редактор показывает реально изменённые файлы.
Source control awareness полезна и в solo project: modified/untracked/generated/conflict badges. Unreal встроенно показывает checkout/history/diff и может checkout on save (Source Control); Новый движок может начать с простого read-only Git status и текстовых diff.
11. Input UX
В gameplay коде не использовать raw Key.W как единственный API. Использовать named actions:
Move (Vector2)
Look (Vector2)
Jump (Button)
Interact (Button)
Action Map хранит bindings для keyboard, mouse, gamepad, touch и rebinding. UI navigation — отдельный context с приоритетом над gameplay. Godot InputMap управляет actions и несколькими InputEvents, включая deadzone (InputMap); Unity Input System строит named actions и UI events поверх action asset (Runtime UI event system).
Editor должен показывать live input monitor: action, raw device event, resolved value, active context и deadzone. Это устраняет классическую ошибку «клавиша работает в editor, но не в game».
12. Accessibility и cognitive load
Даже internal editor должен иметь:
- keyboard-first command palette;
- все действия с menu/shortcut и discoverability;
- масштабируемый UI и high contrast;
- не использовать цвет как единственный сигнал;
- readable error text и copyable diagnostics;
- focus order и screen-reader labels для важных controls;
- reduced motion в editor preview;
- единые единицы/локализация чисел;
- сохраненные workspace и пользовательские shortcuts.
UX «удобного личного движка» — не меньше функций, а меньше скрытого состояния, модальных ловушек и неочевидных разрушительных операций.
13. Шаблоны и Blender: принятые границы UX
Вложенный экземпляр явно отделён в дереве; Inspector показывает источник, локальный override и Revert. В MVP доступны field overrides, добавление объектов/компонентов, suppression и reparent внутри одного экземпляра; перенос через nested boundary, variant inheritance и Apply to template отложены. Patch использует instance chain/ObjectId/ComponentId/FieldId; display name и transform path не заменяют ID. Удалённая цель и несовместимая схема дают конфликт с сохранением пользовательских данных. Полные правила.
Обычный официальный Blender не модифицируется. Стандартный импорт glTF/GLB работает без дополнений. Необязательный Python add-on упрощает экспорт, сохраняет source IDs и manifest; без устойчивых IDs нельзя гарантировать matching внутренних частей после rename/reorder. Gameplay, physics settings и instance overrides принадлежат Faset и не перезаписываются новым экспортом.