Refactor creator dialogs to use centralized settings management and improve UI state handling

This commit is contained in:
MaddoScientisto 2026-02-08 20:33:52 +01:00
commit 99281deef4
12 changed files with 510 additions and 242 deletions

View file

@ -1,5 +1,5 @@
@tool
extends Window
extends BaseCreatorDialog
# Popup window for configuring weapon parameters before creation
# Displays all input fields and creation/cancel buttons
@ -17,7 +17,6 @@ var description_field: TextEdit
var sprite_resource: Texture2D
var sprite_picker: EditorResourcePicker
var sprite_preview: TextureRect
var editor_interface: EditorInterface
# Bullet selection fields
var bullet_dropdown: OptionButton
@ -36,109 +35,78 @@ var bullets_per_shot_field: SpinBox
var spread_angle_field: SpinBox
var random_spread_field: SpinBox
# Buttons
var create_button: Button
var cancel_button: Button
# Mode and prefill data
# Mode
var is_3d_mode: bool = true
var prefill_data: Dictionary = {}
var _ui_built: bool = false
var _setup_called: bool = false
func setup(editor_iface: EditorInterface, is_3d: bool = true, prefill: Dictionary = {}) -> void:
editor_interface = editor_iface
# Public method with custom signature - calls base setup internally
func setup_weapon(editor_iface: EditorInterface, is_3d: bool = true, prefill: Dictionary = {}) -> void:
is_3d_mode = is_3d
prefill_data = prefill
# Update title based on mode and prefill status
var mode_text = "3D" if is_3d_mode else "2D"
var action_text = "Duplicate" if not prefill_data.is_empty() else "Create New"
title = action_text + " Weapon (" + mode_text + ")"
_setup_called = true
# Call parent setup with standard signature
setup(editor_iface, prefill)
# If sprite picker already exists, ensure it has editor context
if sprite_picker:
_setup_sprite_picker()
# If UI is already built (setup called after _ready), apply prefill data now
if _ui_built:
if prefill_data.is_empty():
_set_default_values()
else:
_apply_prefill_data()
func _custom_setup() -> void:
# Called by parent setup() - use for any additional initialization
pass
func _ready() -> void:
# Window configuration
var mode_text = "3D" if is_3d_mode else "2D"
var action_text = "Duplicate" if not prefill_data.is_empty() else "Create New"
title = action_text + " Weapon (" + mode_text + ")"
size = Vector2i(750, 950)
# Wait for setup to be called if it hasn't been yet
if not _setup_called:
await get_tree().process_frame
super._ready()
func _configure_window() -> void:
size = settings.get("weapon_dialog_size") if settings else Vector2i(750, 950)
transient = false
exclusive = false
unresizable = false
# Connect close request (X button) to cancel action
close_requested.connect(_on_cancel_pressed)
# Center on screen
position = (DisplayServer.screen_get_size() - size) / 2
_build_ui()
_ui_built = true
# Apply prefill data if provided, otherwise use defaults
# Note: this might be overridden by setup() if called via call_deferred
if prefill_data.is_empty():
_set_default_values()
else:
_apply_prefill_data()
func _build_ui() -> void:
# Main margin container
var margin = MarginContainer.new()
margin.set_anchors_preset(Control.PRESET_FULL_RECT)
margin.add_theme_constant_override("margin_left", 12)
margin.add_theme_constant_override("margin_top", 12)
margin.add_theme_constant_override("margin_right", 12)
margin.add_theme_constant_override("margin_bottom", 12)
add_child(margin)
# Main vbox
var vbox = VBoxContainer.new()
vbox.add_theme_constant_override("separation", 8)
margin.add_child(vbox)
# Scroll container for form
var scroll = ScrollContainer.new()
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
vbox.add_child(scroll)
var main_vbox = VBoxContainer.new()
main_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
main_vbox.add_theme_constant_override("separation", 12)
scroll.add_child(main_vbox)
func _update_title() -> void:
var mode_text = "3D" if is_3d_mode else "2D"
var action_text = "Duplicate" if not prefill_data.is_empty() else "Create New"
title = action_text + " Weapon (" + mode_text + ")"
func _get_saved_position() -> Vector2i:
if settings:
var pos = settings.get("weapon_dialog_position")
return pos if pos else Vector2i.ZERO
return Vector2i.ZERO
func _save_dialog_size() -> void:
if settings:
settings.set("weapon_dialog_size", size)
settings.call("save_settings")
func _save_dialog_position() -> void:
if settings:
settings.set("weapon_dialog_position", position)
settings.call("save_settings")
func _build_content(container: VBoxContainer) -> void:
# Basic Info Section
_build_basic_info_section(main_vbox)
_build_basic_info_section(container)
# Stats Section
_build_stats_section(main_vbox)
vbox.add_child(HSeparator.new())
# Buttons at bottom
_build_stats_section(container)
func _build_buttons(vbox: VBoxContainer) -> void:
var button_hbox = HBoxContainer.new()
button_hbox.alignment = BoxContainer.ALIGNMENT_CENTER
button_hbox.add_theme_constant_override("separation", 8)
vbox.add_child(button_hbox)
cancel_button = Button.new()
var cancel_button = Button.new()
cancel_button.text = "Cancel"
cancel_button.custom_minimum_size = Vector2(100, 0)
cancel_button.pressed.connect(_on_cancel_pressed)
button_hbox.add_child(cancel_button)
create_button = Button.new()
var create_button = Button.new()
create_button.text = "Create Weapon"
create_button.custom_minimum_size = Vector2(150, 0)
create_button.pressed.connect(_on_create_pressed)
@ -369,7 +337,7 @@ func _set_default_values() -> void:
description_field.text = "A new weapon for testing"
# Select default bullet based on mode
var default_bullet = "res://Resources/Bullets/3D/icicle_repeater_bullets_3D.tres" if is_3d_mode else "res://Resources/Bullets/simple_ice_bullet.tres"
var default_bullet = settings.get("default_bullet_3d") if is_3d_mode else settings.get("default_bullet_2d")
_select_bullet_by_path(default_bullet)
# Weapon stats defaults
@ -387,9 +355,7 @@ func _set_default_values() -> void:
func _populate_bullet_dropdown() -> void:
# Get all bullet resources from the appropriate Bullets folder
var bullets_dir = "res://Resources/Bullets/"
if is_3d_mode:
bullets_dir += "3D/"
var bullets_dir = settings.get("bullets_3d_dir") if is_3d_mode else settings.get("bullets_dir")
var dir = DirAccess.open(bullets_dir)
@ -470,6 +436,9 @@ func _on_create_pressed() -> void:
"random_spread": random_spread_field.value
}
# Save dialog size
_save_dialog_size()
# Emit signal with weapon data
weapon_data_confirmed.emit(weapon_data)
@ -478,6 +447,8 @@ func _on_create_pressed() -> void:
queue_free()
func _on_cancel_pressed() -> void:
# Save dialog size before closing
_save_dialog_size()
# Close without creating
hide()
queue_free()
@ -500,8 +471,8 @@ func _validate_inputs() -> bool:
# Check if resources already exist
var dimension_suffix = "_3D" if is_3d_mode else "_2D"
var weapon_resource_path: String = "res://Resources/Weapons/" + key + dimension_suffix + ".tres"
var item_resource_path: String = "res://Resources/Items/" + key + "_Item" + dimension_suffix + ".tres"
var weapon_resource_path: String = settings.get("weapons_dir") + key + dimension_suffix + ".tres"
var item_resource_path: String = settings.get("items_dir") + key + "_Item" + dimension_suffix + ".tres"
if ResourceLoader.exists(weapon_resource_path):
_show_error("Weapon resource already exists at:\n" + weapon_resource_path + "\n\nPlease choose a different item key.")