Merge branch 'jclemente/4_4_update' of https://github.com/STEMuli-Tx/stem-city into jclemente/4_4_update
# Conflicts: # scenes/main.tscn # scripts/javascript_global.gd.uidpull/18/head
commit
f82c182e71
@ -0,0 +1,36 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://crbry5s73b6rw"
|
||||||
|
path.s3tc="res://.godot/imported/colormap.png-212e5588ca846efe35817fd63dff6086.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/colormap.png-212e5588ca846efe35817fd63dff6086.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://people/Textures/colormap.png"
|
||||||
|
dest_files=["res://.godot/imported/colormap.png-212e5588ca846efe35817fd63dff6086.s3tc.ctex", "res://.godot/imported/colormap.png-212e5588ca846efe35817fd63dff6086.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://blfrsgh3cct2l"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://cprx4wmn43sgk" path="res://scripts/structure_menu.gd" id="1_structure_menu"]
|
||||||
|
|
||||||
|
[node name="StructureMenu" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 0
|
||||||
|
offset_right = 300.0
|
||||||
|
offset_bottom = 600.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_structure_menu")
|
||||||
|
|
||||||
|
[node name="MenuPanel" type="Panel" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="MenuPanel"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
horizontal_scroll_mode = 0
|
||||||
|
|
||||||
|
[node name="ItemsContainer" type="HBoxContainer" parent="MenuPanel/ScrollContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
|
[node name="ToggleButton" type="Button" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 1
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_right = 40.0
|
||||||
|
offset_bottom = 40.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
text = ">"
|
||||||
@ -1 +1 @@
|
|||||||
uid://g0rf3gsjgld
|
uid://boq8j7e7veaup
|
||||||
|
|||||||
@ -0,0 +1,314 @@
|
|||||||
|
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)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cprx4wmn43sgk
|
||||||
@ -0,0 +1,175 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
# Reference to the builder node
|
||||||
|
@export var builder: Node3D
|
||||||
|
|
||||||
|
# Menu properties
|
||||||
|
@export var menu_width: float = 300.0
|
||||||
|
@export var menu_speed: float = 0.3
|
||||||
|
|
||||||
|
# Menu state
|
||||||
|
var is_open: bool = false
|
||||||
|
var selected_index: int = -1
|
||||||
|
|
||||||
|
# References to UI elements
|
||||||
|
@onready var toggle_button = $ToggleButton
|
||||||
|
@onready var menu_panel = $MenuPanel
|
||||||
|
@onready var items_container = $MenuPanel/ScrollContainer/ItemsContainer
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
# Initialize menu state
|
||||||
|
menu_panel.position.x = -menu_width
|
||||||
|
menu_panel.size.x = menu_width
|
||||||
|
|
||||||
|
# Connect toggle button
|
||||||
|
toggle_button.pressed.connect(_on_toggle_button_pressed)
|
||||||
|
|
||||||
|
# Initial population
|
||||||
|
populate_menu()
|
||||||
|
|
||||||
|
# Connect to mission manager for updates
|
||||||
|
var mission_manager = get_node_or_null("/root/Main/MissionManager")
|
||||||
|
if mission_manager:
|
||||||
|
mission_manager.mission_started.connect(_on_mission_started)
|
||||||
|
mission_manager.mission_completed.connect(_on_mission_completed)
|
||||||
|
|
||||||
|
func _on_toggle_button_pressed():
|
||||||
|
is_open = !is_open
|
||||||
|
|
||||||
|
# Animate menu
|
||||||
|
var tween = create_tween()
|
||||||
|
tween.tween_property(menu_panel, "position:x", 0.0 if is_open else -menu_width, menu_speed)
|
||||||
|
|
||||||
|
# Update toggle button text
|
||||||
|
toggle_button.text = "◀" if is_open else "▶"
|
||||||
|
|
||||||
|
func populate_menu():
|
||||||
|
# Clear existing items
|
||||||
|
for child in items_container.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
# Add unlocked structures
|
||||||
|
for i in range(builder.structures.size()):
|
||||||
|
var structure = builder.structures[i]
|
||||||
|
if "unlocked" in structure and structure.unlocked:
|
||||||
|
create_structure_item(structure, i)
|
||||||
|
|
||||||
|
func create_structure_item(structure, index):
|
||||||
|
var item = PanelContainer.new()
|
||||||
|
item.custom_minimum_size = Vector2(menu_width - 20, 100)
|
||||||
|
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
|
||||||
|
|
||||||
|
var hbox = HBoxContainer.new()
|
||||||
|
hbox.custom_minimum_size = Vector2(menu_width - 20, 100)
|
||||||
|
item.add_child(hbox)
|
||||||
|
|
||||||
|
# Thumbnail
|
||||||
|
var thumbnail = TextureRect.new()
|
||||||
|
thumbnail.custom_minimum_size = Vector2(80, 80)
|
||||||
|
thumbnail.expand_mode = TextureRect.EXPAND_FILL_WIDTH
|
||||||
|
thumbnail.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||||
|
|
||||||
|
# Try to load thumbnail
|
||||||
|
if "thumbnail" in structure and structure.thumbnail:
|
||||||
|
var texture = load(structure.thumbnail)
|
||||||
|
if texture:
|
||||||
|
thumbnail.texture = texture
|
||||||
|
else:
|
||||||
|
# Try to get thumbnail from model path
|
||||||
|
var model_path = structure.model.resource_path
|
||||||
|
var colormap_path = model_path.get_basename() + "_colormap.png"
|
||||||
|
if ResourceLoader.exists(colormap_path):
|
||||||
|
thumbnail.texture = load(colormap_path)
|
||||||
|
|
||||||
|
hbox.add_child(thumbnail)
|
||||||
|
|
||||||
|
# Info container
|
||||||
|
var info = VBoxContainer.new()
|
||||||
|
info.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
hbox.add_child(info)
|
||||||
|
|
||||||
|
# Structure name
|
||||||
|
var name_label = Label.new()
|
||||||
|
if "title" in structure and structure.title:
|
||||||
|
name_label.text = structure.title
|
||||||
|
else:
|
||||||
|
name_label.text = get_structure_name(structure)
|
||||||
|
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))
|
||||||
|
info.add_child(name_label)
|
||||||
|
|
||||||
|
# Structure cost
|
||||||
|
var cost_label = Label.new()
|
||||||
|
cost_label.text = "Cost: $" + str(structure.price)
|
||||||
|
cost_label.add_theme_color_override("font_color", Color(0.2, 0.8, 0.2))
|
||||||
|
info.add_child(cost_label)
|
||||||
|
|
||||||
|
# Structure description
|
||||||
|
var desc = Label.new()
|
||||||
|
if "description" in structure and structure.description:
|
||||||
|
desc.text = structure.description
|
||||||
|
else:
|
||||||
|
desc.text = "A structure for your city!"
|
||||||
|
desc.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||||
|
info.add_child(desc)
|
||||||
|
|
||||||
|
# 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 == MouseButton.LEFT:
|
||||||
|
select_structure(index)
|
||||||
|
|
||||||
|
func select_structure(index):
|
||||||
|
if index >= 0 and index < builder.structures.size():
|
||||||
|
builder.index = index
|
||||||
|
builder.update_structure()
|
||||||
|
|
||||||
|
# Update selection highlight
|
||||||
|
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
|
||||||
|
if i/2 == index: # Divide by 2 because of separators
|
||||||
|
style.border_color = Color(0.9, 0.9, 0.2)
|
||||||
|
else:
|
||||||
|
style.border_color = Color(0.3, 0.3, 0.3)
|
||||||
|
|
||||||
|
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.substr(1) + " "
|
||||||
|
|
||||||
|
return title.strip_edges()
|
||||||
|
|
||||||
|
func _on_mission_started(mission):
|
||||||
|
# Update menu when a new mission starts
|
||||||
|
populate_menu()
|
||||||
|
|
||||||
|
func _on_mission_completed(mission):
|
||||||
|
# Update menu when a mission is completed (new structures may be unlocked)
|
||||||
|
populate_menu()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://0nf5shqoqhn8
|
||||||
Loading…
Reference in New Issue