GGua REFERENCE日本語GitHub ↗
GODOT / UI

Install and implement UI

Install the released addon, then connect UI built from standard Controls to the automatic collector.

Install the packaged add-on

  1. Open the latest release

    Download the Godot ZIP from the release assets and extract it.

  2. Copy addons/gua
    Expected layouttext
    your-game/
    ├─ project.godot
    └─ addons/
       └─ gua/
          ├─ gua.gdextension
          ├─ gua_auto_adapter.gd
          ├─ plugin.cfg
          └─ bin/

    What each file does

    CodeMeaning
    project.godotThe main Godot project configuration.
    addons/gua/gua.gdextensionTells Godot how to load the native Gua extension.
    addons/gua/gua_auto_adapter.gdCollects Controls and routes external actions back into Godot.
    addons/gua/plugin.cfgDeclares the add-on and its editor entry point.
    addons/gua/bin/Contains the platform-specific native libraries loaded by the extension.
  3. Open the project in Godot

    Check the Godot output to confirm that the GDExtension loaded successfully.

Attach it from GDScript

  1. Preload the adapter explicitly

    Explicit preload avoids depending on class_name registration order.

    main.gdgdscript
    extends Control
    
    const GuaAutoAdapterScript := preload(
      "res://addons/gua/gua_auto_adapter.gd"
    )
    
    var ui := GuaAutoAdapterScript.new()
    
    func _ready() -> void:
      ui.attach(self)
      ui.update("title")
      ui.start_inspector_bridge(8765)
    
    func _process(_delta: float) -> void:
      ui.update("title")

    Read main.gd from top to bottom

    CodeMeaning
    extends ControlMakes this script a root UI Control and a valid value for attach(self).
    preload("res://addons/gua/gua_auto_adapter.gd")Loads the adapter script explicitly before the scene starts.
    var ui := GuaAutoAdapterScript.new()Creates one adapter instance for collection and action dispatch.
    func _ready() -> void:Runs once after this Control and its children enter the scene tree.
    ui.attach(self)Sets this Control as the root; Controls below it become the collection scope.
    ui.update("title")Publishes the current Controls under the logical screen name title.
    ui.start_inspector_bridge(8765)Starts the WebSocket bridge used by Inspector, MCP, and external tests.
    func _process(_delta: float) -> void:Runs every rendered frame; the underscore marks the unused elapsed-time argument.
    ui.update("title")Re-collects state and dispatches queued external actions every frame.
  2. Pin IDs only where stability matters

    The default ID comes from the NodePath. Use metadata when an ID must survive scene-tree refactoring.

    Stable and sensitive fieldsgdscript
    name_input.set_meta("gua_id", "login-user")
    password_input.set_meta("gua_id", "login-password")
    password_input.set_meta("gua_sensitive", true)

    What the metadata means

    CodeMeaning
    name_input.set_meta("gua_id", "login-user")Pins a test-facing ID that survives NodePath refactoring.
    password_input.set_meta("gua_id", "login-password")Pins a stable ID for the password field.
    password_input.set_meta("gua_sensitive", true)Prevents plaintext from entering the semantic tree, retained history, or diagnostics. Mask rendered screenshots separately.

Publish a World Object Tree

For a door, enemy, objective, or other non-UI object, add its Node2D or Node3D to the gua_world_object group and attach semantic metadata. The adapter collects position and state on each ui.update(), so game code does not call the native registration API directly.

Publish a door as a game-world objectgdscript
@onready var reactor_door: Node2D = $World/ReactorDoor
var reactor_door_locked := true

func expose_reactor_door() -> void:
  reactor_door.add_to_group(&"gua_world_object")
  reactor_door.set_meta(&"gua_world_id", "reactor-door")
  reactor_door.set_meta(&"gua_world_kind", "door")
  reactor_door.set_meta(&"gua_world_label", "Reactor door")
  reactor_door.set_meta(&"gua_world_visible_to_player", true)
  reactor_door.set_meta(&"gua_world_tags", ["reactor", "mission-critical"])
  update_reactor_door_state()

func update_reactor_door_state() -> void:
  reactor_door.set_meta(&"gua_world_state", {
    "locked": reactor_door_locked,
    "power": "online"
  })

Call expose_reactor_door() once from _ready(), then call update_reactor_door_state() whenever the door changes. gua_world_id is required and unique within the frame. Position comes from global_position, and the nearest published ancestor becomes the parent. Keep state flat and limited to strings, finite numbers, booleans, or null. See World Object Tree for the conceptual model and query tools.

Export to Web

The same released add-on supports Godot Web Debug and Release exports. In the Web export preset, enable Extension Support and use the single-threaded variant. Godot reads gua.gdextension and selects the matching web.wasm32.single.debug or web.wasm32.single.release WASM automatically.

Commonly observed Controls

Inputs

LineEdit, TextEdit, CheckBox, OptionButton, and ItemList

State

Focus, selection, value, scrolling, ranges, visibility, and enabled state