> 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

Crea una interfaz de usuario de estilo navegador con los activos HTML y CSS de UIDoc, enlaces CSL, listas y eventos.

***

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

UIDoc es similar a un navegador, pero no es un navegador web incrustado. 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`.

## Edita visualmente y genera 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, redimensionarlos, reordenarlos o cambiar su padre en Capas, y editar propiedades comunes de HTML y CSS en el inspector. La vista previa la renderiza el propio tiempo de ejecución de UIDoc, por lo que usa el mismo comportamiento de diseño y renderizado compatible que el juego.

El inspector de la 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`, así que el código del juego no necesita repetir las vinculaciones de bajo nivel mostradas más adelante en esta guía:

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

Para un modal, usa `UiShop_UIDoc.draw(data, player, shop_event, consume=true)` para bloquear la entrada del puntero a los widgets de juego que están debajo. El parámetro opcional final `consume` tiene como valor predeterminado `false`. Guarda los recursos UIDoc existentes en el editor para regenerar los wrappers con este parámetro.

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

Al usar las herramientas de automatización, `uidoc_create_asset` devuelve su versión de plantilla y el contenido generado exacto `index.html`/`index.css` Usa `uidoc_diagnostics` para comprobaciones de autoría y del viewport en el entorno del editor. Usa `uidoc_runtime_inspect` para lo que se dibuja ahora mismo: nodos maquetados con texto y rectángulos de pantalla resueltos, controladores de clic y claves de fila, los enlaces enviados y problemas de ejecución; por defecto usa el cliente activo mientras Start Game está en ejecución, de lo contrario requiere un `scope: "editor"`. Cada respuesta de ejecución indica su entorno.

## 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 UI 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 UI del jugador desde el `ao_late_update` pila de llamadas. Vacía 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 estático `data-key` para `event.key`; los controles repetidos usan su resuelto `data-for-key` 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; dibujarlo de nuevo 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, pueden estar activos cuatro recursos UIDoc diferentes 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 opcional al principio lo invierte. `!` lo invierte. `data-if` no resuelve expresiones locales a la lista como `item.visible`; el estado visual repetido debe usar en su lugar un enlace de pintura local a la lista, mientras que la visibilidad estructural o interactiva repetida debe decidirse al construir la lista CSL. Para otro estado visual dinámico, mantén las clases estáticas y enlaza un color o una 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 estático `data-key` nombra el rol del control; UIDoc combina ese rol con la clave enlazada de cada elemento de lista contenedor y su índice actual para su identidad de tiempo de ejecución registrada.

Para el ejemplo anterior, un nombre de prueba en vivo contiene un sufijo como `inventory-item#potion-42:7/__widget`. `client_ui_tree` lo acorta a un selector único sin el opcional `/__widget`, como `inventory-item#potion-42:7`; pasa ese resultado directamente a `Test.click_button`. 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` por cada 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 dibujar el documento:

```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 el mismo viewport:

```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 del viewport. Mantén los controles de zoom fijos fuera del viewport con zoom.

{% 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 e imágenes `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 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`, incluyendo el sufijo `.uidoc` .
* Dibújalo desde el código de UI 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 omite de la lista enlazada las filas estructurales/interactivas.
* Dale a los nodos repetidos una `data-for-key` directa estable `data-key` al nombrar el rol de un control.
* Trata la compatibilidad de 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 simple.
* Dale al contenido desplazable un tamaño real. No se deben usar las transformaciones como su único tamaño de diseño.
* Usa el propio comportamiento de diseño adaptable y zoom de UIDoc en lugar de aplicar una segunda escala manual de la UI en CSL.
