Funpix Kit
Inicio / Componentes / fpx · ui_kit

fpx · ui_kit

UI mínima con el tema como datos: UiThemeDefinition (.tres) → UiThemeBuilder → Theme con variaciones y colores semánticos, presets dark/light, ContextView y pila de ventanas.

capa 0 v0.2.0 sin dependencias

El ZIP incluye: addons/fpx/ui_kit + sus tests.

Qué es

La base de UI que inventory_ui necesita, y nada más: un tema = un .tres (UiThemeDefinition: tipografía, tamaños, texto, superficies, colores semánticos, rarezas, botones, campos, contextuales, scrollbars, skin opcional) → UiThemeBuilder.build() → un Theme de Godot con variaciones (HotbarSlot, ContextPanel, ContextBand, TooltipPanel, OverlayPanel, SmallLabel, MutedLabel, HeadingLabel…), iconos SVG generados desde los colores y el tipo Semantic con los colores semánticos (D-FW-7). ThemeColors es la vía única para leerlos desde código (ThemeColors.of(control, &"success")). ContextView: menús y fichas contextuales (acciones, submenús, bandas, info). UiWindowStack: pila LIFO de ventanas flotantes con capas, arrastre, chrome de título y sonido por hook.

Presets del kit: data/themes/dark.tres y data/themes/light.tres — sin skin de arte ni fuente propia (cada juego pone las suyas). Desde 2026-08-31 los defaults del esquema SON la paleta del mockup del diseñador (carbón #1A1E23, headers #15181C, dorado #D6C893, pizarra #3A4150): dark = defaults → el kit, sus demos y el tema por defecto del juego visten el mismo «nuevo modelo».

Ficha de ítem (mockup del diseñador 2026-08-31): el builder publica además las variaciones que inventory_ui/ItemTooltip usa para no hardcodear estilos — TooltipSectionBand + TooltipSectionHeader (headers de sección edge-to-edge), TooltipWarnBand (banner de aviso, fondo derivado de color_warning sobre el panel), TooltipStatValue/TooltipStatLabel (valor bold coloreado por signo + etiqueta blanca), KeyBadge (badges de tecla del pie) y TooltipFlavorLabel (itálica falsa por skew, funciona con cualquier fuente). Dial nuevo: color_set (línea de set del header; clave semántica set).

Instalación

  1. Descarga fpx-ui_kit-v0.2.0.zip (botón de arriba) y extráelo en la raíz de tu proyecto Godot — deja la estructura tal cual:
text
tu-juego/
├── project.godot
├── addons/
│   └── fpx/
│       └── ui_kit/
└── tests/          ← opcional: bórralo si no quieres los tests
  1. Abre el proyecto (o corre --import headless). Sin plugins ni autoloads que activar: las clases quedan disponibles en cualquier script.
  2. Opcional — verifica con la suite (necesita GdUnit4, ver la guía): -a tests/ui_kit.

Ejemplo de uso

Usa las fixtures incluidas en el componente para probar en segundos; en tu juego, sustitúyelas por tus datos.

ui_kit · ejemplo
# Un tema = un .tres. Los presets van SIN skin ni fuente propia, y los
# DEFAULTS del esquema son la paleta del «nuevo modelo» del diseñador
# (2026-08-31): dark() = ese look tal cual; tu juego aporta fuente y ajustes.
var def := UiKitFixtures.dark()          # o light(), o tu UiThemeDefinition.tres
var theme := UiThemeBuilder.build(def)   # Theme con variaciones e iconos

# Aplicarlo al juego y registrar el fallback para leer colores desde código:
get_tree().root.theme = theme
ThemeColors.fallback_theme = theme

# Variaciones listas: HeadingLabel, SmallLabel, MutedLabel, TooltipPanel,
# OverlayPanel, ContextPanel… y las de la ficha de ítem (TooltipSectionBand,
# TooltipWarnBand, KeyBadge, TooltipFlavorLabel). Por theme_type_variation.
var title := Label.new()
title.theme_type_variation = &"HeadingLabel"

# Colores semánticos (D-FW-7): la VÍA ÚNICA desde código.
var danger := ThemeColors.of(title, &"danger")
var hp := ThemeColors.of(title, &"hp")

# Menús y fichas contextuales, sin UI propia del juego:
var menu := ContextView.open_menu(self, "Acciones", get_global_mouse_position())
menu.add_action("Atacar", func() -> void: attack())
menu.add_check("Sigilo", false, func(on: bool) -> void: set_stealth(on))
menu.add_submenu("Más…", func(sub: ContextView) -> void:
	sub.add_action("Opción anidada", func() -> void: pass)
)
var card := ContextView.open_card(self, "Enemigo", at)
card.add_bar(64, 100, &"HpBar", "64 / 100 PV")
card.add_info("envenenado", &"danger")

# Ventanas flotantes con chrome y arrastre (pila LIFO, ESC cierra la de arriba):
var window := CanvasLayer.new()
window.layer = UiWindowStack.next_layer()
add_child(window)
var panel := PanelContainer.new()
window.add_child(panel)
UiWindowStack.apply_chrome(window, panel, mi_contenido, "*", "Inventario",
		func() -> void: window.queue_free())
UiWindowStack.opened(window)

Demo en vivo

El componente REAL corriendo en tu navegador — Godot 4.7 exportado a Web sobre las fixtures del kit. La primera carga baja el motor (~10 MB comprimido) y se comparte entre todas las demos.

abrir a pantalla completa ↗

API pública

ClaseQué da
UiThemeDefinition (Resource)todos los diales exportados · semantic_color(key)
UiThemeBuilderbuild(def) -> Theme · SEMANTIC_KEYS · _panel_box(bg, border, w, radius, margin)
ThemeColorsof(control, key) -> Color · constant_of(control, name, type, default) · fallback_theme (lo registra el juego al aplicar su tema) · SEMANTIC_TYPE
ContextViewopen_menu(host, title, at) · open_card(host, title, at) · open_card_above(...) · add_action(text, callable, hint, enabled) · add_submenu · add_separator · bandas e info · any_menu_open()
UiWindowStackopened/closed(window) · is_topmost · next_layer() · apply_chrome(window, panel, box, icon, title, on_close) · make_draggable · refit · sound_hook: Callable · clear()

Qué configura el juego

Su UiThemeDefinition.tres (o un preset del kit), lo aplica a get_tree().root.theme y registra ThemeColors.fallback_theme = theme; UiWindowStack.sound_hook = tu_reproductor si quiere sonido de ventanas. Con skin: skin_dir con la lámina 9-slice (opcional).

Fixture mínima

testing/ui_kit_fixtures.gd — UiKitFixtures.dark()/light() (= los .tres del kit), apply(def) (construye y registra el fallback), reset().

ui_kit_fixtures.gdcódigo completo
ui_kit_fixtures.gd
# res://addons/fpx/ui_kit/testing/ui_kit_fixtures.gd
class_name UiKitFixtures
extends RefCounted
## Fixture mínima del componente `ui_kit`: los DOS presets minimalistas del kit
## — `dark()` y `light()` — SIN skin de arte ni fuente propia (decisión del
## diseñador 2026-08-29: el kit se ve desacoplado y quien lo usa le pone su
## propio tema). Son los mismos valores que `data/themes/{dark,light}.tres`
## (test anti-drift). `dark()` = los defaults del esquema (= el tema base de
## Stremus sin lámina); `light()` = la paleta invertida con los colores
## semánticos oscurecidos para legibilidad sobre claro.


static func dark() -> UiThemeDefinition:
	var def := UiThemeDefinition.new()
	def.id = &"fpx_dark"
	def.display_name = "Funpix Kit · Dark"
	def.skin_dir = ""
	return def


static func light() -> UiThemeDefinition:
	var def := UiThemeDefinition.new()
	def.id = &"fpx_light"
	def.display_name = "Funpix Kit · Light"
	def.skin_dir = ""
	def.text_primary = Color(0.12, 0.13, 0.16)
	def.text_secondary = Color(0.35, 0.37, 0.42)
	def.text_muted = Color(0.0, 0.0, 0.0, 0.50)
	def.text_outline = Color(1.0, 1.0, 1.0, 0.85)
	def.panel_bg = Color(0.97, 0.97, 0.98, 0.96)
	def.panel_border = Color(0.75, 0.77, 0.82, 0.90)
	def.overlay_bg = Color(0.93, 0.94, 0.96, 0.90)
	def.overlay_border = Color(0.75, 0.77, 0.82, 0.45)
	def.color_player = Color(0.05, 0.55, 0.48)
	def.color_enemy = Color(0.80, 0.22, 0.20)
	def.color_active = Color(0.75, 0.55, 0.00)
	def.color_warning = Color(0.85, 0.42, 0.05)
	def.color_success = Color(0.15, 0.60, 0.25)
	def.color_danger = Color(0.80, 0.18, 0.15)
	def.color_resource = Color(0.72, 0.50, 0.05)
	def.color_ap = Color(0.80, 0.50, 0.05)
	def.color_mp = Color(0.15, 0.55, 0.30)
	def.color_hp = Color(0.78, 0.20, 0.25)
	def.rarity_comun = Color(0.45, 0.48, 0.54)
	def.rarity_trascendente = Color(0.55, 0.45, 0.15)
	def.button_bg = Color(0.90, 0.91, 0.94, 0.95)
	def.button_bg_hover = Color(0.84, 0.86, 0.90)
	def.button_bg_pressed = Color(0.78, 0.80, 0.85)
	def.button_bg_disabled = Color(0.90, 0.91, 0.94, 0.55)
	def.button_border = Color(0.66, 0.69, 0.75)
	def.button_border_hover = Color(0.75, 0.55, 0.00)
	def.button_text = Color(0.12, 0.13, 0.16)
	def.button_text_disabled = Color(0.0, 0.0, 0.0, 0.35)
	def.input_bg = Color(1.0, 1.0, 1.0, 0.98)
	def.input_border = Color(0.70, 0.72, 0.78)
	def.tooltip_bg = Color(0.99, 0.99, 1.0, 0.98)
	def.tooltip_border = Color(0.65, 0.68, 0.74)
	def.context_bg = Color(0.98, 0.98, 0.99, 0.98)
	def.context_border = Color(0.72, 0.75, 0.80, 0.70)
	def.context_band_bg = Color(0.90, 0.91, 0.94, 1.0)
	def.context_item_hover = Color(0.0, 0.0, 0.0, 0.06)
	def.widget_header_bg = Color(0.90, 0.91, 0.94, 0.95)
	def.scrollbar_track = Color(0.0, 0.0, 0.0, 0.06)
	def.scrollbar_grabber = Color(0.0, 0.0, 0.0, 0.22)
	def.scrollbar_grabber_hover = Color(0.0, 0.0, 0.0, 0.40)
	return def


## Construye el Theme de un preset y lo deja como fallback de ThemeColors (lo
## que el juego haría al aplicar su tema): así los widgets del kit resuelven
## colores también fuera del árbol y en tests headless.
static func apply(def: UiThemeDefinition) -> Theme:
	var theme := UiThemeBuilder.build(def)
	ThemeColors.fallback_theme = theme
	return theme


static func reset() -> void:
	ThemeColors.fallback_theme = null

Cómo se prueba

tests/ui_kit/ — ui_theme_test (ambos presets construyen sin skin, controles de formulario e iconos rasterizados, tipo Semantic completo, .tres == fixture), window_stack_test (LIFO, capas, poda), theme_colors_test (resolución por control/fallback/blanco).

Ejemplar oro (Stremus)

scripts/ui/{ui_theme_definition,ui_theme_builder,theme_colors,window_stack}.gd, scripts/ui/context/context_view.gd (main@670d5a0); sus temas data/themes/ (Sora, jerarquía de tamaños, skin de arte) son el ejemplar de contenido — el kit NO los trae.

Deuda declarada

  • FLAG-UI-MINIMAL-FIRST: HUD-grid (HudWidget/HudManager/HudLayout), Keymap, FloatText, InfoBubble, StatusIcons, SkillIcons, ThemeEditorCore llegan en FK-11.
  • FLAG-I18N: los textos de chrome («✕», títulos) los pasa el llamador; no hay tabla de etiquetas.
  • UiThemeDefinition conserva diales del ejemplar que el kit no usa aún (hotbar_*, widget_header_bg).
Generado el 2026-08-31 · Funpix Kit — componentes extraídos de Stremus: El Tercer Despertar (ejemplar oro) · Funpixart