From 5673f44b2db21987c0abb453c40484c1d223cb99 Mon Sep 17 00:00:00 2001 From: betalars Date: Mon, 24 Mar 2025 17:17:25 +0100 Subject: [PATCH] fix infinite recursion and focus management issues in video settings --- src/logic-scenes/main menu/video_settings.gd | 59 +++++++++++++------ .../main menu/video_settings.tscn | 44 ++++++++------ 2 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/logic-scenes/main menu/video_settings.gd b/src/logic-scenes/main menu/video_settings.gd index e6a96ac..cc35a1b 100644 --- a/src/logic-scenes/main menu/video_settings.gd +++ b/src/logic-scenes/main menu/video_settings.gd @@ -1,47 +1,47 @@ extends VBoxContainer +# This is a hack so values changing to the default to not create a recursion. signal changed signal leave_stage var has_stage:bool = false: set(stage): has_stage = stage - preset_selected = preset_selected + match preset_selected: + 1: %PerformancePreset.grab_focus() + 2: %BalancedPreset.grab_focus() + 3: %QualityPreset.grab_focus() + _: %FullscreenMode.grab_focus() @export_file(".json") var settings_path = "user://video_settings.json" @export_enum("None", "Performance", "Balanced", "Quality") var preset_selected:int = 2: set(value): + # this may not call changed! preset_selected = value - if has_stage: - match preset_selected: - 1: %PerformancePreset.grab_focus() - 2: %BalancedPreset.grab_focus() - 3: %QualityPreset.grab_focus() - _: %FullscreenMode.grab_focus() @export var window_mode: DisplayServer.WindowMode = DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN: set(value): window_mode = value - changed.emit() + if not ignore_changes: changed.emit() @onready var fullscreen_selector: OptionButton = %FullscreenMode @export_range(0.5, 2) var render_scale: float = 1: set(value): render_scale = value - changed.emit() + if not ignore_changes: changed.emit() @onready var scale_selector: SpinBox = %RenderScale @export var upscale_mode: RenderingServer.ViewportScaling3DMode = RenderingServer.ViewportScaling3DMode.VIEWPORT_SCALING_3D_MODE_BILINEAR : set(value): upscale_mode = value - changed.emit() + if not ignore_changes: changed.emit() @onready var upscale_selector: OptionButton = %SuperResolution @export_range(30, 144) var max_fps: int = 60: set(value): max_fps = value - changed.emit() + if not ignore_changes: changed.emit() @onready var fps_enabler: CheckBox = %EnableFps var fps_enabled: bool: set(value): @@ -52,37 +52,39 @@ var fps_enabled: bool: @export_enum("low", "medium", "high", "ultra") var lighting_quality: int = 3: set(value): lighting_quality = value - changed.emit() + if not ignore_changes: changed.emit() @onready var lightning_selector: OptionButton = %LightingQuality @export_enum("low", "medium", "high") var shadow_quality: int = 3: set(value): shadow_quality = value - changed.emit() + if not ignore_changes: changed.emit() @onready var shadow_selector: OptionButton = %ShadowQuality @export_enum("no", "1x", "2x", "4x", "8x") var texture_filtering:int = 3: set(value): texture_filtering = value - changed.emit() + if not ignore_changes: changed.emit() @onready var texture_selector: OptionButton = %TextureFiltering @export_enum("no", "1x", "2x", "4x") var msaa = 0: set(value): msaa = value - changed.emit() + if not ignore_changes: changed.emit() @onready var msaa_selector: OptionButton = %AntiAlaising @export var vsync_mode: DisplayServer.VSyncMode = DisplayServer.VSyncMode.VSYNC_ENABLED: set(value): vsync_mode = value - changed.emit() + if not ignore_changes: changed.emit() @onready var vsync_selector: OptionButton = %vSync +var ignore_changes: bool = false var has_changed: bool = false: set(value): has_changed = value - preset_selected = 0 + if not ignore_changes: + preset_selected = 0 if has_changed: %ExitButton.text = "discard" else: @@ -106,7 +108,7 @@ func _ready() -> void: fps_selector.value_changed.connect(func(value): max_fps = value) fps_enabler.toggled.connect(func(value): fps_enabled = value) - changed.connect(func():has_changed = true) + changed.connect(func(): has_changed = true) preset_selected = preset_selected @@ -114,6 +116,9 @@ func _ready() -> void: %ConfirmExit.pressed.connect(_on_exit_confirmed) %ConfirmSave.pressed.connect(_on_confirm_button_pressed) %ConfirmAbort.pressed.connect($Popup.hide) + %PerformancePreset.pressed.connect(_on_performance_preset_pressed) + %BalancedPreset.pressed.connect(_on_balanced_preset_pressed) + %QualityPreset.pressed.connect(_on_quality_preset_pressed) func load_settings(): @@ -205,6 +210,9 @@ func _on_confirm_button_pressed() -> void: save_settings() func _on_performance_preset_pressed() -> void: + ignore_changes = true + has_changed = true + render_scale = 0.8 max_fps = 60 fps_enabled = true @@ -216,9 +224,15 @@ func _on_performance_preset_pressed() -> void: propagate_settings() + changed.emit() + ignore_changes = false + preset_selected = 1 func _on_balanced_preset_pressed() -> void: + ignore_changes = true + has_changed = true + render_scale = 1 max_fps = 60 fps_enabled = true @@ -230,9 +244,15 @@ func _on_balanced_preset_pressed() -> void: propagate_settings() + changed.emit() + ignore_changes = false + preset_selected = 2 func _on_quality_preset_pressed() -> void: + ignore_changes = true + has_changed = true + render_scale = 1 max_fps = 60 fps_enabled = false @@ -243,6 +263,9 @@ func _on_quality_preset_pressed() -> void: vsync_mode = DisplayServer.VSyncMode.VSYNC_ENABLED propagate_settings() + + changed.emit() + ignore_changes = false preset_selected = 3 diff --git a/src/logic-scenes/main menu/video_settings.tscn b/src/logic-scenes/main menu/video_settings.tscn index d4d6e66..74b90cb 100644 --- a/src/logic-scenes/main menu/video_settings.tscn +++ b/src/logic-scenes/main menu/video_settings.tscn @@ -44,37 +44,37 @@ func _ready() -> void: func _input(event: InputEvent) -> void: if has_focus(): - if Input.is_action_just_pressed(\"ui_accept\"): - print(\"pressed!\") - print(pressed) + if event.is_action_pressed(\"ui_accept\"): pressed = not pressed - print(pressed) get_viewport().set_input_as_handled() if pressed: - - if Input.is_action_just_pressed(\"ui_up\") or Input.is_action_just_pressed(\"ui_right\"): + grab_focus() + # + if event.is_action_pressed(\"ui_up\") or event.is_action_pressed(\"ui_right\"): value += step - get_viewport().set_input_as_handled() - await(get_tree().create_timer(hold_down_delay).timeout) + call_deferred(\"check_input_held\", true) - while Input.is_action_pressed(\"ui_up\") or Input.is_action_pressed(\"ui_right\"): - value += step * repeat_multiplier - await(get_tree().create_timer(repeat_delay).timeout) - - elif Input.is_action_just_pressed(\"ui_down\") or Input.is_action_just_pressed(\"ui_left\"): + elif event.is_action_pressed(\"ui_down\", true) or event.is_action_pressed(\"ui_left\", true): value -= step - get_viewport().set_input_as_handled() - else: - if Input.is_action_just_pressed(\"ui_up\"): - print(focus_neighbor_top) + + call_deferred(\"check_input_held\", false) + get_viewport().set_input_as_handled() + func _on_focus_enter(): get_line_edit().add_theme_stylebox_override(\"normal\", focus_stylebox) func _on_focus_exit(): get_line_edit().remove_theme_stylebox_override(\"normal\") + +func check_input_held(upward: bool): + await(get_tree().create_timer(repeat_delay).timeout) + while ((Input.is_action_pressed(\"ui_up\", true) or Input.is_action_pressed(\"ui_right\", true) and upward) or (Input.is_action_pressed(\"ui_down\", true) or Input.is_action_pressed(\"ui_left\", true) and not upward)): + value += step * repeat_multiplier * (1 if upward else -1) + await(get_tree().create_timer(repeat_delay).timeout) + " [node name="Video Settings" type="VBoxContainer"] @@ -134,6 +134,7 @@ layout_mode = 2 selected = 1 item_count = 3 popup/item_0/text = "Windowed" +popup/item_0/id = 0 popup/item_1/text = "Fullscreen" popup/item_1/id = 1 popup/item_2/text = "exclusive Fullscreen" @@ -152,6 +153,7 @@ text = "reset" [node name="RenderScale" type="SpinBox" parent="GridContainer/HBoxContainer"] unique_name_in_owner = true +custom_minimum_size = Vector2(120, 0) layout_mode = 2 focus_mode = 2 min_value = 0.25 @@ -174,7 +176,8 @@ layout_mode = 2 selected = 0 item_count = 3 popup/item_0/text = "disabled" -popup/item_1/text = " " +popup/item_0/id = 0 +popup/item_1/text = " FSR 1.0" popup/item_1/id = 1 popup/item_2/text = "FSR 2.2" popup/item_2/id = 2 @@ -214,6 +217,7 @@ layout_mode = 2 selected = 1 item_count = 4 popup/item_0/text = "minimum" +popup/item_0/id = 0 popup/item_1/text = "low (SDF Global Illumination)" popup/item_1/id = 1 popup/item_2/text = "medium (SDF and Screen Space Global Illumination)" @@ -231,6 +235,7 @@ layout_mode = 2 selected = 1 item_count = 3 popup/item_0/text = "performance" +popup/item_0/id = 0 popup/item_1/text = "balanced" popup/item_1/id = 1 popup/item_2/text = "quality" @@ -246,6 +251,7 @@ layout_mode = 2 selected = 1 item_count = 6 popup/item_0/text = "disabled" +popup/item_0/id = 0 popup/item_1/text = "1x (very fast)" popup/item_1/id = 1 popup/item_2/text = "2x (fast)" @@ -267,6 +273,7 @@ layout_mode = 2 selected = 1 item_count = 4 popup/item_0/text = "disabled" +popup/item_0/id = 0 popup/item_1/text = "2x MSAA" popup/item_1/id = 1 popup/item_2/text = "4x MSAA" @@ -284,6 +291,7 @@ layout_mode = 2 selected = 1 item_count = 4 popup/item_0/text = "disabled" +popup/item_0/id = 0 popup/item_1/text = "enabled" popup/item_1/id = 1 popup/item_2/text = "adaptive"