cirnogodot/addons/weapon_creator/WeaponViewer.gd

179 lines
5.9 KiB
GDScript3
Raw Normal View History

@tool
extends PanelContainer
# Displays all weapons from the ItemsDatabase in a grid format
# Shows sprite and name, with tooltip showing resource path
# Clicking opens the weapon resource in the inspector
signal weapon_selected(weapon_resource_path: String)
var _editor_interface: EditorInterface
var _grid_container: HFlowContainer
var _items_database_path := "res://Resources/ItemsDatabase.tres"
func setup(editor_interface: EditorInterface) -> void:
_editor_interface = editor_interface
func _ready() -> void:
_build_ui()
refresh_weapons()
func _build_ui() -> void:
# Main margin container
var margin = MarginContainer.new()
margin.add_theme_constant_override("margin_left", 8)
margin.add_theme_constant_override("margin_top", 8)
margin.add_theme_constant_override("margin_right", 8)
margin.add_theme_constant_override("margin_bottom", 8)
add_child(margin)
# Main vbox
var vbox = VBoxContainer.new()
vbox.add_theme_constant_override("separation", 8)
margin.add_child(vbox)
# Header with title and refresh button
var header_hbox = HBoxContainer.new()
vbox.add_child(header_hbox)
var title = Label.new()
title.text = "Weapons"
title.size_flags_horizontal = Control.SIZE_EXPAND_FILL
header_hbox.add_child(title)
var refresh_button = Button.new()
refresh_button.text = "Refresh"
refresh_button.pressed.connect(refresh_weapons)
header_hbox.add_child(refresh_button)
vbox.add_child(HSeparator.new())
# Scroll container for grid
var scroll = ScrollContainer.new()
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
vbox.add_child(scroll)
# Flow container for responsive wrapping
_grid_container = HFlowContainer.new()
_grid_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_grid_container.add_theme_constant_override("h_separation", 8)
_grid_container.add_theme_constant_override("v_separation", 8)
scroll.add_child(_grid_container)
func refresh_weapons() -> void:
if not _grid_container:
return
# Clear existing items
for child in _grid_container.get_children():
child.queue_free()
# Load ItemsDatabase
if not ResourceLoader.exists(_items_database_path):
_add_error_label("ItemsDatabase not found at: " + _items_database_path)
return
var items_database = load(_items_database_path)
if items_database == null:
_add_error_label("Failed to load ItemsDatabase")
return
var loot_items = items_database.get("LootItems")
if loot_items == null:
_add_error_label("No LootItems found in database")
return
# Filter for weapons only (items with WeaponData3D)
var weapon_count = 0
for loot_item in loot_items:
var weapon_data = loot_item.get("WeaponData3D")
if weapon_data != null:
_create_weapon_tile(loot_item, weapon_data)
weapon_count += 1
if weapon_count == 0:
_add_error_label("No weapons found in database")
func _create_weapon_tile(loot_item: Resource, weapon_data: Resource) -> void:
var button = Button.new()
button.custom_minimum_size = Vector2(100, 110)
button.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
button.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
var vbox = VBoxContainer.new()
vbox.add_theme_constant_override("separation", 2)
vbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
var sprite: Texture2D = loot_item.get("InventorySprite")
var texture_rect = TextureRect.new()
texture_rect.custom_minimum_size = Vector2(64, 64)
texture_rect.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
texture_rect.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
texture_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
if sprite:
texture_rect.texture = sprite
vbox.add_child(texture_rect)
else:
var placeholder_label = Label.new()
placeholder_label.text = "No Icon"
placeholder_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
placeholder_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
placeholder_label.custom_minimum_size = Vector2(64, 64)
placeholder_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
placeholder_label.add_theme_font_size_override("font_size", 10)
vbox.add_child(placeholder_label)
var name_label = Label.new()
var item_name: String = loot_item.get("ItemName")
name_label.text = item_name if item_name else "Unknown"
name_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
name_label.vertical_alignment = VERTICAL_ALIGNMENT_TOP
name_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
name_label.custom_minimum_size = Vector2(90, 0)
name_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
name_label.clip_text = true
name_label.max_lines_visible = 2
name_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
name_label.add_theme_font_size_override("font_size", 11)
name_label.add_theme_constant_override("line_spacing", -2)
vbox.add_child(name_label)
button.add_child(vbox)
vbox.set_anchors_preset(Control.PRESET_FULL_RECT)
vbox.add_theme_constant_override("margin_left", 4)
vbox.add_theme_constant_override("margin_top", 4)
vbox.add_theme_constant_override("margin_right", 4)
vbox.add_theme_constant_override("margin_bottom", 4)
var weapon_path = weapon_data.resource_path
if weapon_path:
button.tooltip_text = weapon_path
else:
button.tooltip_text = "Built-in resource (no file path)"
button.pressed.connect(_on_weapon_clicked.bind(weapon_data, weapon_path))
_grid_container.add_child(button)
func _on_weapon_clicked(weapon_data: Resource, weapon_path: String) -> void:
if not _editor_interface:
push_error("Editor interface not available")
return
# Select the weapon resource in the inspector
if weapon_data:
_editor_interface.edit_resource(weapon_data)
_editor_interface.get_inspector().set_current_tab(0)
weapon_selected.emit(weapon_path)
func _add_error_label(error_message: String) -> void:
var label = Label.new()
label.text = error_message
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.modulate = Color.ORANGE_RED
_grid_container.add_child(label)