mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-07-01 13:41:16 +00:00
Add item creation and viewer dialogs with filtering options for 2D/3D items
This commit is contained in:
parent
670a37140f
commit
1b572e82bf
8 changed files with 1236 additions and 0 deletions
396
addons/weapon_creator/ItemCreatorDialog.gd
Normal file
396
addons/weapon_creator/ItemCreatorDialog.gd
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
@tool
|
||||
extends Window
|
||||
|
||||
# Dialog for creating new items
|
||||
# Provides input fields for all item properties
|
||||
|
||||
signal item_data_confirmed(item_data: Dictionary)
|
||||
|
||||
# Editor reference
|
||||
var editor_interface: EditorInterface
|
||||
var prefill_data: Dictionary = {}
|
||||
var _ui_built: bool = false
|
||||
|
||||
# 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 setup(editor_iface: EditorInterface, prefill: Dictionary = {}) -> void:
|
||||
editor_interface = editor_iface
|
||||
prefill_data = prefill
|
||||
|
||||
var action_text = "Duplicate" if not prefill_data.is_empty() else "Create New"
|
||||
title = action_text + " Item"
|
||||
|
||||
if _ui_built:
|
||||
if prefill_data.is_empty():
|
||||
_set_default_values()
|
||||
else:
|
||||
_apply_prefill_data()
|
||||
|
||||
func _ready() -> void:
|
||||
var action_text = "Duplicate" if not prefill_data.is_empty() else "Create New"
|
||||
title = action_text + " Item"
|
||||
size = Vector2i(750, 850)
|
||||
transient = false
|
||||
exclusive = false
|
||||
unresizable = false
|
||||
|
||||
close_requested.connect(_on_cancel_pressed)
|
||||
position = (DisplayServer.screen_get_size() - size) / 2
|
||||
|
||||
_build_ui()
|
||||
_ui_built = true
|
||||
|
||||
if prefill_data.is_empty():
|
||||
_set_default_values()
|
||||
else:
|
||||
_apply_prefill_data()
|
||||
|
||||
func _set_default_values() -> void:
|
||||
pass
|
||||
|
||||
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_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_content(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)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
item_data_confirmed.emit(item_data)
|
||||
queue_free()
|
||||
|
||||
func _on_cancel_pressed() -> void:
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue