198 lines
6.4 KiB
GDScript
198 lines
6.4 KiB
GDScript
extends MenuButton
|
|
class_name MenuItemGenerator
|
|
|
|
# Export a filter type property that uses the Structure.StructureType enum
|
|
@export var filter_type: Structure.StructureType
|
|
# Private variable to store loaded structures
|
|
var _structures = []
|
|
# Icons for locked/unlocked status (set these in _ready)
|
|
var _lock_icon: Texture2D
|
|
var _unlock_icon: Texture2D
|
|
|
|
func _ready():
|
|
# Connect the signal for item selection
|
|
get_popup().id_pressed.connect(_on_item_selected)
|
|
|
|
# Add to group for easy refreshing of all structure menus
|
|
add_to_group("structure_menus")
|
|
|
|
EventBus.structure_unlocked.connect(_on_structure_unlock)
|
|
|
|
|
|
# Load icons (you'll need to create or find these icons)
|
|
_lock_icon = load("res://sprites/sticky_builder_icons/lock.png") if ResourceLoader.exists("res://sprites/sticky_builder_icons/lock.png") else null
|
|
if(_lock_icon):
|
|
_lock_icon = _get_scaled_icon(_lock_icon,32)
|
|
# Load all structures and populate the menu
|
|
_load_structures()
|
|
_populate_menu()
|
|
|
|
# Load all structure resources from the structures directory
|
|
func _load_structures():
|
|
_structures.clear()
|
|
|
|
var dir = DirAccess.open("res://structures")
|
|
if not dir:
|
|
push_error("Failed to access the structures directory")
|
|
return
|
|
|
|
dir.list_dir_begin()
|
|
var file_name = dir.get_next()
|
|
|
|
while file_name != "":
|
|
if not dir.current_is_dir() and file_name.ends_with(".tres"):
|
|
var structure = load("res://structures/" + file_name)
|
|
|
|
# Only add structures that match our filter type
|
|
if structure is Structure and structure.type == filter_type:
|
|
_structures.append(structure)
|
|
|
|
file_name = dir.get_next()
|
|
|
|
# Sort structures by size category first (small to large), then by title
|
|
_structures.sort_custom(func(a, b):
|
|
# First compare by size category
|
|
if a.size_category != b.size_category:
|
|
return a.size_category < b.size_category
|
|
# If same size category, sort by title
|
|
return a.title < b.title)
|
|
|
|
# Populate the menu with the loaded structures
|
|
func _populate_menu():
|
|
var popup = get_popup()
|
|
popup.clear()
|
|
|
|
var current_size_category = -1
|
|
var menu_item_to_structure_index = {} # Map menu item IDs to structure indices
|
|
var current_item_id = 0
|
|
|
|
for i in range(_structures.size()):
|
|
var structure = _structures[i]
|
|
# Add separator between size categories
|
|
if structure.size_category != current_size_category:
|
|
if i > 0:
|
|
popup.add_separator()
|
|
current_item_id += 1
|
|
current_size_category = structure.size_category
|
|
|
|
# Add size category header (optional)
|
|
#var category_name = ""
|
|
#match current_size_category:
|
|
#Structure.SizeCategory.SMALL: category_name = "Small"
|
|
#Structure.SizeCategory.MEDIUM: category_name = "Medium"
|
|
#Structure.SizeCategory.LARGE: category_name = "Large"
|
|
#
|
|
#if category_name != "":
|
|
#popup.add_item(category_name, -1)
|
|
#popup.set_item_disabled(popup.item_count - 1, true)
|
|
|
|
# Create the item text with structure info
|
|
var item_text = structure.title
|
|
|
|
# Create info section for price, population, and energy
|
|
var info_parts = []
|
|
|
|
# Add price if available
|
|
if structure.price > 0:
|
|
info_parts.append("$" + str(structure.price))
|
|
|
|
# Add population count
|
|
if structure.population_count > 0:
|
|
info_parts.append("+" + str(structure.population_count) + " pop")
|
|
|
|
# Add energy usage and production
|
|
if structure.kW_usage > 0:
|
|
info_parts.append("-" + str(structure.kW_usage) + " kW")
|
|
if structure.kW_production > 0:
|
|
info_parts.append("+" + str(structure.kW_production) + " kW")
|
|
# Add the info parts to the item text
|
|
if info_parts.size() > 0:
|
|
item_text += " (" + " | ".join(info_parts) + ")"
|
|
|
|
# Add lock/unlock icon if we're showing all structures
|
|
if not structure.unlocked:
|
|
if _lock_icon:
|
|
popup.add_icon_item(_lock_icon, item_text)
|
|
popup.set_item_disabled(current_item_id, true)
|
|
menu_item_to_structure_index[current_item_id] = i
|
|
current_item_id += 1
|
|
else:
|
|
var icon = load(structure.icon) if ResourceLoader.exists(structure.icon) else null
|
|
popup.add_icon_item(icon, item_text)
|
|
menu_item_to_structure_index[current_item_id] = i
|
|
current_item_id += 1
|
|
|
|
# Store the mapping for use in _on_item_selected
|
|
set_meta("menu_item_to_structure_index", menu_item_to_structure_index)
|
|
|
|
# Handle the menu item selection
|
|
func _on_item_selected(id: int):
|
|
var menu_item_to_structure_index = get_meta("menu_item_to_structure_index", {})
|
|
if id in menu_item_to_structure_index:
|
|
var structure_index = menu_item_to_structure_index[id]
|
|
var selected_structure = _structures[structure_index]
|
|
Globals.set_structure(selected_structure)
|
|
# Consume the input event to prevent it from reaching the game
|
|
get_viewport().set_input_as_handled()
|
|
|
|
# Method to manually refresh the menu items
|
|
func refresh():
|
|
_load_structures()
|
|
_populate_menu()
|
|
|
|
# Method to unlock a structure by resource path and refresh the menu
|
|
func unlock_structure(resource_path: String):
|
|
var structure = load(resource_path)
|
|
if structure is Structure and not structure.unlocked:
|
|
structure.unlocked = true
|
|
structure.resource_changed.emit()
|
|
|
|
# Save the resource
|
|
ResourceSaver.save(structure, resource_path)
|
|
|
|
# Refresh the menu
|
|
refresh()
|
|
|
|
return true
|
|
|
|
return false
|
|
|
|
func _get_scaled_icon(texture: Texture2D, target_height: int) -> Texture2D:
|
|
if texture == null:
|
|
return null
|
|
|
|
var img = texture.get_image()
|
|
var scale = target_height / float(img.get_height())
|
|
var new_width = int(img.get_width() * scale)
|
|
|
|
img.resize(new_width, target_height, Image.INTERPOLATE_LANCZOS)
|
|
|
|
var new_texture = ImageTexture.create_from_image(img)
|
|
return new_texture
|
|
|
|
# Override _gui_input to ensure we're handling all input
|
|
func _gui_input(event: InputEvent) -> void:
|
|
# When menu is open, accept all input to prevent it from reaching the game
|
|
if get_popup().visible:
|
|
get_viewport().set_input_as_handled()
|
|
|
|
# Override _input to catch all input events
|
|
func _input(event: InputEvent) -> void:
|
|
if get_popup().visible and (event is InputEventMouseButton or event is InputEventMouseMotion):
|
|
# When menu is visible, accept all mouse input to prevent it from reaching the game
|
|
get_viewport().set_input_as_handled()
|
|
|
|
# If it's a mouse button press, mark it as handled
|
|
if event is InputEventMouseButton:
|
|
event.pressed = false
|
|
|
|
# Override _unhandled_input to catch any remaining input events
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if get_popup().visible:
|
|
get_viewport().set_input_as_handled()
|
|
if event is InputEventMouseButton:
|
|
event.pressed = false
|
|
|
|
func _on_structure_unlock(structure:Structure)->void:
|
|
refresh()
|