Использование контейнеров
Якоря — эффективный способ обработки различных соотношений сторон для базовой поддержки нескольких разрешений в графических интерфейсах.
Для более сложных интерфейсов этот подход может оказаться неудобным.
В играх такое часто бывает: например, в RPG, онлайн-чатах, стратегиях или симуляторах. Ещё один пример, где нужны продвинутые средства компоновки — игровые инструменты (или просто инструменты).
Во всех этих случаях нужен более функциональный интерфейс — похожий на ОС, с продвинутой компоновкой и форматированием. В таких случаях лучше подходят контейнеры.
Компоновка контейнеров
Контейнеры предоставляют мощные возможности компоновки (например, интерфейс редактора Godot полностью построен на них):
Когда используется узел, производный от Контейнера, все дочерние узлы Control теряют возможность самостоятельного позиционирования. Это означает, что Контейнер будет управлять их расположением, а любые попытки ручного изменения этих узлов либо игнорируются, либо сбрасываются при следующем изменении размера родителя.
Аналогично, когда размер производного узла Container изменяется, все его дочерние элементы будут перемещены в соответствии с ним, причем поведение будет зависеть от типа используемого контейнера:
Пример изменения размера дочерних кнопок HBoxContainer.
Настоящее преимущество контейнеров заключается в том, что их можно вкладывать друг в друга (как узлы), что позволяет создавать очень сложные макеты, размер которых можно легко изменить.
Варианты размеров
При добавлении узла в контейнер, то, как контейнер обрабатывает каждый дочерний элемент, в основном зависит от параметров размера контейнера. Эти параметры можно найти, изучив структуру любого Control, являющегося дочерним элементом Container.
Параметры размеров независимы для вертикального и горизонтального размера, и не все контейнеры их используют (но большинство):
Fill: обеспечивает заполнение элементом управления указанной области внутри контейнера. Независимо от того, расширяется элемент управления или нет (см. ниже), он будет заполнять указанную область только при включенном параметре (по умолчанию).
Expand: пытается использовать как можно больше пространства в родительском контейнере (по каждой оси). Элементы управления, которые не расширяются, будут оттеснены теми, которые расширяются. Расстояние между расширяющимися элементами управления определяется Stretch Ratio (Коэффициентом растяжения) (см. ниже). Этот параметр доступен только для родительского контейнера соответствующего типа, например, HBoxContainer имеет этот параметр для изменения размера по горизонтали.
Shrink Begin При расширении старайтесь оставаться слева или сверху расширенной области.
Shrink Center При расширении старайтесь оставаться в центре расширенной области.
Shrink End При расширении старайтесь оставаться справа или внизу расширенной области.
Stretch Ratio: соотношение между развёрнутыми элементами управления и занимаемым ими доступным пространством. Элемент управления со значением "2" займёт вдвое больше доступного пространства, чем элемент управления со значением "1".
Рекомендуется поэкспериментировать с этими флагами и различными контейнерами, чтобы лучше понять, как они работают.
Типы Container
Godot предлагает несколько типов контейнеров по умолчанию, поскольку они служат разным целям:
Box Containers (Контейнеры-ящики)
Располагает дочерние элементы управления вертикально или горизонтально (через HBoxContainer и VBoxContainer). В противоположном указанному направлению (например, вертикально для горизонтального контейнера) дочерние элементы просто разворачиваются.
Эти контейнеры используют свойство Stretch Ratio для дочерних элементов с установленным флагом Expand.
Grid Container (Сетчатый контейнер)
Располагает дочерние элементы управления в виде сетки (через GridContainer, необходимо указать количество столбцов). Использует как вертикальный, так и горизонтальный флаги расширения.
Margin Container (Контейнер маржи)
Дочерние элементы управления расширяются до границ данного элемента управления (через MarginContainer). Отступы к полям будут добавлены в зависимости от настроек темы.
Опять же, помните, что поля — это значение Theme, поэтому их необходимо редактировать в разделе переопределений констант каждого элемента управления:
Tab Container (Контейнер вкладок)
Позволяет размещать несколько дочерних элементов управления друг над другом (через TabContainer), при этом видимым будет только текущий элемент.
Изменение текущего значения осуществляется с помощью вкладок, расположенных в верхней части контейнера, путем нажатия:
Заголовки генерируются из имен узлов по умолчанию (хотя их можно переопределить через API TabContainer).
Такие настройки, как размещение вкладок и StyleBox, можно изменить в переопределениях темы TabContainer.
Split Container (Раздельный контейнер)
Принимает только один или два дочерних элемента управления, а затем размещает их рядом друг с другом с помощью разделителя (через HSplitContainer и VSplitContainer). Учитывает как горизонтальные, так и вертикальные флаги, а также Ratio.
Разделитель можно перетаскивать, чтобы изменить соотношение размеров между двумя дочерними элементами:
PanelContainer (Панельный контейнер)
Контейнер, который отображает StyleBox, а затем расширяет дочерние элементы, чтобы покрыть всю его область (через PanelContainer, с учетом полей StyleBox). Он учитывает как горизонтальные, так и вертикальные размеры.
Этот контейнер полезен в качестве элемента управления верхнего уровня или просто для добавления пользовательских фонов к разделам макета.
FoldableContainer (Складной контейнер)
Контейнер, который можно развернуть/свернуть (через FoldableContainer). Дочерние элементы управления скрываются при его сворачивании.
ScrollContainer (Контейнер для прокрутки)
Принимает один дочерний узел. Если дочерний узел больше контейнера, будут добавлены полосы прокрутки для панорамирования узла (через ScrollContainer). Учитываются как вертикальные, так и горизонтальные параметры размера, и это поведение можно включить или отключить для каждой оси в свойствах.
Колесико мыши и сенсорное перетаскивание (если сенсорное управление доступно) также являются допустимыми способами панорамирования дочернего элемента управления.
Как и в примере выше, один из наиболее распространенных способов использования этого контейнера — совместно с VBoxContainer в качестве дочернего элемента.
AspectRatioContainer
Тип контейнера, который размещает дочерние элементы управления таким образом, чтобы их пропорции автоматически сохранялись при изменении размера контейнера. (через AspectRatioContainer). Он поддерживает несколько режимов растяжения, позволяющих регулировать размеры дочерних элементов управления относительно контейнера: "fill (заполнение)," "width control height (высота элемента управления шириной)," "height control width (ширина элемента управления высотой)," and "cover (покрытие)."
Это полезно, когда у вас есть контейнер, который должен быть динамичным и реагировать на разные размеры экрана, и вы хотите, чтобы дочерние элементы масштабировались пропорционально, не теряя при этом своих предполагаемых форм.
FlowContainer
FlowContainer — это контейнер, который размещает свои дочерние элементы управления горизонтально или вертикально (через HFlowContainer и через VFlowContainer). Когда доступное место заканчивается, он переносит дочерние элементы на следующую строку или столбец, подобно тому, как текст переносится в книге.
Это полезно для создания гибких макетов, в которых дочерние элементы управления автоматически подстраиваются под доступное пространство, не перекрывая друг друга.
CenterContainer
CenterContainer — это контейнер, который автоматически центрирует все дочерние элементы управления внутри себя при их минимальном размере. Он гарантирует, что дочерние элементы управления всегда будут выровнены по центру, что упрощает создание центрированных макетов без ручного позиционирования (через CenterContainer).
SubViewportContainer
Это специальный элемент управления, который принимает только один узел Viewport в качестве дочернего элемента и отображает его так, как если бы это было изображение (через SubViewportContainer).
Создание пользовательских Containers
Можно создать собственный контейнер с помощью скрипта. Вот пример контейнера, который подгоняет дочерние элементы под свой размер:
extends Container
func _notification(what):
if what == NOTIFICATION_SORT_CHILDREN:
# Must re-sort the children
for c in get_children():
# Fit to own size
fit_child_in_rect(c, Rect2(Vector2(), size))
func set_some_setting():
# Some setting changed, ask for children re-sort.
queue_sort()
using Godot;
public partial class CustomContainer : Container
{
public override void _Notification(int what)
{
if (what == NotificationSortChildren)
{
// Must re-sort the children
foreach (Control c in GetChildren())
{
// Fit to own size
FitChildInRect(c, new Rect2(new Vector2(), Size));
}
}
}
public void SetSomeSetting()
{
// Some setting changed, ask for children re-sort.
QueueSort();
}
}