Godot Version
4.5.1
Question
I changed the parent of the BoxMenu now my code aint working, when I click Options in the GameMenu it shows me the error Invalid access to property or key ‘item_selected’ on a base object of type ‘null instance’. "see screenshot for more details"
It worked before (not perfect), I tried the name it correct in the :
UI refs
@onready var resolution_dropdown: OptionButton = $OptionsMenu/OptionMenu/OptionsBox/Resolution/ResolutionDropdown
extends Control
# -------------------------
# VARIABELEN
# -------------------------
var pending_resolution: Vector2i = Vector2i.ZERO
var old_resolution: Vector2i = Vector2i.ZERO
var countdown: int = 15
var countdown_timer: Timer
var fullscreen_pending := false
# UI refs
@onready var resolution_dropdown: OptionButton = $OptionsMenu/OptionMenu/OptionsBox/Resolution/ResolutionDropdown
@onready var fullscreen_check: BaseButton = $OptionsMenu/OptionMenu/OptionsBox/Fullscreen/FullscreenCheck
@onready var subtitles_check: BaseButton = $OptionsMenu/OptionMenu/OptionsBox/Subtitles/SubtitlesCheck
@onready var language_dropdown: OptionButton = $OptionsMenu/OptionMenu/OptionsBox/Language/LanguageDropdown
@onready var music_slider: HSlider = $OptionsMenu/OptionMenu/OptionsBox/"Music Volume"/MusicSlider
@onready var speech_slider: HSlider = $OptionsMenu/OptionMenu/OptionsBox/"Speech Volume"/SpeechSlider
@onready var sfx_slider: HSlider = $OptionsMenu/OptionMenu/OptionsBox/"SFX Volume"/SFXSlider
@onready var resolution_popup: Popup = $ResolutionPopup
@onready var countdown_label: Label = $ResolutionPopup/CountdownLabel
@onready var apply_button: TextureButton = $ResolutionPopup/ApplyButton
@onready var cancel_button: TextureButton = $ResolutionPopup/CancelButton
@onready var save_button = $SaveButton
@onready var exit_button = $ExitButton
# -------------------------
# READY
# -------------------------
func _ready() -> void:
# Timer
countdown_timer = Timer.new()
countdown_timer.wait_time = 1.0
countdown_timer.one_shot = false
add_child(countdown_timer)
countdown_timer.timeout.connect(_on_countdown_tick)
# Signals via code (dan hoef je in de editor minder te klikken)
resolution_dropdown.item_selected.connect(_on_resolution_selected)
apply_button.pressed.connect(_on_apply_pressed)
cancel_button.pressed.connect(_on_cancel_pressed)
save_button.pressed.connect(_on_save_button_pressed)
exit_button.pressed.connect(_on_exit_button_pressed)
fullscreen_check.toggled.connect(_on_fullscreen_check_toggled)
subtitles_check.toggled.connect(_on_subtitles_check_toggled)
language_dropdown.item_selected.connect(_on_language_dropdown_item_selected)
music_slider.value_changed.connect(_on_music_slider_value_changed)
speech_slider.value_changed.connect(_on_speech_slider_value_changed)
sfx_slider.value_changed.connect(_on_sfx_slider_value_changed)
load_settings()
# -------------------------
# LOAD / SAVE
# -------------------------
func load_settings() -> void:
var config := ConfigFile.new()
if config.load("user://settings.cfg") != OK:
return
var res_id: int = config.get_value("video", "resolution", 0)
resolution_dropdown.select(res_id)
_apply_resolution_silent(res_id)
var fullscreen_cfg: bool = config.get_value("video", "fullscreen", false)
fullscreen_pending = fullscreen_cfg
fullscreen_check.button_pressed = fullscreen_cfg
music_slider.value = config.get_value("audio", "music", 50)
speech_slider.value = config.get_value("audio", "speech", 50)
sfx_slider.value = config.get_value("audio", "sfx", 50)
subtitles_check.button_pressed = config.get_value("gameplay", "subtitles", false)
var lang_id: int = config.get_value("gameplay", "language", 0)
language_dropdown.select(lang_id)
func save_settings() -> void:
var config := ConfigFile.new()
config.set_value("video", "resolution", resolution_dropdown.get_selected_id())
config.set_value("video", "fullscreen", fullscreen_check.button_pressed)
config.set_value("audio", "music", music_slider.value)
config.set_value("audio", "speech", speech_slider.value)
config.set_value("audio", "sfx", sfx_slider.value)
config.set_value("gameplay", "subtitles", subtitles_check.button_pressed)
config.set_value("gameplay", "language", language_dropdown.get_selected_id())
config.save("user://settings.cfg")
# -------------------------
# RESOLUTIE
# -------------------------
func _apply_resolution_silent(index: int) -> void:
var res_text := resolution_dropdown.get_item_text(index)
var parts := res_text.split("×")
if parts.size() != 2:
return
var width := int(parts[0])
var height := int(parts[1])
DisplayServer.window_set_size(Vector2i(width, height))
func _on_resolution_selected(index: int) -> void:
var res_text := resolution_dropdown.get_item_text(index)
var parts := res_text.split("×")
if parts.size() != 2:
return
pending_resolution = Vector2i(int(parts[0]), int(parts[1]))
old_resolution = DisplayServer.window_get_size()
# Forceer windowed (2-frame fix)
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
await get_tree().process_frame
DisplayServer.window_set_size(pending_resolution)
print("PREVIEW REQUEST:", pending_resolution)
await get_tree().process_frame
print("WINDOW AFTER REQUEST:", DisplayServer.window_get_size())
# Popup openen
countdown = 15
countdown_label.text = str(countdown)
resolution_popup.popup_centered()
countdown_timer.start()
# -------------------------
# COUNTDOWN / REVERT
# -------------------------
func _on_countdown_tick() -> void:
countdown -= 1
if countdown_label:
countdown_label.text = str(countdown)
if countdown <= 0:
_revert_resolution()
func _revert_resolution() -> void:
countdown_timer.stop()
resolution_popup.hide()
DisplayServer.window_set_size(old_resolution)
# Dropdown terugzetten naar oude resolutie
for i in range(resolution_dropdown.item_count):
if resolution_dropdown.get_item_text(i) == str(old_resolution.x) + "×" + str(old_resolution.y):
resolution_dropdown.select(i)
break
# -------------------------
# APPLY / CANCEL
# -------------------------
func _on_apply_pressed():
countdown_timer.stop()
resolution_popup.hide()
# resolutie opslaan
save_settings()
old_resolution = pending_resolution
# fullscreen NA apply toepassen
if fullscreen_pending:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
func _on_cancel_pressed() -> void:
_revert_resolution()
# -------------------------
# OVERIGE SIGNALS
# -------------------------
func _on_fullscreen_check_toggled(toggled_on: bool) -> void:
fullscreen_pending = toggled_on
func _on_subtitles_check_toggled(toggled_on: bool) -> void:
print("Subtitles:", toggled_on)
func _on_language_dropdown_item_selected(index: int) -> void:
print("Language set to:", language_dropdown.get_item_text(index))
func _on_music_slider_value_changed(value: float) -> void:
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Music"), linear_to_db(value / 100.0))
func _on_speech_slider_value_changed(value: float) -> void:
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Speech"), linear_to_db(value / 100.0))
func _on_sfx_slider_value_changed(value: float) -> void:
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("SFX"), linear_to_db(value / 100.0))
func _on_exit_button_pressed() -> void:
get_tree().change_scene_to_file("res://scenes/MainMenu.tscn")
func _on_save_button_pressed() -> void:
save_settings()
Some one can help me out ? Im not a script writer can understand it a bit, using Copilot to help me but it getting frustated to work with it ![]()


