@tool extends BaseCreatorDialog # Dialog for creating new items # Provides input fields for all item properties signal item_data_confirmed(item_data: Dictionary) # UI elements var _item_name_edit: LineEdit var _item_key_edit: LineEdit var _short_name_edit: LineEdit var _description_edit: TextEdit var _sprite_picker: EditorResourcePicker var _sprite_preview: TextureRect var _selected_sprite: Texture2D = null var _item_type_option: OptionButton var _tier_spin: SpinBox var _price_spin: SpinBox var _amount_spin: SpinBox var _max_spin: SpinBox var _pickup_if_maxed_check: CheckBox var _consume_on_use_check: CheckBox var _selectable_check: CheckBox const ITEM_TYPE_NAMES = [ "KeycardRed", "KeycardBlue", "KeycardGreen", "Ammo", "Medkit", "FrogBomb", "Bomb", "Mine", "Battery", "Weapon", "Power", "Points", "Credits", "KeyItem" ] func _configure_window() -> void: size = settings.get("item_dialog_size") if settings else 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 _get_saved_position() -> Vector2i: if settings: var pos = settings.get("item_dialog_position") return pos if pos else Vector2i.ZERO return Vector2i.ZERO func _save_dialog_size() -> void: if settings: settings.set("item_dialog_size", size) settings.call("save_settings") func _save_dialog_position() -> void: if settings: settings.set("item_dialog_position", position) settings.call("save_settings") func _build_content(container: VBoxContainer) -> void: _build_basic_info_section(container) _build_properties_section(container) func _build_buttons(parent: VBoxContainer) -> void: var button_hbox = HBoxContainer.new() button_hbox.alignment = BoxContainer.ALIGNMENT_CENTER button_hbox.add_theme_constant_override("separation", 8) parent.add_child(button_hbox) 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) var create_button = Button.new() create_button.text = "Create" create_button.custom_minimum_size = Vector2(100, 0) create_button.pressed.connect(_on_create_pressed) button_hbox.add_child(create_button) func _build_basic_info_section(content_vbox: VBoxContainer) -> void: # Basic Info Section content_vbox.add_child(_create_section_label("Basic Information")) var name_input = _create_input("Item Name:") content_vbox.add_child(name_input["container"]) _item_name_edit = name_input["edit"] var key_input = _create_input("Item Key:") content_vbox.add_child(key_input["container"]) _item_key_edit = key_input["edit"] var short_name_input = _create_input("Short Name:") content_vbox.add_child(short_name_input["container"]) _short_name_edit = short_name_input["edit"] var desc_label = Label.new() desc_label.text = "Description:" content_vbox.add_child(desc_label) _description_edit = TextEdit.new() _description_edit.custom_minimum_size = Vector2(0, 60) _description_edit.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY content_vbox.add_child(_description_edit) content_vbox.add_child(HSeparator.new()) # Sprite Section var sprite_label = Label.new() sprite_label.text = "Inventory Sprite" sprite_label.add_theme_font_size_override("font_size", 14) content_vbox.add_child(sprite_label) var sprite_container = HBoxContainer.new() sprite_container.add_theme_constant_override("separation", 8) content_vbox.add_child(sprite_container) # Left side: Label and resource picker var left_vbox = VBoxContainer.new() left_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL left_vbox.add_theme_constant_override("separation", 4) sprite_container.add_child(left_vbox) var picker_hbox = HBoxContainer.new() picker_hbox.add_theme_constant_override("separation", 4) left_vbox.add_child(picker_hbox) var picker_label = Label.new() picker_label.text = "Sprite:" picker_label.custom_minimum_size = Vector2(120, 0) picker_hbox.add_child(picker_label) _sprite_picker = EditorResourcePicker.new() _sprite_picker.base_type = "Texture2D" _sprite_picker.editable = true _sprite_picker.size_flags_horizontal = Control.SIZE_EXPAND_FILL _sprite_picker.resource_changed.connect(_on_sprite_resource_changed) _sprite_picker.resource_selected.connect(_on_resource_picker_opening) picker_hbox.add_child(_sprite_picker) if editor_interface: _setup_sprite_picker() # Right side: Preview var preview_container = PanelContainer.new() preview_container.custom_minimum_size = Vector2(64, 64) sprite_container.add_child(preview_container) _sprite_preview = TextureRect.new() _sprite_preview.custom_minimum_size = Vector2(64, 64) _sprite_preview.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL _sprite_preview.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED preview_container.add_child(_sprite_preview) func _build_properties_section(content_vbox: VBoxContainer) -> void: content_vbox.add_child(HSeparator.new()) # Properties Section var properties_label = Label.new() properties_label.text = "Properties" properties_label.add_theme_font_size_override("font_size", 16) content_vbox.add_child(properties_label) var type_hbox = HBoxContainer.new() content_vbox.add_child(type_hbox) var type_label = Label.new() type_label.text = "Item Type:" type_label.custom_minimum_size = Vector2(120, 0) type_hbox.add_child(type_label) _item_type_option = OptionButton.new() _item_type_option.size_flags_horizontal = Control.SIZE_EXPAND_FILL for item_type in ITEM_TYPE_NAMES: _item_type_option.add_item(item_type) type_hbox.add_child(_item_type_option) var tier_spin = _create_spinbox("Tier:", 0, 0, 100, 1) content_vbox.add_child(tier_spin["container"]) _tier_spin = tier_spin["spinbox"] var price_spin = _create_spinbox("Price:", 0, 0, 999999, 1) content_vbox.add_child(price_spin["container"]) _price_spin = price_spin["spinbox"] var amount_spin = _create_spinbox("Amount:", 1, 0, 999999, 1) content_vbox.add_child(amount_spin["container"]) _amount_spin = amount_spin["spinbox"] var max_spin = _create_spinbox("Max:", 1, 0, 999999, 1) content_vbox.add_child(max_spin["container"]) _max_spin = max_spin["spinbox"] _pickup_if_maxed_check = CheckBox.new() _pickup_if_maxed_check.text = "Pickup If Maxed" content_vbox.add_child(_pickup_if_maxed_check) _consume_on_use_check = CheckBox.new() _consume_on_use_check.text = "Consume On Use" content_vbox.add_child(_consume_on_use_check) _selectable_check = CheckBox.new() _selectable_check.text = "Selectable" content_vbox.add_child(_selectable_check) func _apply_prefill_data() -> void: if prefill_data.is_empty(): return if prefill_data.has("item_name"): _item_name_edit.text = str(prefill_data["item_name"]) if prefill_data.has("item_key"): _item_key_edit.text = str(prefill_data["item_key"]) if prefill_data.has("short_name"): _short_name_edit.text = str(prefill_data["short_name"]) if prefill_data.has("description"): _description_edit.text = str(prefill_data["description"]) if prefill_data.has("sprite_resource") and prefill_data["sprite_resource"] != null: _selected_sprite = prefill_data["sprite_resource"] _sprite_preview.texture = _selected_sprite _sprite_picker.edited_resource = _selected_sprite if prefill_data.has("item_type"): _item_type_option.selected = int(prefill_data["item_type"]) if prefill_data.has("tier"): _tier_spin.value = int(prefill_data["tier"]) if prefill_data.has("price"): _price_spin.value = int(prefill_data["price"]) if prefill_data.has("amount"): _amount_spin.value = int(prefill_data["amount"]) if prefill_data.has("max"): _max_spin.value = int(prefill_data["max"]) if prefill_data.has("pickup_if_maxed"): _pickup_if_maxed_check.button_pressed = bool(prefill_data["pickup_if_maxed"]) if prefill_data.has("consume_on_use"): _consume_on_use_check.button_pressed = bool(prefill_data["consume_on_use"]) if prefill_data.has("selectable"): _selectable_check.button_pressed = bool(prefill_data["selectable"]) func _on_sprite_resource_changed(resource: Resource) -> void: if resource is Texture2D: _selected_sprite = resource _sprite_preview.texture = resource print("Sprite resource changed: ", resource.resource_path if resource.resource_path else "[Unsaved Resource]") elif resource == null: _selected_sprite = null _sprite_preview.texture = null print("Sprite resource cleared") else: push_warning("Selected resource is not a Texture2D") call_deferred("_restore_window_focus") func _on_resource_picker_opening(_resource: Resource, _inspect: bool) -> void: pass func _restore_window_focus() -> void: if visible: move_to_foreground() func _setup_sprite_picker() -> void: if _sprite_picker and editor_interface: _sprite_picker.toggle_mode = false func _on_create_pressed() -> void: var item_name = _item_name_edit.text.strip_edges() var item_key = _item_key_edit.text.strip_edges() if item_name.is_empty(): _show_error("Item Name cannot be empty") return if item_key.is_empty(): _show_error("Item Key cannot be empty") return var item_data = { "item_name": item_name, "item_key": item_key, "short_name": _short_name_edit.text.strip_edges(), "description": _description_edit.text, "sprite_resource": _selected_sprite, "item_type": _item_type_option.selected, "tier": int(_tier_spin.value), "price": int(_price_spin.value), "amount": int(_amount_spin.value), "max": int(_max_spin.value), "pickup_if_maxed": _pickup_if_maxed_check.button_pressed, "consume_on_use": _consume_on_use_check.button_pressed, "selectable": _selectable_check.button_pressed } _save_dialog_size() item_data_confirmed.emit(item_data) queue_free() func _on_cancel_pressed() -> void: _save_dialog_size() queue_free() 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 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