Files
settled-reach/client/ui/stance_indicator.gd
T
jpmschweitzerandClaude Opus 4.6 168c5e0d9b fix(ui): restore STANCE_ICONS constant removed during refactor
Startup crash — preload loop referenced STANCE_ICONS but the constant
was accidentally dropped when rewriting the icon cache logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 16:43:49 +02:00

103 lines
3.1 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Control
## D-053: Stance indicator — implant-styled badge (D-169).
## Sprint/Walk/Careful/Crouch. Icon (D-086) + color-coded label.
const STANCE_COLORS := {
"Sprint": Color("#d45d5d"), # Red — fast, loud, dangerous
"Walk": Color("#c8d0e0"), # Default — neutral white-blue
"Careful": Color("#6bc9a6"), # Green — quiet, observant
"Crouch": Color("#e8c547"), # Amber — very quiet, slow
}
const STANCE_ICONS := {
"Sprint": "res://assets/icons/icon_stance_sprint.svg",
"Walk": "res://assets/icons/icon_stance_walk.svg",
"Careful": "res://assets/icons/icon_stance_careful.svg",
"Crouch": "res://assets/icons/icon_stance_crouch.svg",
}
var _current_stance: String = "Walk"
var _panel: ImplantPanel
var _icon: TextureRect
var _label: Label
var _icon_mat: ShaderMaterial
var _icon_cache: Dictionary = {} # stance name → Texture2D
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_IGNORE
var theme_res := load("res://ui/implant/default_implant.tres") as ImplantTheme
var icon_shader := load("res://shaders/icon_tint.gdshader") as Shader
if not theme_res:
push_error("StanceIndicator: failed to load implant theme")
return
if not icon_shader:
push_error("StanceIndicator: failed to load icon_tint shader")
return
# Preload all stance icons at startup
for stance_name in STANCE_ICONS:
var tex := load(STANCE_ICONS[stance_name]) as Texture2D
if tex:
_icon_cache[stance_name] = tex
else:
push_error("StanceIndicator: failed to load icon for %s" % stance_name)
_panel = ImplantPanel.new()
_panel.name = "StancePanel"
_panel.theme_resource = theme_res
_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(_panel)
var hbox := HBoxContainer.new()
hbox.add_theme_constant_override("separation", 4)
hbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
_icon = TextureRect.new()
_icon.expand_mode = TextureRect.EXPAND_KEEP_SIZE
_icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
_icon.custom_minimum_size = Vector2(20.0, 20.0) # D-086: 20×20 viewBox
_icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
_icon_mat = ShaderMaterial.new()
_icon_mat.shader = icon_shader
_icon_mat.set_shader_parameter("tint_color", STANCE_COLORS["Walk"])
_icon.material = _icon_mat
hbox.add_child(_icon)
_label = Label.new()
_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
_label.add_theme_font_size_override("font_size", theme_res.font_body)
hbox.add_child(_label)
_panel.add_component(hbox)
_apply_stance("Walk")
func _apply_stance(stance: String) -> void:
_current_stance = stance
var color: Color = STANCE_COLORS.get(stance, Color("#c8d0e0"))
if _icon:
var tex: Texture2D = _icon_cache.get(stance)
if tex:
_icon.texture = tex
if _icon_mat:
_icon_mat.set_shader_parameter("tint_color", color)
if _label:
_label.text = stance
_label.add_theme_color_override("font_color", color)
func update_from_state() -> void:
var stance: String = GameState.player_stance
if stance == _current_stance:
return
_apply_stance(stance)
func get_current_stance() -> String:
return _current_stance