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 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 _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(18.0, 18.0) _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 if theme_res: _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")) var icon_path: String = STANCE_ICONS.get(stance, "") if _icon and not icon_path.is_empty(): var tex := load(icon_path) as Texture2D if tex: _icon.texture = tex _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