ziva-sh/godot-control-layout

Constrói UIs de Controle no Godot 4 que redimensionam em vez de recortar ou sobrepor — containers versus âncoras, presets de âncora via código, flags de tamanho, custom_minimum_size, margens do MarginContainer, quebra de linha em Label, mouse_filter, HUDs com CanvasLayer, nomes de override de tema no Godot 4 (add_theme_color_override e afins) e as configurações de display/window/stretch para múltiplas resoluções. Use ao criar ou corrigir menus, HUDs, diálogos e telas de inventário, quando elementos de UI estão cortados, com tamanho zero, sobrepostos ou ignorando entrada do mouse.

O que é godot-control-layout?

Esta skill oferece um guia completo e prático para criar interfaces de usuário (UI) responsivas no Godot 4, evitando os problemas mais comuns de layout como elementos cortados, sobrepostos ou com tamanho zero. Ela cobre três pilares fundamentais: o uso correto de containers (como VBoxContainer, HBoxContainer, MarginContainer) para organizar filhos automaticamente; a aplicação de âncoras apenas no nó raiz da UI através do método `set_anchors_and_offsets_preset()`; e a configuração das opções de redimensionamento da tela (display/window/stretch) no projeto. Além disso, aborda tópicos essenciais como a criação de HUDs usando CanvasLayer para que fiquem fixos na tela, o controle de quebra de linha e overflow em Labels, a gestão de eventos de mouse com a propriedade `mouse_filter`, e os nomes atualizados dos métodos de override de tema (add_theme_color_override, etc.) em relação ao Godot 3. A skill é útil para qualquer desenvolvedor que esteja criando menus, HUDs, diálogos ou inventários no Godot 4, fornecendo exemplos de código GDScript e uma checklist de depuração para identificar rapidamente as causas de problemas de layout.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ziva-sh/godot-skills/tree/HEAD/skills/godot-control-layout

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Layout de controle no Godot 4

A maioria das UIs quebradas no Godot vem de três erros: posicionar filhos de um container manualmente, ancorar um controle sem redefinir seus offsets e deixar as configurações de esticamento (stretch) nos valores padrão. Organize com containers, ancore apenas a raiz de cada UI e deixe os tamanhos mínimos guiarem o resto.

Containers possuem seus filhos

Um filho de qualquer Container (VBoxContainer, HBoxContainer, GridContainer, MarginContainer, PanelContainer, CenterContainer, ScrollContainer, FlowContainer) não pode manter sua própria position, size ou âncoras: o container as sobrescreve na próxima organização. Controle a participação de um filho no espaço com:

  • size_flags_horizontal / size_flags_vertical: Control.SIZE_FILL (padrão), SIZE_EXPAND_FILL para ocupar espaço extra, SIZE_SHRINK_CENTER / SIZE_SHRINK_END para ficar pequeno e alinhado.
  • size_flags_stretch_ratio: proporção do espaço extra entre irmãos que se expandem.
  • custom_minimum_size: o menor tamanho que o filho aceita. Containers nunca encolhem um filho abaixo de seu tamanho mínimo combinado, que é como textos e botões evitam ser cortados.

Escolha o container pelo layout: linhas ou colunas (VBoxContainer, HBoxContainer), uma grade (GridContainer com columns), preenchimento (MarginContainer, preenchimento definido por constantes de tema margin_left, margin_top, margin_right, margin_bottom), um fundo (PanelContainer, style box panel), conteúdo longo (ScrollContainer com um filho que tenha SIZE_EXPAND_FILL), itens que quebram linha (HFlowContainer).

Âncoras apenas para a raiz

Âncoras posicionam um controle em relação ao retângulo do seu pai e são o que você usa para o nó de UI mais externo. Em código, use set_anchors_and_offsets_preset(). set_anchors_preset() apenas move as âncoras e mantém os offsets antigos, então um controle criado em código permanece com tamanho (0, 0).

