extends Node # UIManager - Handles all UI setup and updates const item_tex = [ preload("res://assets/textures/player_board_and_blue_print/tile_null.tres"), preload("res://assets/textures/player_board_and_blue_print/tile_heart.tres"), preload("res://assets/textures/player_board_and_blue_print/tile_diamond.tres"), preload("res://assets/textures/player_board_and_blue_print/tile_star.tres"), preload("res://assets/textures/player_board_and_blue_print/tile_coin.tres") ] # Node references - will be set by Main var action_menu var move_button var grab_button var put_button var randomize_button var arrange_button var playerboard_ui var local_player_character enum ActionState { NONE, MOVING, GRABBING, PUTTING, RANDOMIZING, ARRANGING, PLACING_OBSTACLE } var current_action_state = ActionState.NONE func initialize(main_node): # Get node references from main scene action_menu = main_node.get_node("ActionMenu") move_button = main_node.get_node("ActionMenu/ActionButtonContainer/MoveButton") grab_button = main_node.get_node("ActionMenu/ActionButtonContainer/GrabButton") put_button = main_node.get_node("ActionMenu/ActionButtonContainer/PutButton") randomize_button = main_node.get_node("ActionMenu/ActionButtonContainer/RandomizeButton") arrange_button = main_node.get_node("ActionMenu/ActionButtonContainer/ArrangeButton") playerboard_ui = main_node.get_node("PlayerboardUI") func setup_action_buttons(action_state_callback): move_button.pressed.connect(func(): action_state_callback.call(ActionState.MOVING)) grab_button.pressed.connect(func(): action_state_callback.call(ActionState.GRABBING)) put_button.pressed.connect(func(): if local_player_character: local_player_character.auto_put_item() ) randomize_button.pressed.connect(func(): action_state_callback.call(ActionState.RANDOMIZING)) arrange_button.pressed.connect(func(): if local_player_character and local_player_character.action_points >= 2: action_state_callback.call(ActionState.ARRANGING) ) func setup_playerboard_ui(): for child in playerboard_ui.get_children(): child.queue_free() playerboard_ui.columns = 5 for i in range(25): var slot = TextureRect.new() var highlight_rect = TextureRect.new() var hr_tex = load("res://assets/models/pboard/HighlightRect.tres") var select_rect = TextureRect.new() var sr_tex = load("res://assets/models/pboard/SelectRect.tres") var adjacent_rect = TextureRect.new() var ar_tex = load("res://assets/models/pboard/AdjacentRect.tres") slot.custom_minimum_size = Vector2(36, 36) slot.texture = item_tex[0] playerboard_ui.add_child(slot, true) highlight_rect.texture = hr_tex highlight_rect.size = Vector2(36, 36) select_rect.texture = sr_tex select_rect.size = Vector2(36, 36) adjacent_rect.texture = ar_tex adjacent_rect.size = Vector2(36, 36) slot.add_child(highlight_rect) slot.add_child(select_rect) slot.add_child(adjacent_rect) slot.get_child(0).hide() slot.get_child(1).hide() slot.get_child(2).hide() func update_playerboard_ui(): if not local_player_character: return for i in range(25): var slot = playerboard_ui.get_child(i) # Safety check: Ensure playerboard has enough items if i >= local_player_character.playerboard.size(): continue var item = local_player_character.playerboard[i] slot.texture = item_tex[0] match item: 7: slot.texture = item_tex[1] 8: slot.texture = item_tex[2] 9: slot.texture = item_tex[3] 10: slot.texture = item_tex[4] func update_button_states(): if not local_player_character or local_player_character.is_in_group("Bots"): move_button.visible = false grab_button.visible = false put_button.visible = false randomize_button.visible = false arrange_button.visible = false return move_button.visible = true grab_button.visible = true put_button.visible = true randomize_button.visible = true arrange_button.visible = true move_button.disabled = false grab_button.disabled = false put_button.disabled = false arrange_button.disabled = false func set_local_player(player): local_player_character = player # Connect to powerup signals var powerup_manager = player.get_node_or_null("PowerUpManager") if powerup_manager: powerup_manager.points_changed.connect(_on_powerup_points_changed) # ============================================================================= # Power-Up Bar UI (Battery Style) # ============================================================================= var powerup_bar: HBoxContainer var powerup_segments: Array = [] func setup_powerup_bar_ui(main_node): """Create battery-style power-up bar with 4 segments.""" var parent = main_node.get_node_or_null("PlayerboardUI") if not parent: parent = main_node # Create container powerup_bar = HBoxContainer.new() powerup_bar.name = "PowerUpBar" powerup_bar.custom_minimum_size = Vector2(200, 30) # Position above playerboard powerup_bar.position = Vector2(0, -40) # Create label var label = Label.new() label.text = "POWER: " label.add_theme_font_size_override("font_size", 14) powerup_bar.add_child(label) # Create 4 battery segments powerup_segments.clear() for i in range(4): var segment = Panel.new() segment.custom_minimum_size = Vector2(40, 24) segment.name = "Segment" + str(i) # Style the segment var style = StyleBoxFlat.new() style.bg_color = Color(0.2, 0.2, 0.2, 0.8) # Dark empty style.border_color = Color(0.4, 0.8, 0.4, 1.0) # Green border style.set_border_width_all(2) style.corner_radius_top_left = 4 if i == 0 else 0 style.corner_radius_bottom_left = 4 if i == 0 else 0 style.corner_radius_top_right = 4 if i == 3 else 0 style.corner_radius_bottom_right = 4 if i == 3 else 0 segment.add_theme_stylebox_override("panel", style) powerup_bar.add_child(segment) powerup_segments.append(segment) parent.add_child(powerup_bar) func update_powerup_bar(current_points: int, max_points: int): """Update battery segments based on current power-up points.""" var bars_filled = current_points / 4 # 4 points per bar for i in range(powerup_segments.size()): var segment = powerup_segments[i] var style = segment.get_theme_stylebox("panel").duplicate() if i < bars_filled: # Filled segment - bright green style.bg_color = Color(0.3, 0.9, 0.3, 1.0) else: # Empty segment - dark style.bg_color = Color(0.2, 0.2, 0.2, 0.8) segment.add_theme_stylebox_override("panel", style) func _on_powerup_points_changed(current: int, max_points: int): update_powerup_bar(current, max_points) # ============================================================================= # Leaderboard UI # ============================================================================= var leaderboard_panel: PanelContainer func setup_leaderboard_ui(main_node): """Create leaderboard panel on right side of screen.""" leaderboard_panel = PanelContainer.new() leaderboard_panel.name = "LeaderboardPanel" leaderboard_panel.custom_minimum_size = Vector2(180, 180) # Position on right side leaderboard_panel.set_anchors_preset(Control.PRESET_TOP_RIGHT) leaderboard_panel.position = Vector2(-200, 100) # Style the panel var style = StyleBoxFlat.new() style.bg_color = Color(0.1, 0.1, 0.1, 0.85) style.border_color = Color(0.8, 0.7, 0.2, 1.0) # Gold border style.set_border_width_all(2) style.corner_radius_top_left = 8 style.corner_radius_top_right = 8 style.corner_radius_bottom_left = 8 style.corner_radius_bottom_right = 8 leaderboard_panel.add_theme_stylebox_override("panel", style) var vbox = VBoxContainer.new() vbox.name = "VBox" # Title var title = Label.new() title.text = "LEADERBOARD" title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER title.add_theme_font_size_override("font_size", 16) title.add_theme_color_override("font_color", Color(0.9, 0.8, 0.2)) vbox.add_child(title) # Separator var sep = HSeparator.new() vbox.add_child(sep) # Create 4 player entries for i in range(4): var entry = HBoxContainer.new() entry.name = "Entry" + str(i + 1) entry.visible = false var rank_label = Label.new() rank_label.name = "RankLabel" rank_label.custom_minimum_size = Vector2(40, 0) rank_label.text = _get_rank_text(i + 1) rank_label.add_theme_font_size_override("font_size", 14) entry.add_child(rank_label) var name_label = Label.new() name_label.name = "NameLabel" name_label.custom_minimum_size = Vector2(80, 0) name_label.clip_text = true name_label.text = "---" name_label.add_theme_font_size_override("font_size", 14) entry.add_child(name_label) var score_label = Label.new() score_label.name = "ScoreLabel" score_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT score_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL score_label.text = "0" score_label.add_theme_font_size_override("font_size", 14) score_label.add_theme_color_override("font_color", Color(0.8, 1.0, 0.8)) entry.add_child(score_label) vbox.add_child(entry) leaderboard_panel.add_child(vbox) main_node.add_child(leaderboard_panel) func _get_rank_text(rank: int) -> String: match rank: 1: return "1st" 2: return "2nd" 3: return "3rd" 4: return "4th" _: return str(rank) + "th" # ============================================================================= # Timer Labels for Goal Panels # ============================================================================= func setup_timer_labels(main_node): """Add timer labels to each player goals panel.""" var all_player_goals = main_node.get_node_or_null("AllPlayerGoals") if not all_player_goals: return for i in range(all_player_goals.get_child_count()): var panel = all_player_goals.get_child(i) # Skip if timer already exists if panel.get_node_or_null("TimerLabel"): continue var timer_label = Label.new() timer_label.name = "TimerLabel" timer_label.text = "01:00" timer_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER timer_label.add_theme_font_size_override("font_size", 18) timer_label.add_theme_color_override("font_color", Color(1.0, 0.9, 0.3)) # Add at the top of the panel var margin = panel.get_node_or_null("MarginContainer") if margin: margin.add_child(timer_label) margin.move_child(timer_label, 0) else: panel.add_child(timer_label)