class_name ValueStepper extends Control ## A reusable UI control for stepping through discrete values with arrow buttons ## ## ValueStepper provides left/right arrow navigation for cycling through predefined options. ## Perfect for settings like language, resolution, difficulty, graphics quality, etc. ## Supports both mouse clicks and keyboard/gamepad navigation. ## ## @tutorial(ValueStepper Usage): See docs/UI_COMPONENTS.md signal value_changed(new_value: String, new_index: int) ## The data source for values. @export var data_source: String = "language" ## Custom display format function. Leave empty to use default. @export var custom_format_function: String = "" var values: Array[String] = [] var display_names: Array[String] = [] var current_index: int = 0 var original_scale: Vector2 var original_modulate: Color var is_highlighted: bool = false @onready var left_button: Button = $LeftButton @onready var right_button: Button = $RightButton @onready var value_display: Label = $ValueDisplay func _ready() -> void: DebugManager.log_info("ValueStepper ready for: " + data_source, "ValueStepper") # Store original visual properties original_scale = scale original_modulate = modulate # Connect button signals if left_button and not left_button.pressed.is_connected(_on_left_button_pressed): left_button.pressed.connect(_on_left_button_pressed) if right_button and not right_button.pressed.is_connected(_on_right_button_pressed): right_button.pressed.connect(_on_right_button_pressed) # Initialize data _load_data() _update_display() ## Loads data based on the data_source type func _load_data() -> void: match data_source: "language": _load_language_data() "resolution": _load_resolution_data() "difficulty": _load_difficulty_data() _: DebugManager.log_warn("Unknown data_source: " + data_source, "ValueStepper") func _load_language_data() -> void: var languages_data: Dictionary = SettingsManager.get_languages_data() if languages_data.has("languages"): values.clear() display_names.clear() for lang_code in languages_data.languages.keys(): values.append(lang_code) display_names.append(languages_data.languages[lang_code]["display_name"]) # Set current index based on current language var current_lang: String = SettingsManager.get_setting("language") var index: int = values.find(current_lang) current_index = max(0, index) DebugManager.log_info("Loaded %d languages" % values.size(), "ValueStepper") func _load_resolution_data() -> void: # Example resolution data - customize as needed values = ["1920x1080", "1366x768", "1280x720", "1024x768"] display_names = ["1920×1080 (Full HD)", "1366×768", "1280×720 (HD)", "1024×768"] current_index = 0 DebugManager.log_info("Loaded %d resolutions" % values.size(), "ValueStepper") func _load_difficulty_data() -> void: # Example difficulty data - customize as needed values = ["easy", "normal", "hard", "nightmare"] display_names = ["Easy", "Normal", "Hard", "Nightmare"] current_index = 1 # Default to "normal" DebugManager.log_info("Loaded %d difficulty levels" % values.size(), "ValueStepper") ## Updates the display text based on current selection func _update_display() -> void: if values.size() == 0 or current_index < 0 or current_index >= values.size(): value_display.text = "N/A" return if display_names.size() > current_index: value_display.text = display_names[current_index] else: value_display.text = values[current_index] ## Changes the current value by the specified direction (-1 for previous, +1 for next) func change_value(direction: int) -> void: if values.size() == 0: DebugManager.log_warn("No values available for: " + data_source, "ValueStepper") return var new_index: int = (current_index + direction) % values.size() if new_index < 0: new_index = values.size() - 1 current_index = new_index var new_value: String = values[current_index] _update_display() _apply_value_change(new_value, current_index) value_changed.emit(new_value, current_index) DebugManager.log_info( "Value changed to: " + new_value + " (index: " + str(current_index) + ")", "ValueStepper" ) ## Override this method for custom value application logic func _apply_value_change(new_value: String, _index: int) -> void: match data_source: "language": SettingsManager.set_setting("language", new_value) if LocalizationManager: LocalizationManager.change_language(new_value) "resolution": # Apply resolution change logic here DebugManager.log_info("Resolution would change to: " + new_value, "ValueStepper") "difficulty": # Apply difficulty change logic here DebugManager.log_info("Difficulty would change to: " + new_value, "ValueStepper") ## Sets up custom values for the stepper func setup_custom_values( custom_values: Array[String], custom_display_names: Array[String] = [] ) -> void: values = custom_values.duplicate() display_names = ( custom_display_names.duplicate() if custom_display_names.size() > 0 else values.duplicate() ) current_index = 0 _update_display() DebugManager.log_info("Setup custom values: " + str(values.size()) + " items", "ValueStepper") ## Gets the current value func get_current_value() -> String: if values.size() > 0 and current_index >= 0 and current_index < values.size(): return values[current_index] return "" ## Sets the current value by string func set_current_value(value: String) -> void: var index: int = values.find(value) if index >= 0: current_index = index _update_display() ## Visual highlighting for navigation systems func set_highlighted(highlighted: bool) -> void: is_highlighted = highlighted if highlighted: scale = original_scale * UIConstants.UI_CONTROL_HIGHLIGHT_SCALE modulate = Color(1.1, 1.1, 0.9) else: scale = original_scale modulate = original_modulate ## Handle input actions for navigation integration func handle_input_action(action: String) -> bool: match action: "move_left": change_value(-1) return true "move_right": change_value(1) return true _: return false func _on_left_button_pressed() -> void: AudioManager.play_ui_click() DebugManager.log_info("Left button clicked", "ValueStepper") change_value(-1) func _on_right_button_pressed() -> void: AudioManager.play_ui_click() DebugManager.log_info("Right button clicked", "ValueStepper") change_value(1) ## For navigation system integration func get_control_name() -> String: return data_source + "_stepper"