Interface do jogo

A interface de jogo no Turian é escrita como na web ou no UI Toolkit da Unity: um documento XML .ui descreve os elementos, uma folha de estilo .uss descreve a aparência, e um UiController em C# ou bindings de dados lhes dão vida. Ela é desenhada pelo Guinevere, o mesmo toolkit que desenha o Turian Studio.
Colocando um documento na tela
- Crie
Assets/UI/menu.uieAssets/UI/theme.uss(abaixo). - Adicione um nó e depois Add Component → UI → UI Document.
- Solte
menu.uino campo Document.
| Propriedade | Significado |
|---|---|
Document |
O documento .ui a renderizar. |
StyleSheets |
Folhas .uss extras aplicadas sobre as do documento. |
Mode |
ScreenSpaceOverlay (desenhado sobre a cena) ou WorldSpace (em um quad na cena). |
SortOrder |
Ordem de desenho entre documentos em espaço de tela. |
ScaleMode, ReferenceResolution |
Tamanho constante em pixels, ou escala com a tela a partir de uma resolução de referência. |
PanelSize |
Tamanho em pixels de um painel no mundo. |
Documentos no mundo são renderizados nas visualizações do Studio e nas renderizações da CLI; jogos exportados ainda não os desenham. Adicione um componente UI Raycaster para torná-los clicáveis.
Um documento
<?xml version="1.0" encoding="utf-8"?>
<UI xmlns="https://turian.dev/ui" controller="Usercode.MainMenu">
<Style src="Assets/UI/theme.uss" />
<VisualElement name="root" class="screen">
<Label class="title" text="{Title}" />
<Button name="play" text="Play" click="OnPlay" />
<Toggle name="music" label="Music" value="{Music, mode=TwoWay}" />
<Button name="quit" text="Quit" click="OnQuit" />
</VisualElement>
</UI>
- A raiz é sempre
<UI>; ela contém folhas<Style>,<Template>s opcionais e um elemento visual. - Atributos comuns:
name(id único),class(classes de estilo),style(declarações inline),tooltip,enabled. - O texto interno de um elemento folha vira o seu
text:<Label>Menu principal</Label>.
Elementos
| Elemento | Observações |
|---|---|
VisualElement |
Contêiner genérico; organize-o com flex-direction, gap, tamanhos e alinhamento. |
Label |
Texto. |
Button |
text; dispara click. |
Image |
src, width, height. |
ImageButton |
image-normal, image-hover, image-pressed, nine-slice="l,t,r,b"; dispara click. |
TextField |
value, placeholder; dispara value-changed. |
Toggle |
value, label; dispara value-changed. |
ScrollView |
Rola os filhos verticalmente. |
Tabs / Tab |
<Tab header="…"> por página; dispara changed. |
Dê um name aos controles com estado (TextField, Toggle, Tabs) para que o estado seja mantido entre quadros.
Templates e listas
<Template name="StatRow">
<VisualElement class="row">
<Label text="{label}" />
<Label binding-text="{path}" />
</VisualElement>
</Template>
<Instance template="StatRow" label="Ouro" path="Player.Gold" />
<ScrollView>
<Repeat items="{Inventory}" as="item">
<Label binding-text="{item.Name}" />
</Repeat>
</ScrollView>
Estilizando com .uss
--accent: #4a90e2;
.screen { flex-direction: column; gap: 12; padding: 24; align-items: center; }
.title { font-size: 32; color: #ffffff; text-shadow: #000000 2 2; }
Button { width: 220; height: 44; border-radius: 8; background-color: #2a2f3a; }
Button:hover { background-color: var(--accent); }
#quit { background-color: #6b2b2b; }
- Seletores:
Tipo,.classe,#nome,*, compostos comoButton.primarye gruposa, b. Combinadores de descendente e de filho não são suportados. - Estados:
:hover,:active,:focus,:disabled. - Variáveis: declare
--nome: valor;no nível superior e usevar(--nome). - Layout:
flex-direction,flex-wrap,flex-grow,gap,width/height(pixels ou%), tamanhos mín./máx.,padding,margin,align-items,justify-content,align-self. - Caixa:
background-color,border-color,border-width,border-radius. - Texto:
color,font-size,font-family(um.ttf/.otfdo projeto ou uma fonte do sistema),text-outline,text-shadow,text-inner-shadow,text-gradient.
Code-behind e data binding
namespace Usercode;
public sealed class MainMenu : UiController
{
public string Title => "Meu Jogo";
public bool Music { get; set; } = true;
public void OnPlay() => Log.Logger.LogInformation("Jogar pressionado");
public void OnQuit() => Log.Logger.LogInformation("Sair pressionado");
}
- Todo método público
voidsem parâmetros é um manipulador de eventos, referenciado pelo nome emclick,value-changed,changed,submit,activatedouselection-changed. {Caminho}em um atributo o vincula a uma propriedade do controller (ou de um contexto de dados separado), relida a cada quadro — sem necessidade de notificações de mudança.binding-text="{…}"é a forma explícita, e um bloco<Bindings>pode agrupá-los.- Modos:
OneWay(padrão),TwoWay(campos de texto e toggles escrevem de volta),OneTime. - Conversores:
{Health | percent}— os embutidos sãonot,percent,thousands,upperelower; registre os seus comValueConverters.Register("nome", conversor). - Sobrescreva
OnBind,OnUpdate(float deltaTime)eOnUnbindpara preparação, lógica por quadro e finalização.
Textos localizados
O texto dos rótulos é buscado automaticamente nas tabelas de textos do projeto; text-key indica uma chave explícita. Veja Localização.
Pré-visualizando sem o jogo
A CLI renderiza um documento em PNG sem GPU, vinculando JSON como dados:
turian-cli ui --file Assets/UI/menu.ui --out menu.png --data '{"Title":"Prévia","Music":true}'
Erros de análise informam a linha e a coluna do XML problemático.