Перейти к содержимому

UXML

Только client UI недоступен в server.lua Reflex-модуля.

UI загружает постоянные интерфейсы из UXML и позволяет менять их из Lua. Он подходит для панелей, меню, списков и интерактивных окон. Для простого текста или изображения, которое полностью перерисовывается каждый кадр, обычно удобнее ImGui.

UI разделён на несколько страниц:

UXML loader создаёт удерживаемое дерево VisualElement: оно продолжает существовать между кадрами, пока модуль его не удалит. Методы Build* сразу подключают корень к одному из экранных/HUD-контейнеров, а методы Create* только создают отсоединённые элементы в памяти.

После подключения UI layout рассчитывает размеры и позиции, renderer рисует дерево, а event system направляет pointer/focus-события подходящим элементам. Изменение свойства или стиля обновляет это же дерево — повторно рисовать весь интерфейс каждый кадр не нужно.

Способ создания Где находится элемент
BuildFromUxmlAbsolute() В корневом экранном слое. Позицию задают стили UXML/USS; указатель по умолчанию не перехватывается.
BuildFromUxmlInteractive() В том же экранном слое, но с включённым взаимодействием мышью.
BuildFromUxml() / BuildFromUxmlAbsoluteCenter() В отдельном HUD-окне, доступном игроку в редакторе интерфейса.
CreateFromUxml() / CreateVisualElement() / CreateLabel() Нигде, пока элемент не добавлен в уже отображаемое дерево через Add().

OpenWindow() не создаёт вторую копию интерфейса. Он открывает переданный элемент как эксклюзивное окно и применяет выбранные правила для курсора, ввода игрока, размытия и перекрывающего UI.

Файлы UXML и USS размещаются в папке ui/ модуля. В Lua путь указывается относительно неё.

ui/StatusPanel.uxml
<ui:UXML xmlns:ui="UnityEngine.UIElements">
<Style src="./styles.uss" />
<ui:VisualElement name="Root" class="status-panel">
<ui:Label name="lblStatus" text="Loading..." />
</ui:VisualElement>
</ui:UXML>
ui/styles.uss
.status-panel {
position: absolute;
left: 24px;
top: 160px;
padding: 12px;
background-color: rgba(8, 13, 20, 0.9);
}
scripts/main.lua
local root = UI:BuildFromUxmlAbsolute("StatusPanel.uxml")
if root ~= nil then
local label = root:GetChild("lblStatus")
label.text = "Module is active"
end

BuildFromUxmlAbsolute() сразу добавляет корень на экран. В отличие от ImGui, повторять этот код каждый кадр не нужно.

Свойства доступны только для чтения.

Свойство Тип Что показывает
UI.IsConsoleVisible boolean Открыта ли игровая консоль
UI.IsCursorUnlocked boolean Освобождён ли курсор
UI.IsExclusiveWindowOpen boolean Открыто ли эксклюзивное окно игры или модуля
UI.IsWindowOpen boolean Открыто ли окно этого модуля через OpenWindow()
UI:BuildFromUxmlAbsolute(path: string): VisualElement

Загружает UXML и добавляет его в корневой UI. Элемент не перехватывает мышь, пока вы явно не включите взаимодействие. Возвращает корень или nil, если файл не удалось загрузить.

UI:BuildFromUxmlInteractive(path: string): VisualElement

Загружает UXML, добавляет его на экран и сразу включает обработку указателя. Используйте для кнопок, полей ввода и других интерактивных панелей.

UI:BuildFromUxmlAbsoluteCenter(
path: string,
id: string,
title: string
): VisualElement

Создаёт HUD-окно, начальная позиция которого находится по центру. id должен быть непустым и уникальным внутри модуля.

UI:BuildFromUxml(
path: string,
id: string,
title: string,
anchorMode: string,
posX: string,
posY: string
): VisualElement

Создаёт настраиваемое HUD-окно с указанной привязкой и начальной позицией. Координаты принимают значения UI Toolkit, например "24px" или "10%".

Допустимые anchorMode:

