cirnogodot/addons/weapon_creator/BaseCreatorDialog.gd

207 lines
5.7 KiB
GDScript

@tool
class_name BaseCreatorDialog
extends Window
# Base class for all creator dialogs
# Ensures consistent initialization and UI building patterns
const WeaponCreatorSettings = preload("res://addons/weapon_creator/WeaponCreatorSettings.gd")
const SETTINGS_PATH = "user://weapon_creator_settings.tres"
signal data_confirmed(data: Dictionary)
var editor_interface: EditorInterface
var prefill_data: Dictionary = {}
var _ui_built: bool = false
var settings: Resource
# Base setup - override _custom_setup() in derived classes for additional initialization
func setup(editor_iface: EditorInterface, prefill: Dictionary = {}) -> void:
editor_interface = editor_iface
prefill_data = prefill
if ResourceLoader.exists(SETTINGS_PATH):
settings = ResourceLoader.load(SETTINGS_PATH)
if not settings:
settings = WeaponCreatorSettings.new()
_custom_setup()
_update_title()
if _ui_built:
_apply_data()
# Override this in derived classes for custom initialization
func _custom_setup() -> void:
pass
func _ready() -> void:
if not settings:
if ResourceLoader.exists(SETTINGS_PATH):
settings = ResourceLoader.load(SETTINGS_PATH)
if not settings:
settings = WeaponCreatorSettings.new()
_configure_window()
_update_title()
close_requested.connect(_on_window_close_requested)
_build_ui()
_ui_built = true
_apply_data()
# Restore position after UI is built, or center if no saved position
_restore_or_center_position()
func _restore_or_center_position() -> void:
var saved_pos = _get_saved_position()
if saved_pos != Vector2i.ZERO:
position = saved_pos
else:
# Use popup_centered_clamped to properly center on the current screen
popup_centered_clamped(size, 0.75)
func _get_saved_position() -> Vector2i:
# Override in derived classes to return their specific saved position
return Vector2i.ZERO
func _on_window_close_requested() -> void:
_save_dialog_size_and_position()
_on_cancel_pressed()
func _save_dialog_size_and_position() -> void:
_save_dialog_size()
_save_dialog_position()
func _save_dialog_size() -> void:
# Override in derived classes to save their specific dialog size
pass
func _save_dialog_position() -> void:
# Override in derived classes to save their specific dialog position
pass
func _configure_window() -> void:
size = Vector2i(750, 850)
transient = false
exclusive = false
unresizable = false
func _update_title() -> void:
var action_text = "Duplicate" if not prefill_data.is_empty() else "Create New"
title = action_text + " Item"
func _build_ui() -> void:
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)
var vbox = VBoxContainer.new()
vbox.add_theme_constant_override("separation", 8)
margin.add_child(vbox)
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 content_vbox = VBoxContainer.new()
content_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
content_vbox.add_theme_constant_override("separation", 12)
scroll.add_child(content_vbox)
_build_content(content_vbox)
vbox.add_child(HSeparator.new())
_build_buttons(vbox)
func _build_content(container: VBoxContainer) -> void:
push_warning("_build_content should be overridden in derived class")
func _build_buttons(vbox: VBoxContainer) -> void:
var button_hbox = HBoxContainer.new()
button_hbox.alignment = BoxContainer.ALIGNMENT_END
button_hbox.add_theme_constant_override("separation", 8)
vbox.add_child(button_hbox)
var cancel_button = Button.new()
cancel_button.text = "Cancel"
cancel_button.pressed.connect(_on_cancel_pressed)
button_hbox.add_child(cancel_button)
var create_button = Button.new()
create_button.text = "Create"
create_button.pressed.connect(_on_create_pressed)
button_hbox.add_child(create_button)
func _apply_data() -> void:
if prefill_data.is_empty():
_set_default_values()
else:
_apply_prefill_data()
func _set_default_values() -> void:
pass
func _apply_prefill_data() -> void:
pass
func _on_cancel_pressed() -> void:
queue_free()
func _on_create_pressed() -> void:
push_warning("_on_create_pressed should be overridden in derived class")
func _show_error(message: String) -> void:
var dialog = AcceptDialog.new()
dialog.dialog_text = message
dialog.title = "Error"
add_child(dialog)
dialog.popup_centered()
dialog.confirmed.connect(func(): dialog.queue_free())
# Helper methods for creating common UI elements
func _create_input(label_text: String) -> Dictionary:
var hbox = HBoxContainer.new()
var label = Label.new()
label.text = label_text
label.custom_minimum_size = Vector2(120, 0)
hbox.add_child(label)
var edit = LineEdit.new()
edit.size_flags_horizontal = Control.SIZE_EXPAND_FILL
hbox.add_child(edit)
return {"container": hbox, "edit": edit}
func _create_spinbox(label_text: String, default_value: float, min_value: float, max_value: float, step: float) -> Dictionary:
var hbox = HBoxContainer.new()
var label = Label.new()
label.text = label_text
label.custom_minimum_size = Vector2(120, 0)
hbox.add_child(label)
var spinbox = SpinBox.new()
spinbox.min_value = min_value
spinbox.max_value = max_value
spinbox.step = step
spinbox.value = default_value
spinbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
hbox.add_child(spinbox)
return {"container": hbox, "spinbox": spinbox}
func _create_section_label(text: String) -> Label:
var label = Label.new()
label.text = text
label.add_theme_font_size_override("font_size", 16)
return label