> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/docs-es/ui/uidoc-quick-start.md).

# Inicio rápido de UIDoc

***

UIDoc te permite describir la IU del juego con HTML y CSS, luego suministrar sus datos cambiantes y manejar sus eventos en CSL. Es útil para menús, inventarios, árboles de habilidades y otras interfaces estructuradas en espacio de pantalla.

UIDoc es similar a un navegador, pero no es un navegador web integrado. Usa el subconjunto compatible descrito en [Compatibilidad de HTML y CSS de UIDoc](/all-out-docs/docs-es/ui/uidoc-html-css-support.md).

## Crea un recurso UIDoc

Crea una carpeta dentro del `res` directorio de tu juego. El nombre de la carpeta debe terminar en `.uidoc` y contener `index.html` y `index.css`:

```
res/
└── UI/
    └── settings.uidoc/
        ├── index.html
        └── index.css
```

Las rutas de recursos usadas por CSL son relativas a `res`, por lo que este documento se carga como `UI/settings.uidoc`.

## Editar visualmente y generar CSL

Selecciona un recurso UIDoc en el editor All Out para abrir su vista de autoría visual. Puedes seleccionar y arrastrar elementos en el lienzo, cambiar su tamaño, reordenarlos o cambiarles el padre en Capas, y editar propiedades comunes de HTML y CSS en el inspector. La vista previa se renderiza por el propio tiempo de ejecución de UIDoc, así que usa el mismo comportamiento compatible de diseño y renderizado que el juego.

El inspector de Interfaz infiere campos dinámicos, listas repetidas, entradas y acciones a partir del marcado del documento. Guardar un recurso como `ui/shop.uidoc` también mantiene `scripts/generated/uidoc/ui/shop.csl`. Su envoltorio tipado proporciona `default_data`, `decode_event`, lectores de entrada y `draw`, por lo que el código del juego no necesita repetir los enlaces de bajo nivel que se muestran más adelante en esta guía:

```csl
data := UiShop_UIDoc.default_data();
data.title = "Tienda";
UiShop_UIDoc.draw(data, player, shop_event);
```

El código generado usa las mismas `UI.uidoc_*` llamadas públicas documentadas más abajo; no añade un sistema de ejecución aparte ni cambia la API de tiempo de ejecución de UIDoc.

Al usar las herramientas de automatización, `uidoc_create_asset` devuelve la versión de su plantilla y el contenido generado exacto `index.html`/`index.css` del contenido. Los recursos UIDoc no se recargan en caliente en un juego en ejecución, así que reinicia el juego después de cambiar esos archivos. Usa `uidoc_diagnostics` para comprobaciones de compilación y de ventana gráfica, y luego `uidoc_runtime_inspect` para inspeccionar nodos en vivo, enlaces, estilos, cargas útiles de clic y rectángulos.

## Escribe el documento

En `index.html`:

```html
<div class="screen">
  <div class="panel">
    <span class="title">Configuración</span>
    <span class="message">{{message}}</span>
    <button class="close" data-on-click="event:close">Cerrar</button>
  </div>
</div>
```

`{{message}}` es un enlace de texto. `data-on-click` envía un `UIDoc_Event` a CSL.

En `index.css`:

```css
.screen {
  position: fixed;
  inset: env(safe-area-inset-top) env(safe-area-inset-right)
         env(safe-area-inset-bottom) env(safe-area-inset-left);
  display: flex;
  align-items: center;
  justify-content: center;
}

.panel {
  display: flex;
  flex-direction: column;
  width: 420px;
  padding: 24px;
  gap: 16px;
  color: white;
  background: #172033;
  border: 2px solid #52627d;
  border-radius: 12px;
  box-shadow: 0 12px 28px 0 #00000066;
}

.title {
  font-size: 32px;
  text-align: center;
}

.close {
  height: 48px;
  background: #3559a8;
  border-radius: 8px;
}

.close:hover {
  background: #4770ca;
}

.close:pressed {
  background: #29447f;
}
```

Los márgenes de área segura mantienen la IU a pantalla completa libre de recortes del dispositivo y del área de la barra superior del juego.

## Enlázalo y dibújalo desde CSL

