TargetInformer UI Component
Status: Stable - Refactored in v5.1.0 to use view-only architecture
The TargetInformer component displays information about the current game object being targeted, manipulated, or built. It automatically shows the highest-priority object based on the game state with no need for manual state management.
Overview
Section titled “Overview”TargetInformer reads from three authoritative state sources and displays information about whichever has the highest priority:
- Manipulation State (Highest Priority) - Active manipulated objects
- Building State (Medium Priority) - Building preview objects
- Targeting State (Lowest Priority) - Hovered/targeted objects
This design eliminates state synchronization issues by reading directly from the source rather than maintaining a separate copy.
Architecture (v5.1.0)
Section titled “Architecture (v5.1.0)”View-Only Component Pattern
Section titled “View-Only Component Pattern”TargetInformer is a pure view component that:
- Reads from authoritative state sources
- Never maintains independent state
- Automatically updates when any state source changes
- Computes display target on-demand via the
get_display_target()method
## Returns the current display target based on priority:## 1. Manipulation (highest) → 2. Building → 3. Targeting (lowest)func get_display_target() -> Node: # Priority 1: Manipulation if _manipulation_state and _manipulation_state.get_active_root() != null: return _manipulation_state.get_active_root()
# Priority 2: Building preview if _building_state and _building_state.preview != null: return _building_state.preview
# Priority 3: Targeting (lowest) if _targeting_state: return _targeting_state.get_target()
return nullState Change Detection
Section titled “State Change Detection”All state changes trigger a unified _on_state_changed() handler:
func resolve_gb_dependencies(p_container: GBCompositionContainer) -> void: # ... resolve state references ...
# Connect to state changes if _manipulation_state: _manipulation_state.active_manipulatable_changed.connect(_on_state_changed) _manipulation_state.started.connect(_on_state_changed) _manipulation_state.canceled.connect(_on_state_changed) _manipulation_state.finished.connect(_on_state_changed)
if _building_state: _building_state.preview_changed.connect(_on_state_changed)
if _targeting_state: _targeting_state.target_changed.connect(_on_state_changed)When any state changes, _on_state_changed() is called, which triggers refresh():
func _on_state_changed(_unused1 = null, _unused2 = null): refresh()
func refresh(): var current = display_target
# If target changed, rebuild UI if current != _last_display_target: _last_display_target = current setup_for_target(current) return
# Update position every frame (for moving targets) if _position_label and current is Node2D: _position_label.text = _format_position(current)Basic Setup
Section titled “Basic Setup”# Create and add to scenevar informer = TargetInformer.new()add_child(informer)
# Inject dependenciesvar container = GBCompositionContainer.new()informer.resolve_gb_dependencies(container)
# Now automatically displays highest-priority target# No further manual updates neededAccessing Display Target
Section titled “Accessing Display Target”# Get the current display targetvar target = informer.get_display_target()
# Target is automatically determined by priority:# - Active manipulation has highest priority# - Building preview is second priority# - Targeted object is lowest priority
if target != null: print("Displaying: %s" % target.name)Configuring Display Format
Section titled “Configuring Display Format”The TargetInfoSettings resource controls display formatting:
# Position display formatsettings.position_format = "Position: (%s, %s)"settings.position_decimals = 2 # Round to 2 decimal placesMode-Based Visibility
Section titled “Mode-Based Visibility”TargetInformer respects ModeState for visibility control:
# Automatically hides when mode is OFF# Automatically shows when mode is ON# (handled internally by _on_mode_changed handler)Priority System
Section titled “Priority System”When Multiple States Have Values
Section titled “When Multiple States Have Values”The priority system determines what gets displayed:
Scenario: User is targeting object A, but picks up object B to manipulate
display_target returns: B (manipulation has priority over targeting)
After manipulation ends:display_target returns: A (targeting becomes active again)Changing Priority Order
Section titled “Changing Priority Order”To change the priority order, modify the display_target property getter:
# Example: If you want Building to have highest priorityvar display_target: Node: get(): # Priority 1: Building preview (new highest) if _building_state and _building_state.preview != null: return _building_state.preview
# Priority 2: Manipulation if _manipulation_state and _manipulation_state.get_active_root() != null: return _manipulation_state.get_active_root()
# Priority 3: Targeting (lowest) if _targeting_state: return _targeting_state.get_target()
return nullDisplay Format
Section titled “Display Format”Name Display
Section titled “Name Display”TargetInformer displays the object name using GBObjectUtils.get_display_name():
# Override _to_string() on your objects for custom names:class_name MyObject extends Node
func _to_string() -> String: return "Custom Object Name"Position Display
Section titled “Position Display”For Node2D and Node3D objects, position is displayed:
# Uses settings.position_format and settings.position_decimals# Format: "Position: (X, Y)"# Example: "Position: (10.50, 20.75)"UI Structure
Section titled “UI Structure”TargetInformer creates labels in the info_parent container:
@export var info_parent: Control
# Automatically populates with:# - _name_label: displays object name# - _position_label: displays position (if applicable)Troubleshooting
Section titled “Troubleshooting”Display Not Updating
Section titled “Display Not Updating”Problem: TargetInformer shows stale information
Solution: Ensure all state sources are properly injected. In runtime builds prefer non-failing checks and helpful logging:
# Verify states are assigned (runtime-safe checks)if _manipulation_state == null or _building_state == null or _targeting_state == null: push_warning("One or more Grid Building states not injected; ensure GBCompositionContainer is provided")Target Shows Wrong Object
Section titled “Target Shows Wrong Object”Problem: Display_target returns unexpected object
Solution: Check priority order. Highest-priority state source will always be shown:
# Debug: Check which state has priorityif _manipulation_state and _manipulation_state.get_active_root(): print("Manipulation active - will be displayed")elif _building_state and _building_state.preview: print("Building preview active - will be displayed")elif _targeting_state and _targeting_state.get_target(): print("Targeting active - will be displayed")Position Not Showing
Section titled “Position Not Showing”Problem: Position label doesn’t appear
Checks:
- Ensure target is
Node2DorNode3D(notNode) - Verify TargetInfoSettings has valid
position_format - Check that
info_parentis properly configured
API Reference
Section titled “API Reference”Methods
Section titled “Methods”get_display_target() -> Node
Section titled “get_display_target() -> Node”- Description: Returns the highest-priority display target
- Returns: The target to display, or
nullif no state source has a target - Type: Public
- Priority: Manipulation > Building > Targeting
resolve_gb_dependencies(p_container: GBCompositionContainer)
Section titled “resolve_gb_dependencies(p_container: GBCompositionContainer)”- Description: Inject dependencies and connect to state signals
- Parameters: Composition container with states and settings
- Signal Connections: Connects all state source signals to unified handler
refresh()
Section titled “refresh()”- Description: Update display based on current state
- Timing: Called every frame and on state changes
- Behavior: Detects target changes and rebuilds UI if needed
setup_for_target(p_target: Node)
Section titled “setup_for_target(p_target: Node)”- Description: Build UI labels for the given target
- Parameters: Target node to display (can be null)
- Clears: All existing labels before creating new ones
_format_position(p_target: Node) -> String
Section titled “_format_position(p_target: Node) -> String”- Description: Format position based on settings
- Parameters: Node2D or Node3D object
- Returns: Formatted position string
Last Updated: October 2025 | Version: 5.1.0+