Presets: PRESET_FULL_RECT, PRESET_TOP_LEFT, PRESET_TOP_RIGHT, PRESET_BOTTOM_LEFT, PRESET_BOTTOM_RIGHT, PRESET_CENTER, PRESET_TOP_WIDE, PRESET_BOTTOM_WIDE, PRESET_LEFT_WIDE, PRESET_RIGHT_WIDE, PRESET_HCENTER_WIDE, PRESET_VCENTER_WIDE, e os presets de centro-borda como PRESET_CENTER_TOP.

HUD em um CanvasLayer

Um Control sob um Node2D é desenhado no espaço do mundo e se move com a Camera2D. Coloque o HUD sob um CanvasLayer para que ele permaneça na tela; a propriedade layer ordena várias camadas de canvas (a maior desenha por cima).

extends CanvasLayer

var score_label: Label


func _ready() -> void:
	var margin := MarginContainer.new()
	margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
	for side in ["margin_left", "margin_top", "margin_right", "margin_bottom"]:
		margin.add_theme_constant_override(side, 16)
	add_child(margin)

	var column := VBoxContainer.new()
	margin.add_child(column)

	var top_bar := HBoxContainer.new()
	column.add_child(top_bar)

	score_label = Label.new()
	score_label.text = "Score: 0"
	score_label.add_theme_font_size_override("font_size", 24)
	score_label.add_theme_color_override("font_color", Color.GOLD)
	top_bar.add_child(score_label)

	var spacer := Control.new()
	spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE
	top_bar.add_child(spacer)

	var pause_button := Button.new()
	pause_button.text = "Pause"
	pause_button.custom_minimum_size = Vector2(96, 40)
	top_bar.add_child(pause_button)


func set_score(value: int) -> void:
	score_label.text = "Score: %d" % value

Construída no editor, a mesma árvore é: CanvasLayer > MarginContainer (Layout: Full Rect) > VBoxContainer > HBoxContainer > Label, Control (Expand), Button.

Texto que não recorta

  • Uma Label com autowrap_mode definido precisa de uma largura de algum lugar. Dentro de um HBoxContainer com flags padrão, ela colapsa para 1 pixel de largura e fica muito alta. Dê a ela SIZE_EXPAND_FILL ou um custom_minimum_size.x.
  • Para texto de uma linha em um espaço fixo, defina text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS (ou clip_text = true).
  • Prefira add_theme_font_size_override("font_size", n) em vez de escalar um controle: scale não altera o tamanho que os containers reservam.
extends VBoxContainer


func add_message(text: String) -> void:
	var label := Label.new()
	label.text = text
	label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	add_child(label)


func add_title(text: String) -> void:
	var label := Label.new()
	label.text = text
	label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
	label.custom_minimum_size = Vector2(0, 32)
	add_child(label)

Cliques que não alcançam o jogo

mouse_filter decide se um controle consome entrada do mouse. Os padrões diferem: Control, ColorRect e Panel comuns usam MOUSE_FILTER_STOP, containers usam MOUSE_FILTER_PASS, Label usa MOUSE_FILTER_IGNORE. Um Control ou ColorRect em tela cheia com STOP engole todos os cliques, então _unhandled_input() no jogo nunca os vê. Defina mouse_filter = Control.MOUSE_FILTER_IGNORE em sobreposições, espaçadores e retângulos decorativos.

Overrides de tema (nomes Godot 4)

Godot 3Godot 4
add_color_override("font_color", c)add_theme_color_override("font_color", c)
add_font_override("font", f)add_theme_font_override("font", f)
(tamanho da fonte ficava em DynamicFont)add_theme_font_size_override("font_size", 24)
add_stylebox_override("normal", sb)add_theme_stylebox_override("normal", sb)
add_constant_override("separation", 8)add_theme_constant_override("separation", 8)
add_icon_override("icon", tex)add_theme_icon_override("icon", tex)
custom_colors/font_color no .tscntheme_override_colors/font_color