Dibuja la IU del jugador desde la `ao_late_update` pila de llamadas. Limpia y reconstruye los enlaces de UIDoc antes de dibujar el documento en cada fotograma:

```go
settings_uidoc_event :: proc(event: UIDoc_Event, userdata: Object) {
    player := userdata.(Player);
    if player == null return;

    if event.handler == "event:close" {
        player.settings_open = false;
    }
}

draw_settings :: proc(player: Player) {
    UI.uidoc_clear_bindings();
    UI.uidoc_bind_text("message", "Los cambios se guardan automáticamente.");

    document := get_asset(UIDoc_Asset, "UI/settings.uidoc");
    if document == null return;

    UI.uidoc(document, false, player, settings_uidoc_event);
}

Player :: class : Player_Base {
    settings_open: bool;
    pet_name: string;

    ao_late_update :: method(dt: float) {
        if this.is_local_or_server() && this.settings_open {
            draw_settings(this);
        }
    }
}
```

La devolución de llamada recibe la cadena exacta del controlador de `data-on-click`. Un control no repetido puede proporcionar un `data-key` para `event.key`; los controles repetidos usan su `data-for-key` resuelta o la clave del elemento de la lista.

`userdata` se pasa solo a esa devolución de llamada; no identifica el documento. Cada recurso UIDoc puede dibujarse una vez por envío de simulación. Cuando un documento deja de dibujarse, su activación actual se cierra; al dibujarlo de nuevo se asigna automáticamente una nueva generación de activación para que los diseños replicados obsoletos no puedan adjuntarse al documento reabierto. Como máximo, cuatro recursos UIDoc diferentes pueden estar activos a la vez.

Los enlaces de nivel superior disponibles son:

```go
bind_player_fields :: proc(player: Player) {
    UI.uidoc_bind_bool("visible", true);
    UI.uidoc_bind_text("name", player.get_username());
    UI.uidoc_bind_float("cameraSize", player.camera.size);
}
```

## Condiciones, enlaces de pintura y listas

Usa `data-if` para incluir un nodo solo mientras un enlace booleano de nivel superior sea verdadero. Un prefijo opcional `!` lo invierte. `data-if` no resuelve expresiones locales de la lista como `item.visible`; el estado visual repetido debería usar en su lugar un enlace de pintura local de la lista, mientras que la visibilidad estructural o interactiva repetida debería decidirse al construir la lista CSL. Para otro estado visual dinámico, mantén las clases estáticas y enlaza un color u opacidad compatibles:

```html
<div
  class="notice"
  data-if="showNotice"
  data-style-color="noticeColor">
  {{noticeText}}
</div>
```

Enlaza `noticeColor` con `UI.uidoc_bind_text` usando una cadena de color CSS compatible. Los atributos de clase se compilan como tokens de clase estáticos y no admiten `{{...}}` interpolación.

Usa `data-for` para datos repetidos:

```html
<div class="inventory">
  <button
    class="item"
    data-for="item in items"
    data-for-key="item.id"
    data-key="inventory-item"
    data-style-color="item.rarityColor"
    data-on-click="event:item">
    {{item.name}}
  </button>
</div>
```

Construye esa lista en CSL antes de llamar a `UI.uidoc`:

```go
Inventory_Row :: struct {
    id: string;
    name: string;
    rarity_color: string;
}

bind_inventory_rows :: proc(items: []Inventory_Row) {
    UI.uidoc_begin_list("items");
    for item: items {
        UI.uidoc_list_item(item.id);
        UI.uidoc_list_bind_text("id", item.id);
        UI.uidoc_list_bind_text("name", item.name);
        UI.uidoc_list_bind_text("rarityColor", item.rarity_color);
    }
    UI.uidoc_end_list();
}
```

Usa una expresión directa estable y única como `data-for-key="item.id"` para cada elemento repetido. Se devuelve como `event.key`. Dale `UI.uidoc_list_item(...)` el mismo valor estable para que la interacción, la entrada y la identidad de desplazamiento sobrevivan a los cambios de la lista. Un `data-key` nombra el rol del control; UIDoc combina ese rol con la clave enlazada de cada elemento de la lista contenedora y su índice actual para su identidad de tiempo de ejecución registrada.

