@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