Remova um override com o remove_theme_*_override(nome) correspondente. Para uma aparência consistente, atribua um recurso Theme ao controle raiz em vez de sobrescrever cada nó; os filhos o herdam.

Resolução e esticamento

Defina estas opções em Project Settings > Display > Window (elas são armazenadas em project.godot):

  • display/window/size/viewport_width e viewport_height: a resolução base para a qual você projeta (padrão 1152 x 648).
  • display/window/stretch/mode: canvas_items para a maioria dos jogos (UI e 2D escalam suavemente), viewport para pixel art, disabled para ferramentas. O modo 2d do Godot 3 é canvas_items no Godot 4. O padrão da configuração é disabled; projetos criados no Godot 4.7 ou posterior iniciam com canvas_items.
  • display/window/stretch/aspect: expand permite que a UI ancorada use espaço extra em telas mais largas ou altas; keep adiciona barras pretas. O padrão é keep; projetos criados no Godot 4.7 ou posterior iniciam com expand.
  • display/window/stretch/scale_mode: integer para pixel art nítida.

Em tempo de execução, as mesmas configurações estão na janela: get_window().content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS e get_window().content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND.

Checklist quando a UI está cortada ou mal posicionada

  1. O controle é filho de um container com position ou size definidos manualmente? Use flags de tamanho e custom_minimum_size.
  2. A raiz foi ancorada apenas com set_anchors_preset()? Use set_anchors_and_offsets_preset().
  3. Uma Label com quebra de linha tem uma largura?
  4. O HUD está sob um CanvasLayer em vez de um Node2D?
  5. display/window/stretch/mode ainda está disabled enquanto o tamanho da janela muda?
  6. Um controle invisível em tela cheia com MOUSE_FILTER_STOP está por cima?

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ziva-sh/godot-4-api-pitfalls

Fixes Godot 3 APIs and GDScript syntax that AI assistants write into Godot 4 projects, such as KinematicBody2D, move_and_slide(velocity), export, onready, setget, yield, string connect(), instance(), rand_range, the Tween node, File, change_scene, Spatial, rect_* properties, Pool*Array, OS time functions and the old TileMap API. Use when writing, reviewing or porting GDScript for Godot 4.x, when a script fails with "not declared", "not found in base", "was removed in Godot 4" or "is not present

ziva-sh/godot-scene-organization

Structures Godot 4 projects so scenes stay reusable and references do not break - when to make a scene, a script or a Resource, instancing with @export PackedScene, preload and load, @onready and %UniqueName node access, _ready order, groups, autoloads, class_name, and resource UIDs with the .uid files added in Godot 4.4, including how to move or rename files safely. Use when creating new scenes or scripts, deciding how nodes find each other, adding global state or an event bus, moving or renami

ziva-sh/godot-signals

Godot 4 signal patterns and their failure modes - declaring typed signals, emit(), connect() and disconnect() with Callables, bind() and unbind(), lambdas, CONNECT_ONE_SHOT and CONNECT_DEFERRED, await on signals and timers, editor-made connections stored in .tscn files, and the call down, signal up rule. Use when wiring UI buttons, timers, Area2D or body events and custom game events, when replacing Godot 3 connect("signal", self, "method") or yield code, or when debugging "already connected", "

ziva-sh/godot-tilemaplayer

Correct Godot 4.3+ TileMapLayer code - set_cell(coords, source_id, atlas_coords), reading cells and custom data, erasing, coordinate conversion, terrains, tile collision through TileSet physics layers, finding the tile a body hit, and migrating from the deprecated TileMap node and its layer-index API. Use when placing, reading or erasing tiles from GDScript, building a TileSet in code, generating levels procedurally, handling tile collisions, or porting TileMap code from Godot 3 or Godot 4.0 to

Habilidades Relacionadas