Решили: dev-инструментов три и они взаимоисключающие полки во весь экран с общим каркасом:
F1 — команды, F2 — лог движка, F3 — витрина боёв. Шапка, тело и подвал у всех троих одинаковые;
кнопки и статус всегда в подвале. Витрина боёв исполняет команды реестра, а не грузит бои сама.
Почему:
- Во весь экран, а не полка на 45% (решение Макса): инструмент открывают, чтобы работать В НЁМ, а кадр под ним всё равно замер — половина экрана уходила ни на что.
- Общий каркас — потому что переключение F1↔F2↔F3 иначе заставляет глаз каждый раз искать кнопки
заново. Стиль
.gm-console*был общим с самого начала, а вот структура разъехалась: у одной полки инструменты были в шапке, у другой статус — отдельной строкой под подвалом. - Взаимоисключение через маркер
IDevOverlayScreen, а не через типы: консоли показываетMenuRouter(UI-слой), витрину — dev-модуль (он знает про контент, UI-слой про бои знать не должен). Общий признак — единственное, что позволяет каждому снять чужую полку, ничего о ней не зная. - Первая колонка витрины — готовая команда (
battle encounter.goblin_raid), а не голый id: её ищут глазами и её же можно перенести в F1 как есть.
Грабли:
GetInitialFocusнавигатора отрабатывает РАНЬШЕ, чем панель примет элемент — поле остаётся без фокуса, клавиши уходят мимо экрана, и Enter выглядит мёртвым при живом обработчике. Лечится тем, что экран фокусирует себя сам наAttachToPanelEventчерезschedule.- Tab и стрелки в UITK — это навигация по фокусу, а не символы. Пока их ловили на поле, фокус
успевал уехать на постороннюю кнопку, и следующий Enter «нажимал» её: со стороны это выглядело как
«консоль сама что-то запустила». Ловим на КОРНЕ экрана в trickle-фазе и гасим
NavigationMoveEvent. - Синтетический
ClickEventне будитButton.clicked(тот слушает pointer-события черезClickable). Проверять кнопки в play-режиме надо вызовом обработчика, иначе тест «нажали» молча ничего не делает и создаёт ложное впечатление поломки. - Ghost-подсказка того же цвета, что ввод, читается как уже введённый текст — то есть врёт о состоянии поля. Нужен и цвет тусклее, и padding, совпадающий с полем: на моно-шрифте это делает её продолжением строки, а не вторым слоем.
- Колонки таблицы обязаны иметь одинаковую ширину в шапке и в строках (общий класс на пару), иначе таблица разъезжается на первой длинной строке.
Владелец правды: Scripts/UI/DevConsole/ (консоль, лог, маркер полки),
Scripts/DevTools/DevBattleBrowserScreen.cs (витрина), MenuRouter.CloseDevOverlays,
секция «ЕДИНЫЙ КАРКАС DEV-ПОЛОК» в UI/Theme/components.uss, клавиши — Game/Input/InputService.cs.