Значение Значение Значение
TopLeft TopMiddle TopRight
MiddleLeft Middle MiddleRight
BottomLeft BottomMiddle BottomRight
local panel = UI:BuildFromUxml(
"StatusPanel.uxml",
"status-panel",
"Status",
"TopRight",
"24px",
"120px"
)
UI:CreateFromUxml(path: string): VisualElement

Создаёт дерево из UXML, но не добавляет его на экран. Это удобно для повторяемых строк списка: создайте элемент, затем добавьте его в контейнер через parent:Add(child).

UI:CreateVisualElement(): VisualElement
UI:CreateLabel(): TextElement

Создаёт пустой контейнер или текстовый элемент. Их также нужно добавить в существующее дерево через Add().

UI:Q(root: VisualElement, id: string): VisualElement
root:GetChild(name: string): VisualElement
root:GetChildAt(index: number): VisualElement

Q() и GetChild() рекурсивно ищут потомка по name и возвращают nil, если совпадения нет. GetChildAt() обращается к непосредственному дочернему элементу по индексу, начиная с 0.

UI:RemoveFromHierarchy(root: VisualElement)
root:RemoveFromHierarchy()

Отсоединяет элемент от текущего родителя, но оставляет объект пригодным для повторного добавления.

UI:Delete(element: VisualElement): bool
element:Delete(): bool

Полностью удаляет элемент вместе с созданными для его дерева обёртками. После успешного удаления прежние ссылки использовать нельзя.

UI:OpenWindow(
element: VisualElement,
unlockCursor: boolean,
lockInput: boolean,
hideOverlappingUI: boolean,
blurBackground: boolean
): bool

Открывает элемент как текущее эксклюзивное окно модуля и применяет выбранные режимы. Возвращает false, если элемент недоступен, уже открыто другое эксклюзивное окно или управление уже заблокировано другим окном.

local menu = UI:BuildFromUxmlInteractive("Menu.uxml")
if menu ~= nil then
UI:OpenWindow(menu, true, true, true, true)
end
UI:CloseWindow(element: VisualElement, hideVisual: boolean = true): bool

Закрывает текущее окно и освобождает захваченные им ресурсы. При hideVisual = true элемент также скрывается. Возвращает false, если переданный элемент не является текущим окном.

Каждый метод возвращает true, если режим был применён или освобождён для текущего окна.

Включить Выключить Эффект
UI:LockCursor(element) UI:UnlockCursor(element) Захват или освобождение курсора
UI:LockPlayerInput(element) UI:UnlockPlayerInput(element) Блокировка управления игроком
UI:HideOverlappingUI(element) UI:ShowOverlappingUI(element) Скрытие перекрывающего игрового UI
UI:BlurBackground(element) UI:UnblurBackground(element) Размытие фона

Эти ресурсы привязаны к активному окну. Для обычной панели, которая не открыта через OpenWindow(), методы возвращают false.

UI:SetWindowVisibilityTypes(
element: VisualElement,
visibilityTypes: table
): bool

Задаёт режимы, в которых HUD-окно доступно. Метод работает только с элементом, созданным через BuildFromUxml() или BuildFromUxmlAbsoluteCenter().

UI:SetWindowVisibilityTypes(panel, {
WindowVisibilityType.Match,
WindowVisibilityType.Spectate,
})
Значение Число Режим
WindowVisibilityType.Match 0 Обычный матч
WindowVisibilityType.Spectate 1 Наблюдение
WindowVisibilityType.Killcam 2 Камера убийства
UI:GetMousePosition(): Vector2
UI:ViewportToUiPoint(point: Vector3): Vector2
UI:UiToViewportPoint(point: Vector2): Vector2
UI:ToUpperInvariant(text: string): string
  • GetMousePosition() возвращает текущую позицию курсора;
  • ViewportToUiPoint() переводит viewport-позицию в UI;
  • UiToViewportPoint() выполняет обратное преобразование;
  • ToUpperInvariant() переводит текст в верхний регистр без зависимости от языка системы. Для nil возвращает nil.
PlayerRankDisplay:BindAgent(
agent: Agent,
rankContainer: VisualElement,
rankImage: VisualElement
)
PlayerRankDisplay:Clear(
rankContainer: VisualElement,
rankImage: VisualElement
)

Заполняет стандартные элементы отображения ранга данными агента или очищает их.