315 lines
11 KiB
GDScript
315 lines
11 KiB
GDScript
extends Control
|
|
|
|
@export var builder: Node3D
|
|
@export var base_menu_width: float = 300.0 # Base width for the menu
|
|
@export var item_width: float = 280.0 # Width of each item
|
|
@export var item_spacing: float = 20.0 # Spacing between items
|
|
@export var menu_speed: float = 0.3
|
|
@export var visible_menu_width: float = 600.0 # The visible width of the menu panel
|
|
@export var item_height: float = 180.0
|
|
@export var menu_vertical_offset: float = 40.0
|
|
|
|
var is_open: bool = false
|
|
var selected_index: int = -1
|
|
var menu_width: float = base_menu_width # Will be updated based on items
|
|
|
|
@onready var toggle_button = $ToggleButton
|
|
@onready var menu_panel = $MenuPanel
|
|
@onready var items_container = $MenuPanel/ScrollContainer/ItemsContainer
|
|
|
|
func _ready():
|
|
# Ensure we have a valid builder reference
|
|
if not builder:
|
|
builder = get_node_or_null("/root/Main/Builder")
|
|
if not builder:
|
|
push_error("StructureMenu: Builder node not found!")
|
|
return
|
|
|
|
# Initialize menu panel position and size
|
|
menu_panel.size.x = base_menu_width
|
|
menu_panel.position.x = -menu_panel.size.x # Start closed
|
|
|
|
# Vertically center the toggle button on the menu panel
|
|
toggle_button.anchor_top = 0.5
|
|
toggle_button.anchor_bottom = 0.5
|
|
toggle_button.offset_top = -toggle_button.size.y / 2
|
|
toggle_button.offset_bottom = toggle_button.size.y / 2
|
|
|
|
# Place toggle button at the left edge of the menu
|
|
toggle_button.position.x = 0
|
|
toggle_button.text = "▶"
|
|
|
|
# Connect signals
|
|
toggle_button.pressed.connect(_on_toggle_button_pressed)
|
|
|
|
# Connect to builder's structure update signal if it exists
|
|
if "structure_updated" in builder:
|
|
print("Connecting to builder's structure_updated signal") # Debug print
|
|
builder.structure_updated.connect(_on_builder_structure_updated)
|
|
|
|
# Wait a frame to ensure all nodes are ready
|
|
await get_tree().process_frame
|
|
_center_toggle_button()
|
|
|
|
# Populate the menu
|
|
populate_menu()
|
|
|
|
# Print debug info
|
|
print("StructureMenu: Builder found: ", builder != null)
|
|
print("StructureMenu: Structures array size: ", builder.structures.size() if builder and "structures" in builder else 0)
|
|
|
|
# Initialize selection if builder has a current index
|
|
if builder and "index" in builder:
|
|
selected_index = builder.index
|
|
update_selection_highlight()
|
|
|
|
func _center_toggle_button():
|
|
# Vertically center the toggle button on the menu panel
|
|
var menu_height = menu_panel.size.y
|
|
var button_height = toggle_button.size.y
|
|
toggle_button.position.y = (menu_height - button_height) / 2
|
|
# Horizontally: always at 0 when closed, at menu_panel.size.x when open
|
|
toggle_button.position.x = menu_panel.size.x if is_open else 0
|
|
|
|
func _on_toggle_button_pressed():
|
|
is_open = !is_open
|
|
var tween = create_tween()
|
|
tween.tween_property(menu_panel, "position:x", 0.0 if is_open else -menu_panel.size.x, menu_speed)
|
|
tween.parallel().tween_property(toggle_button, "position:x", menu_panel.size.x if is_open else 0.0, menu_speed)
|
|
toggle_button.text = "◀" if is_open else "▶"
|
|
_center_toggle_button()
|
|
|
|
func _on_builder_structure_updated(index):
|
|
print("Builder structure updated signal received. Index: ", index) # Debug print
|
|
# Update the selected index and highlight
|
|
selected_index = index
|
|
update_selection_highlight()
|
|
|
|
func populate_menu():
|
|
if not builder or not "structures" in builder:
|
|
push_error("StructureMenu: Builder or structures array not found!")
|
|
return
|
|
|
|
# Clear existing items
|
|
for child in items_container.get_children():
|
|
child.queue_free()
|
|
|
|
# Count unlocked structures
|
|
var unlocked_count = 0
|
|
for structure in builder.structures:
|
|
if "unlocked" in structure and structure.unlocked:
|
|
unlocked_count += 1
|
|
|
|
# Calculate menu width and height using the user's formula
|
|
var padding = item_spacing
|
|
menu_width = (unlocked_count * item_width) + ((unlocked_count + 1) * padding)
|
|
var menu_height = item_height + 2 * padding
|
|
|
|
# Center the menu panel horizontally and set its size using anchors and offsets
|
|
menu_panel.anchor_left = 0.5
|
|
menu_panel.anchor_right = 0.5
|
|
menu_panel.offset_left = -menu_width / 2
|
|
menu_panel.offset_right = menu_width / 2
|
|
menu_panel.anchor_top = 0.0
|
|
menu_panel.anchor_bottom = 0.0
|
|
menu_panel.offset_top = 0
|
|
menu_panel.offset_bottom = menu_height
|
|
$MenuPanel/ScrollContainer.size.x = menu_width
|
|
$MenuPanel/ScrollContainer.size.y = menu_height
|
|
$MenuPanel/ScrollContainer.position.y = 0
|
|
$MenuPanel/ScrollContainer.clip_contents = true
|
|
|
|
# If menu is closed, keep it offscreen
|
|
if not is_open:
|
|
menu_panel.position.x = -menu_width
|
|
_center_toggle_button()
|
|
|
|
# Create a MarginContainer for all-side padding
|
|
var margin = MarginContainer.new()
|
|
margin.add_theme_constant_override("margin_left", padding)
|
|
margin.add_theme_constant_override("margin_right", padding)
|
|
margin.add_theme_constant_override("margin_top", padding)
|
|
margin.add_theme_constant_override("margin_bottom", padding)
|
|
margin.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
margin.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
items_container.add_child(margin)
|
|
margin.position.y = menu_vertical_offset
|
|
|
|
# Create a CenterContainer to center the row both horizontally and vertically
|
|
var center = CenterContainer.new()
|
|
center.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
center.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
margin.add_child(center)
|
|
|
|
# Create a horizontal container for all items
|
|
var row = HBoxContainer.new()
|
|
row.add_theme_constant_override("separation", padding)
|
|
# DO NOT set row.size_flags_horizontal so it doesn't expand
|
|
center.add_child(row)
|
|
|
|
# Add all unlocked structures to the row
|
|
for i in range(builder.structures.size()):
|
|
var structure = builder.structures[i]
|
|
if "unlocked" in structure and structure.unlocked:
|
|
var item = create_structure_item(structure, i)
|
|
row.add_child(item)
|
|
|
|
# Update selection highlight after populating
|
|
update_selection_highlight()
|
|
|
|
func create_structure_item(structure, index):
|
|
var item = PanelContainer.new()
|
|
item.custom_minimum_size = Vector2(item_width, item_height)
|
|
item.size_flags_horizontal = 0 # Prevent horizontal expansion
|
|
item.add_theme_stylebox_override("panel", StyleBoxFlat.new())
|
|
|
|
var style = item.get_theme_stylebox("panel") as StyleBoxFlat
|
|
style.bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
|
style.border_width_left = 2
|
|
style.border_width_top = 2
|
|
style.border_width_right = 2
|
|
style.border_width_bottom = 2
|
|
style.border_color = Color(0.3, 0.3, 0.3)
|
|
style.corner_radius_top_left = 5
|
|
style.corner_radius_top_right = 5
|
|
style.corner_radius_bottom_left = 5
|
|
style.corner_radius_bottom_right = 5
|
|
|
|
# Store the structure index in the item for reference
|
|
item.set_meta("structure_index", index)
|
|
|
|
# Main container for vertical layout
|
|
var vbox = VBoxContainer.new()
|
|
vbox.custom_minimum_size = Vector2(item_width, item_height)
|
|
vbox.size_flags_horizontal = 0 # Prevent horizontal expansion
|
|
vbox.add_theme_constant_override("separation", item_spacing)
|
|
item.add_child(vbox)
|
|
|
|
# Thumbnail container
|
|
var thumbnail_container = CenterContainer.new()
|
|
thumbnail_container.custom_minimum_size = Vector2(128, 128)
|
|
thumbnail_container.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
|
vbox.add_child(thumbnail_container)
|
|
|
|
# Thumbnail
|
|
var thumbnail = TextureRect.new()
|
|
thumbnail.custom_minimum_size = Vector2(128, 128)
|
|
thumbnail.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
|
thumbnail.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
|
thumbnail.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
|
|
# Try to load thumbnail
|
|
if "thumbnail" in structure and structure.thumbnail != null:
|
|
var texture = load(structure.thumbnail)
|
|
if texture != null:
|
|
# Scale the texture to 128x128
|
|
var image = texture.get_image()
|
|
image.resize(128, 128)
|
|
var scaled_texture = ImageTexture.create_from_image(image)
|
|
thumbnail.texture = scaled_texture
|
|
print("Structure ", index, " thumbnail loaded: ", structure.thumbnail)
|
|
print("Texture size: ", scaled_texture.get_size())
|
|
print("Thumbnail size: ", thumbnail.size)
|
|
print("Thumbnail container size: ", thumbnail_container.size)
|
|
|
|
thumbnail_container.add_child(thumbnail)
|
|
|
|
# Debug print after adding to container
|
|
print("After adding to container:")
|
|
print("Thumbnail size: ", thumbnail.size)
|
|
print("Thumbnail container size: ", thumbnail_container.size)
|
|
print("Thumbnail custom_minimum_size: ", thumbnail.custom_minimum_size)
|
|
print("Container custom_minimum_size: ", thumbnail_container.custom_minimum_size)
|
|
|
|
# Info container
|
|
var info = VBoxContainer.new()
|
|
info.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
info.add_theme_constant_override("separation", 5)
|
|
vbox.add_child(info)
|
|
|
|
# Structure name
|
|
var name_label = Label.new()
|
|
if "title" in structure and structure.title != null:
|
|
name_label.text = structure.title
|
|
else:
|
|
name_label.text = "Structure " + str(index)
|
|
name_label.add_theme_font_size_override("font_size", 18)
|
|
name_label.add_theme_color_override("font_color", Color(0.9, 0.9, 0.2))
|
|
name_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
info.add_child(name_label)
|
|
|
|
# Structure cost
|
|
var cost_label = Label.new()
|
|
if "price" in structure:
|
|
cost_label.text = "Cost: $" + str(structure.price)
|
|
else:
|
|
cost_label.text = "Cost: $0"
|
|
cost_label.add_theme_color_override("font_color", Color(0.2, 0.8, 0.2))
|
|
cost_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
info.add_child(cost_label)
|
|
|
|
# Connect click handler
|
|
item.gui_input.connect(func(event): _on_item_gui_input(event, index))
|
|
|
|
# Add to container
|
|
items_container.add_child(item)
|
|
|
|
# Add separator if not last item
|
|
if index < builder.structures.size() - 1:
|
|
var sep = HSeparator.new()
|
|
items_container.add_child(sep)
|
|
|
|
func _on_item_gui_input(event, index):
|
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
|
select_structure(index)
|
|
|
|
func select_structure(index):
|
|
if not builder or not "structures" in builder:
|
|
return
|
|
|
|
if index >= 0 and index < builder.structures.size():
|
|
print("Selecting structure index: ", index) # Debug print
|
|
# Update builder's selected structure
|
|
builder.index = index
|
|
if "update_structure" in builder:
|
|
builder.update_structure()
|
|
|
|
# Update our selected index
|
|
selected_index = index
|
|
|
|
# Update visual feedback
|
|
update_selection_highlight()
|
|
|
|
func update_selection_highlight():
|
|
print("Updating selection highlight. Selected index: ", selected_index) # Debug print
|
|
# Update selection highlight for all items
|
|
for i in range(items_container.get_child_count()):
|
|
var child = items_container.get_child(i)
|
|
if child is PanelContainer:
|
|
var style = child.get_theme_stylebox("panel") as StyleBoxFlat
|
|
var item_index = child.get_meta("structure_index")
|
|
if item_index == selected_index:
|
|
print("Highlighting item: ", item_index) # Debug print
|
|
# Selected item
|
|
style.border_color = Color(0.9, 0.9, 0.2) # Yellow border
|
|
style.bg_color = Color(0.3, 0.3, 0.3, 0.8) # Slightly lighter background
|
|
else:
|
|
# Unselected item
|
|
style.border_color = Color(0.3, 0.3, 0.3)
|
|
style.bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
|
|
|
func get_structure_name(structure):
|
|
var file_name = structure.model.resource_path.get_file().get_basename()
|
|
var names = file_name.split("-")
|
|
var title = ""
|
|
|
|
for part in names:
|
|
if part.length() > 0:
|
|
title += part[0].to_upper() + part.substring(1) + " "
|
|
|
|
return title.strip_edges()
|
|
|
|
func is_mouse_over_menu() -> bool:
|
|
var mouse_pos = get_viewport().get_mouse_position()
|
|
return menu_panel.get_global_rect().has_point(mouse_pos) or toggle_button.get_global_rect().has_point(mouse_pos)
|