En el ejemplo anterior, un nombre de prueba en vivo contiene un sufijo como `inventory-item#potion-42:7/__widget`. Inspecciona el nombre exacto en `client_ui_tree`, y luego apunta a esa instancia con el nombre completo o un sufijo lo suficientemente preciso como `Test.click_button("inventory-item#potion-42:7")`. Una búsqueda solo por rol como `Test.click_button("inventory-item")` es ambigua cuando hay varias filas visibles. `data-on-click` y el texto visible no son selectores de prueba. Las listas anidadas añaden un `#key:index` par por bucle.

## Entradas

Enlaza una entrada con `data-bind-value`:

```html
<input
  id="pet-name"
  class="name-input"
  placeholder="Nombre de la mascota"
  data-bind-value="petName"
  data-on-click="event:name-input">
```

Lee su valor actual después de que el documento se haya dibujado:

```go
draw_pet_name_input :: proc(player: Player, document: UIDoc_Asset) {
    UI.uidoc_bind_text("petName", player.pet_name);
    UI.uidoc(document, false, player, settings_uidoc_event);
    player.pet_name = UI.uidoc_text_value(document, "pet-name", player.pet_name);
}
```

`UI.uidoc_text_value` busca la entrada por su `id` o `data-key`, y luego devuelve el valor actual de su `data-bind-value` enlace.

## Desplazamiento y zoom

El desplazamiento se habilita con overflow de CSS. Ambos ejes pueden habilitarse en la misma ventana gráfica:

```html
<div class="viewport" data-scroll-zoom="zoom">
  <div class="canvas">
    <button
      class="node"
      data-for="node in nodes"
      data-for-key="node.id"
      data-key="canvas-node"
      data-style-transform-x="node.x"
      data-style-transform-y="node.y"
      data-on-click="event:node">
      {{node.name}}
    </button>
  </div>
</div>
```

```css
.viewport {
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overflow-y: auto;
}

.canvas {
  position: relative;
  width: 1600px;
  height: 1000px;
}

.node {
  position: absolute;
  width: 160px;
  height: 64px;
}
```

Enlaza `zoom` con `UI.uidoc_bind_float`. `data-scroll-zoom` escala las posiciones, tamaños, texto, imágenes, regiones de impacto y extensiones de desplazamiento del contenido alrededor del centro de la ventana gráfica. Mantén los controles de zoom fijos fuera de la ventana gráfica ampliada.

{% hint style="warning" %}
Los atributos de expresión de enlace usan una expresión directa, como `data-for-key="node.id"`, `data-style-transform-x="node.x"`, o `data-scroll-zoom="zoom"`. No pongas esas expresiones dentro de `{{...}}`. La interpolación Mustache es para texto y `src`; las clases y `data-key` los valores son estáticos.
{% endhint %}

Para un panel de desplazamiento normal, omite `data-scroll-zoom`. Al arrastrar se desplaza en cada eje habilitado; la rueda desplaza verticalmente, o horizontalmente cuando solo está habilitado el desbordamiento horizontal.

## Errores comunes

* Carga el documento usando su ruta relativa a `res`, incluida la `.uidoc` sufijo.
* Dibújalo desde el código de IU del jugador local bajo `is_local_or_server()`.
* Llama a `UI.uidoc_clear_bindings()` y proporciona los enlaces actuales antes de cada dibujo.
* Dibuja cada recurso UIDoc una vez por actualización. Usa `userdata` solo como datos de devolución de llamada.
* Usa `data-if` solo con booleanos de nivel superior. Enlaza el estado visual local de la lista mediante `data-style-opacity`/`data-style-color`, o bien omite las filas estructurales/interactivas de la lista enlazada.
* Da a los nodos repetidos una `data-for-key` expresión directa estable; mantén `data-key` estático al nombrar el rol de un control.
* Trata la compatibilidad CSS como específica de propiedad/valor. `auto` y `none` se aceptan solo donde la referencia generada los enumera; los bordes laterales como `border-bottom` no son compatibles, y `calc(...)` se limita a los campos de longitud documentados con suma/resta sencilla.
* Dale al contenido desplazable un tamaño real. Las transformaciones por sí solas no deben usarse como su único tamaño de diseño.
* Usa el diseño adaptable y el comportamiento de zoom propios de UIDoc en lugar de aplicar una segunda escala manual de IU en CSL.
