updates for cleaning functionality
This commit is contained in:
264
scripts/ui/ActionLog.gd
Normal file
264
scripts/ui/ActionLog.gd
Normal file
@@ -0,0 +1,264 @@
|
||||
class_name ActionLog
|
||||
extends Control
|
||||
|
||||
## ActionLog - Collapsible panel showing game actions
|
||||
|
||||
signal undo_requested
|
||||
|
||||
# UI Components
|
||||
var panel: PanelContainer
|
||||
var toggle_button: Button
|
||||
var scroll_container: ScrollContainer
|
||||
var log_container: VBoxContainer
|
||||
var undo_button: Button
|
||||
var clear_button: Button
|
||||
|
||||
# State
|
||||
var is_expanded: bool = true
|
||||
var action_entries: Array[Control] = []
|
||||
|
||||
# Layout constants
|
||||
const COLLAPSED_WIDTH: float = 40.0
|
||||
const EXPANDED_WIDTH: float = 280.0
|
||||
const PANEL_HEIGHT: float = 400.0
|
||||
|
||||
func _ready() -> void:
|
||||
_create_ui()
|
||||
_connect_signals()
|
||||
|
||||
func _create_ui() -> void:
|
||||
# Set up this control to anchor to right side
|
||||
set_anchors_preset(Control.PRESET_CENTER_RIGHT)
|
||||
custom_minimum_size = Vector2(EXPANDED_WIDTH, PANEL_HEIGHT)
|
||||
size = Vector2(EXPANDED_WIDTH, PANEL_HEIGHT)
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
# Main horizontal container
|
||||
var hbox = HBoxContainer.new()
|
||||
add_child(hbox)
|
||||
hbox.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
hbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
hbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
hbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
# Toggle button on the left edge
|
||||
toggle_button = Button.new()
|
||||
toggle_button.text = ">"
|
||||
toggle_button.custom_minimum_size = Vector2(30, 0)
|
||||
toggle_button.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
toggle_button.tooltip_text = "Toggle Action Log (L)"
|
||||
hbox.add_child(toggle_button)
|
||||
|
||||
# Panel container for the log
|
||||
panel = PanelContainer.new()
|
||||
hbox.add_child(panel)
|
||||
panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.08, 0.08, 0.12, 0.95)
|
||||
style.border_color = Color(0.3, 0.3, 0.4)
|
||||
style.set_border_width_all(2)
|
||||
style.set_corner_radius_all(5)
|
||||
style.set_content_margin_all(8)
|
||||
panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
# Panel content
|
||||
var panel_vbox = VBoxContainer.new()
|
||||
panel.add_child(panel_vbox)
|
||||
panel_vbox.add_theme_constant_override("separation", 5)
|
||||
|
||||
# Header
|
||||
var header = HBoxContainer.new()
|
||||
panel_vbox.add_child(header)
|
||||
header.add_theme_constant_override("separation", 5)
|
||||
|
||||
var title = Label.new()
|
||||
title.text = "Action Log"
|
||||
title.add_theme_font_size_override("font_size", 14)
|
||||
title.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
header.add_child(title)
|
||||
|
||||
# Undo button
|
||||
undo_button = Button.new()
|
||||
undo_button.text = "Undo"
|
||||
undo_button.custom_minimum_size = Vector2(50, 25)
|
||||
undo_button.add_theme_font_size_override("font_size", 11)
|
||||
undo_button.tooltip_text = "Undo last action (Ctrl+Z)"
|
||||
undo_button.disabled = true
|
||||
header.add_child(undo_button)
|
||||
|
||||
# Clear button
|
||||
clear_button = Button.new()
|
||||
clear_button.text = "Clear"
|
||||
clear_button.custom_minimum_size = Vector2(45, 25)
|
||||
clear_button.add_theme_font_size_override("font_size", 11)
|
||||
header.add_child(clear_button)
|
||||
|
||||
# Separator
|
||||
var separator = HSeparator.new()
|
||||
panel_vbox.add_child(separator)
|
||||
|
||||
# Scroll container for log entries
|
||||
scroll_container = ScrollContainer.new()
|
||||
panel_vbox.add_child(scroll_container)
|
||||
scroll_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
scroll_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
scroll_container.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
||||
scroll_container.custom_minimum_size = Vector2(200, 250)
|
||||
|
||||
# Log entries container
|
||||
log_container = VBoxContainer.new()
|
||||
scroll_container.add_child(log_container)
|
||||
log_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
log_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
log_container.add_theme_constant_override("separation", 3)
|
||||
|
||||
func _connect_signals() -> void:
|
||||
toggle_button.pressed.connect(_on_toggle_pressed)
|
||||
undo_button.pressed.connect(_on_undo_pressed)
|
||||
clear_button.pressed.connect(clear_log)
|
||||
|
||||
# Defer GameManager connections to ensure it's ready
|
||||
call_deferred("_connect_game_manager_signals")
|
||||
|
||||
func _connect_game_manager_signals() -> void:
|
||||
# Connect to GameManager signals
|
||||
if GameManager:
|
||||
if not GameManager.message.is_connected(_on_game_message):
|
||||
GameManager.message.connect(_on_game_message)
|
||||
if not GameManager.card_played.is_connected(_on_card_played):
|
||||
GameManager.card_played.connect(_on_card_played)
|
||||
if not GameManager.turn_changed.is_connected(_on_turn_changed):
|
||||
GameManager.turn_changed.connect(_on_turn_changed)
|
||||
if not GameManager.phase_changed.is_connected(_on_phase_changed):
|
||||
GameManager.phase_changed.connect(_on_phase_changed)
|
||||
if not GameManager.damage_dealt.is_connected(_on_damage_dealt):
|
||||
GameManager.damage_dealt.connect(_on_damage_dealt)
|
||||
if not GameManager.action_undone.is_connected(_on_action_undone):
|
||||
GameManager.action_undone.connect(_on_action_undone)
|
||||
|
||||
func _on_toggle_pressed() -> void:
|
||||
toggle_panel()
|
||||
|
||||
func toggle_panel() -> void:
|
||||
is_expanded = not is_expanded
|
||||
panel.visible = is_expanded
|
||||
toggle_button.text = ">" if is_expanded else "<"
|
||||
|
||||
if is_expanded:
|
||||
custom_minimum_size.x = EXPANDED_WIDTH
|
||||
size.x = EXPANDED_WIDTH
|
||||
else:
|
||||
custom_minimum_size.x = COLLAPSED_WIDTH
|
||||
size.x = COLLAPSED_WIDTH
|
||||
|
||||
func _on_undo_pressed() -> void:
|
||||
undo_requested.emit()
|
||||
|
||||
## Add a log entry with a specific type for styling
|
||||
func add_entry(text: String, entry_type: String = "info") -> void:
|
||||
if not log_container:
|
||||
return
|
||||
|
||||
var entry = _create_entry(text, entry_type)
|
||||
log_container.add_child(entry)
|
||||
action_entries.append(entry)
|
||||
|
||||
# Keep log at reasonable size
|
||||
while action_entries.size() > 100:
|
||||
var old_entry = action_entries.pop_front()
|
||||
old_entry.queue_free()
|
||||
|
||||
# Scroll to bottom after adding
|
||||
call_deferred("_scroll_to_bottom")
|
||||
|
||||
func _create_entry(text: String, entry_type: String) -> Control:
|
||||
var entry_panel = PanelContainer.new()
|
||||
|
||||
var style = StyleBoxFlat.new()
|
||||
style.set_content_margin_all(4)
|
||||
style.set_corner_radius_all(3)
|
||||
|
||||
# Color based on type
|
||||
match entry_type:
|
||||
"turn":
|
||||
style.bg_color = Color(0.2, 0.3, 0.4, 0.8)
|
||||
"phase":
|
||||
style.bg_color = Color(0.15, 0.25, 0.35, 0.6)
|
||||
"action":
|
||||
style.bg_color = Color(0.2, 0.2, 0.3, 0.7)
|
||||
"damage":
|
||||
style.bg_color = Color(0.4, 0.15, 0.15, 0.7)
|
||||
"card":
|
||||
style.bg_color = Color(0.15, 0.3, 0.2, 0.7)
|
||||
_:
|
||||
style.bg_color = Color(0.12, 0.12, 0.18, 0.5)
|
||||
|
||||
entry_panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
var label = Label.new()
|
||||
label.text = text
|
||||
label.add_theme_font_size_override("font_size", 11)
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
||||
label.custom_minimum_size.x = 200
|
||||
entry_panel.add_child(label)
|
||||
|
||||
return entry_panel
|
||||
|
||||
func _scroll_to_bottom() -> void:
|
||||
await get_tree().process_frame
|
||||
scroll_container.scroll_vertical = int(scroll_container.get_v_scroll_bar().max_value)
|
||||
|
||||
func clear_log() -> void:
|
||||
for entry in action_entries:
|
||||
entry.queue_free()
|
||||
action_entries.clear()
|
||||
|
||||
## Enable or disable undo button
|
||||
func set_undo_available(available: bool) -> void:
|
||||
undo_button.disabled = not available
|
||||
|
||||
## Manually add a message (can be called from Main.gd if signal connection fails)
|
||||
func log_message(text: String) -> void:
|
||||
_on_game_message(text)
|
||||
|
||||
## Manually log a turn change
|
||||
func log_turn_change(player_name: String, turn_number: int) -> void:
|
||||
_on_turn_changed(player_name, turn_number)
|
||||
|
||||
## Manually log a phase change
|
||||
func log_phase_change(phase_name: String) -> void:
|
||||
_on_phase_changed(phase_name)
|
||||
|
||||
## Signal handlers
|
||||
func _on_game_message(text: String) -> void:
|
||||
# Determine entry type based on message content
|
||||
var entry_type = "info"
|
||||
if "attacks" in text or "blocks" in text:
|
||||
entry_type = "action"
|
||||
elif "damage" in text or "broken" in text:
|
||||
entry_type = "damage"
|
||||
elif "Played" in text or "Discarded" in text or "Dulled" in text:
|
||||
entry_type = "card"
|
||||
|
||||
add_entry(text, entry_type)
|
||||
|
||||
func _on_card_played(_card_data: Dictionary) -> void:
|
||||
# Already handled by message signal
|
||||
pass
|
||||
|
||||
func _on_turn_changed(player_name: String, turn_number: int) -> void:
|
||||
add_entry("=== " + player_name + " - Turn " + str(turn_number) + " ===", "turn")
|
||||
|
||||
func _on_phase_changed(phase_name: String) -> void:
|
||||
add_entry(phase_name, "phase")
|
||||
|
||||
func _on_damage_dealt(_player_name: String, _amount: int) -> void:
|
||||
# Already handled by message signal
|
||||
pass
|
||||
|
||||
func _on_action_undone(action_name: String) -> void:
|
||||
add_entry("UNDO: " + action_name, "action")
|
||||
|
||||
# Input is handled by Main.gd to avoid duplicate handling
|
||||
@@ -126,17 +126,29 @@ func _create_ui() -> void:
|
||||
end_phase_button.custom_minimum_size = Vector2(100, 40)
|
||||
action_buttons.add_child(end_phase_button)
|
||||
|
||||
# === MESSAGE PANEL (center, above hand) ===
|
||||
# === MESSAGE PANEL (upper center of screen, below top bar) ===
|
||||
# Use a container to properly center the message
|
||||
var message_container = Control.new()
|
||||
root.add_child(message_container)
|
||||
message_container.set_anchors_preset(Control.PRESET_TOP_WIDE)
|
||||
message_container.offset_top = 90
|
||||
message_container.offset_bottom = 160
|
||||
message_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
var message_center = CenterContainer.new()
|
||||
message_container.add_child(message_center)
|
||||
message_center.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
message_center.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
message_panel = _create_panel()
|
||||
root.add_child(message_panel)
|
||||
message_panel.set_anchors_preset(Control.PRESET_CENTER)
|
||||
message_panel.position = Vector2(-100, 200)
|
||||
message_panel.custom_minimum_size = Vector2(200, 40)
|
||||
message_center.add_child(message_panel)
|
||||
message_panel.custom_minimum_size = Vector2(350, 50)
|
||||
|
||||
message_label = Label.new()
|
||||
message_label.text = ""
|
||||
message_label.add_theme_font_size_override("font_size", 16)
|
||||
message_label.add_theme_font_size_override("font_size", 20)
|
||||
message_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
message_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
message_panel.add_child(message_label)
|
||||
message_panel.visible = false
|
||||
|
||||
|
||||
@@ -191,9 +191,7 @@ func _layout_cards() -> void:
|
||||
func _on_card_gui_input(event: InputEvent, index: int) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
print("HandDisplay: Card clicked, index=", index)
|
||||
if index >= 0 and index < card_instances.size():
|
||||
print("HandDisplay: Emitting card_selected for ", card_instances[index].card_data.name)
|
||||
card_selected.emit(card_instances[index])
|
||||
|
||||
func _on_card_mouse_entered(index: int) -> void:
|
||||
|
||||
Reference in New Issue
Block a user