Свои темы
В этом руководстве игра получает собственный вид: палитру, которая перекрашивает встроенные кнопки и списки, новый шаблон для одного элемента и, когда этого мало, целую тему. Тема — это файл, поэтому художник может менять её, не трогая код.
Вам понадобится игра с подключённым IcyUI (Начало работы) и представление о стилях и шаблонах из страниц Ресурсы, стили и темы и Шаблоны элементов и визуальные состояния.
1. Наложите файл темы на встроенную тему
ExtendDefaultTheme загружает файл словаря ресурсов и накладывает его на встроенную тему. Всё, чего в файле нет,
сохраняет встроенный вид:
// Layer the game's palette over the built-in theme.
public static StrideIcyHost Extend(IGame game) =>
game.UseIcyUI(builder => builder.ConfigureTheme().ExtendDefaultTheme("Themes/MyGame.xml"));
Путь отсчитывается от папки вывода игры, как у любого файла разметки: добавьте Themes/MyGame.xml в проект с
Copy to Output Directory = «Copy if newer». Отсутствующий или некорректный файл останавливает игру при запуске с
сообщением, в котором назван этот файл.
2. Перекрасьте, сохранив шаблоны и состояния
Вот весь файл целиком:
<!-- Themes/MyGame.xml: a game palette, layered over the built-in theme with ExtendDefaultTheme. -->
<ResourceDictionary>
<!-- Recolor. An implicit style here builds on the built-in style for its type: the button keeps its template and its
focus state, and changes only what is set. The built-in hover and press states set their own colors, so they
are repeated here in teal; a state group with the same name replaces the built-in one. -->
<Style TargetType="Button" Background="#FF1F6F6B" BorderBrush="#FF5FD0C0">
<Style.StateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Hovered" State="Hovered" Background="#FF2A8A85"/>
<VisualState Name="Pressed" State="Pressed" Background="#FF174F4C"/>
</VisualStateGroup>
</Style.StateGroups>
</Style>
<!-- A visual state group with the same name as one of the built-in style's replaces it, so this repeats the states
to keep: list rows hover and select in teal, and keep the keyboard cursor. -->
<Style TargetType="SelectorItem">
<Style.StateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Hovered" State="Hovered" Background="#FF2A4B49"/>
<VisualState Name="Highlighted" State="Highlighted" Background="#FF2F6A66"/>
<VisualState Name="HighlightedHovered" State="Highlighted,Hovered" Background="#FF2F6A66"/>
<VisualState Name="Selected" State="Selected" Background="#FF1F6F6B"/>
<VisualState Name="SelectedHovered" State="Selected,Hovered" Background="#FF1F6F6B"/>
</VisualStateGroup>
</Style.StateGroups>
</Style>
<!-- A new template for one control. ReplacesTheme drops the built-in style entirely, so this style provides everything:
the template, the colors and every state the control needs. A later entry can use the ones before it. -->
<ControlTemplate x:Key="GameCheckBoxTemplate" TargetType="CheckBox">
<StackPanel Orientation="Horizontal">
<Border Width="20" Height="20" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="2" Margin="0,0,10,0"/>
<ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Center"/>
</StackPanel>
</ControlTemplate>
<Style TargetType="CheckBox" ReplacesTheme="True" Template="{StaticResource GameCheckBoxTemplate}"
Background="#FF26262C" BorderBrush="#FF5FD0C0">
<Style.StateGroups>
<VisualStateGroup Name="CheckStates">
<VisualState Name="Checked" State="Checked" Background="#FF5FD0C0"/>
</VisualStateGroup>
</Style.StateGroups>
</Style>
</ResourceDictionary>
Первый стиль — самый частый случай. <Style TargetType="Button" Background="..."/> в файле строится на встроенном стиле
кнопки: сохраняет шаблон и состояние фокуса и меняет только заданные цвета. Встроенные состояния наведения и нажатия
задают собственные цвета, поэтому файл повторяет их бирюзовыми (шаг 3); без этого кнопка при наведении или нажатии
возвращалась бы к встроенному серому. По тому же правилу
стиль в ресурсах страницы работает поверх темы (Тема под стилями),
здесь оно применено к файлу темы.
3. Замените группу визуальных состояний
Стиль, объявляющий группу состояний с тем же именем, что и во встроенном стиле, заменяет эту группу, поэтому
состояния, которые нужно сохранить, придётся повторить. Строки списка в файле заменяют CommonStates, чтобы
подсвечиваться при наведении и выделении бирюзовым, и сохраняют состояние курсора клавиатуры (Highlighted).
4. Дайте одному элементу новый шаблон
Флажок в файле не перекрашивает встроенный, а заменяет его: у него собственный шаблон — квадрат без галочки — и свои
цвета и состояния. ReplacesTheme="True" велит IcyUI полностью отбросить встроенный стиль для этого типа, так что стиль
сам даёт всё, что нужно элементу: шаблон, цвета и состояния. У этого флажка нет вида при наведении и фокусе, потому что
файл их не объявляет; добавьте их так, как это делает тема по умолчанию.
Запись в файле темы может использовать объявленные перед ней: стиль берёт GameCheckBoxTemplate по ключу, поэтому
объявляйте шаблон первым.
Примечание
Лучший образец того, как выглядят шаблон и его состояния, — файл встроенной темы: DefaultTheme.xml.
5. Замените тему целиком
Чтобы начать с нуля, UseThemeFile делает файл всей темой вместо наложения:
// Or replace the built-in theme entirely with your own file.
public static StrideIcyHost Replace(IGame game) =>
game.UseIcyUI(builder => builder.ConfigureTheme().UseThemeFile("Themes/Dark.xml"));
Скопируйте DefaultTheme.xml (ссылка выше) в проект как Themes/Dark.xml и отредактируйте. С UseThemeFile у элемента,
которого в файле нет, нет никакого вида: ни шаблона, ни цветов. Если нужно изменить лишь часть, лучше используйте
ExtendDefaultTheme.
Что вы построили
Файл темы, который перекрашивает встроенные кнопки и списки, заменяет флажок шаблоном вашей разработки и оставляет все остальные элементы как были, а также способ заменить встроенную тему целиком.
Примечание
Тема выбирается при запуске: Canvas берёт тему при создании, поэтому смена темы во время работы игры не меняет вид уже
созданных Canvas. Записи с ключом (x:Key) в файле темы также не видны для {StaticResource} на ваших страницах: он
ищет только по загружаемой странице; для темы используйте неявные стили, а стили с ключом держите в Resources
страницы.
Дальше
- Свои элементы управления: дайте собственному элементу вид по умолчанию в этом файле темы.
- Ресурсы, стили и темы: какое значение побеждает, когда применимо несколько.