Редактор темы: создать, проверить и сохранить ресурс
Готовый генератор .rdata, редактор элементов и вариаций, предпросмотр и перенос темы между уровнями.
Получить редактируемый файл
Добавьте UiSampleStyle.cs и ThemeAssetBuilder.cs в C#-проект. Прикрепите ThemeAssetBuilder к корню Control отдельного уровня, соберите и запустите F6.
Нажмите Создать, если файла ещё нет. Ожидается Error.Ok и asset://UI/DemoTheme.rdata. Повторное создание возвращает AlreadyExists и сохраняет ваши правки. Загрузить тему для этой кнопки перечитывает ресурс и назначает вариацию ActionButton. AssetPath — путь, заданный разработчиком проекта, а не обработчик произвольного пользовательского ввода.
ThemeAssetBuilder.cs
using Reckfell;
public partial class ThemeAssetBuilder : Control
{
[Export] public string AssetPath { get; set; } = "asset://UI/DemoTheme.rdata";
public Theme? LoadedTheme { get; private set; }
public Label Status { get; private set; } = null!;
public override void _Ready()
{
UiSampleStyle.Prepare(this);
var column = new VBoxContainer { Position = new Vector2(24, 24) }; AddChild(column);
Status = new Label { Text = AssetPath }; column.AddChild(Status);
var create = new Button { Text = UiSampleStyle.Text("Создать, если файла ещё нет", "Create only if absent") }; column.AddChild(create);
create.Pressed += () => Status.Text = CreateAsset().ToString();
var preview = new Button { Text = UiSampleStyle.Text("Загрузить тему для этой кнопки", "Load this button's theme") }; column.AddChild(preview);
preview.Pressed += () =>
{
if (!FileAccess.FileExists(AssetPath)) { Status.Text = Error.FileNotFound.ToString(); return; }
LoadedTheme = ResourceLoader.Load<Theme>(AssetPath, cacheMode: ResourceLoader.CacheMode.Ignore);
if (LoadedTheme is null) { Status.Text = Error.FileUnrecognized.ToString(); return; }
preview.Theme = LoadedTheme; preview.ThemeTypeVariation = "ActionButton"; Status.Text = AssetPath;
};
}
public Error CreateAsset()
{
if (!AssetPath.StartsWith("asset://") && !AssetPath.StartsWith("user://")) return Error.InvalidParameter;
if (!AssetPath.EndsWith(".rdata")) return Error.InvalidParameter;
if (FileAccess.FileExists(AssetPath)) return Error.AlreadyExists;
string directory = ProjectSettings.GlobalizePath(AssetPath.GetBaseDir());
Error error = DirAccess.MakeDirRecursiveAbsolute(directory);
if (error != Error.Ok) return error;
var theme = UiSampleStyle.Create();
theme.SetTypeVariation("ActionButton", "Button");
theme.SetColor("font_color", "ActionButton", new Color(.4f, .6f, 1));
return ResourceSaver.Save(theme, AssetPath);
}
}Для пути asset:// остановите запуск, откройте Content (Ctrl + Space) и найдите созданный файл. Выделение Theme открывает панель Theme; по умолчанию она снизу, но может быть вынесена в плавающее окно. Файл user:// находится в пользовательской папке, а не в Content проекта: фактический путь получите через ProjectSettings.GlobalizePath. Альтернативный путь — создать новый ресурс Theme из редактора и сохранить его в проект; вложенная тема в уровне сама по себе не становится отдельным файлом для повторного использования.
Этот генератор предназначен для подготовки темы в рабочем проекте. В экспортированной игре asset:// обычно недоступен для записи; пользовательскую тему сохраняйте в user:// и явно загружайте при запуске. Проверка FileExists предотвращает повторную запись при обычном нажатии, но не является атомарной защитой от параллельных писателей.
Изменить параметр
- Выберите тип
Button. В группе цветов найдите/добавьтеfont_color, в StyleBoxes —normal, в размерах шрифта —font_size. - Создайте только нужные переопределения. Пустая Theme дополняется стандартной темой; она не содержит автоматически копию всех значений.
- Для StyleBoxFlat задайте фон, границу, скругление и content margins. Состояния normal/hover/pressed/disabled/focus редактируются отдельно.
- Сохраните файл. Назначьте его в Theme корня нужного UI или укажите проектную тему. Для вариации задайте ThemeTypeVariation у целевого Control.
- Проверьте результат на собственном уровне с реальными длинными надписями и размерами окна, затем запустите игру.
Предпросмотр и массовые операции
Редактор содержит предпросмотр стандартных элементов; Add Preview добавляет собственную иерархию для проверки. Предпросмотр проверяет оформление, а игровой код/действия кнопок требуют запуска проекта. Изменение шрифта или отступа проверяйте вместе с minimum size и контейнерами.
Manage Items... управляет типами и элементами. В Import Items доступны источники Default Theme, Editor Theme и другие ресурсы. Выбирайте конкретные параметры для импорта. Копия всех значений усложняет дальнейшую поддержку и может закрепить ненужные defaults. Тема редактора — источник оформления, а не требование использовать её в игре.
Сохранение ResourceSaver и изменения Theme в памяти — разные действия. После изменения файла уже загруженный ресурс может оставаться в кеше; генератор явно использует CacheMode.Ignore для повторного чтения. В игре выберите согласованную политику загрузки, а не бесконтрольное перечитывание темы каждый кадр. CacheMode.Ignore не обещает независимой копии каждого внешнего зависимого ресурса: изменяемый StyleBox или Font может оставаться общим.
Если правки не видны
Проверьте путь назначенного ресурса, тип/вариацию, имя элемента, текущее состояние кнопки, локальные overrides и более близкую тему. Подтвердите, что файл сохранён. Не удаляйте локальные overrides массово, пока не выяснили, какие из них нужны отдельным элементам.