working updates
This commit is contained in:
@@ -340,6 +340,7 @@ func show_card_detail(card: CardInstance) -> void:
|
||||
|
||||
## Hide card detail panel
|
||||
func hide_card_detail() -> void:
|
||||
print("DEBUG: GameUI.hide_card_detail() called")
|
||||
card_detail_panel.visible = false
|
||||
|
||||
## Update button states based on game phase
|
||||
|
||||
@@ -2,32 +2,146 @@ class_name HandDisplay
|
||||
extends Control
|
||||
|
||||
## HandDisplay - Shows the current player's hand in a fan layout
|
||||
## Click a card to select it and show action menu
|
||||
|
||||
signal card_selected(card_instance: CardInstance)
|
||||
signal card_action_requested(card_instance: CardInstance, action: String)
|
||||
signal card_hovered(card_instance: CardInstance)
|
||||
signal card_unhovered
|
||||
signal card_selected(card_instance: CardInstance) # Emitted when selection panel opens
|
||||
|
||||
# Hand card visuals
|
||||
var hand_cards: Array[Control] = []
|
||||
var card_instances: Array[CardInstance] = []
|
||||
|
||||
# Layout settings
|
||||
const CARD_WIDTH: float = 100.0
|
||||
const CARD_HEIGHT: float = 140.0
|
||||
const CARD_OVERLAP: float = 70.0
|
||||
const FAN_ANGLE: float = 2.0 # Degrees per card from center
|
||||
const HOVER_LIFT: float = 25.0
|
||||
# Layout settings - FF-TCG card ratio is approximately 63:88
|
||||
const CARD_WIDTH: float = 195.0 # Hand cards (triple the original 65)
|
||||
const CARD_HEIGHT: float = 273.0 # Matches ~63:88 ratio (triple the original 91)
|
||||
const CARD_OVERLAP: float = 100.0 # Increased overlap for larger cards
|
||||
const FAN_ANGLE: float = 1.0 # Degrees per card from center
|
||||
const HOVER_LIFT: float = 15.0
|
||||
|
||||
# Current hover state
|
||||
# Selected card display settings (double the original 180x252)
|
||||
const SELECTED_CARD_WIDTH: float = 405.0
|
||||
const SELECTED_CARD_HEIGHT: float = 567.0
|
||||
const MENU_WIDTH: float = 180.0
|
||||
|
||||
# Current state
|
||||
var hovered_card_index: int = -1
|
||||
var selected_card_index: int = -1
|
||||
var selected_card_panel: Panel = null
|
||||
var card_image_container: Control = null
|
||||
var action_menu: VBoxContainer = null
|
||||
|
||||
# Debug visualization (set to true to see positioning markers)
|
||||
const DEBUG_MARKERS: bool = false
|
||||
var debug_container_outline: ColorRect = null
|
||||
|
||||
func _ready() -> void:
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
# Connect to resized signal to re-layout when size changes
|
||||
clip_contents = false # Allow cards to extend beyond container bounds
|
||||
resized.connect(_on_resized)
|
||||
_create_selection_ui()
|
||||
if DEBUG_MARKERS:
|
||||
_create_debug_markers()
|
||||
|
||||
func _create_selection_ui() -> void:
|
||||
# Create the selected card display panel using HBoxContainer for reliable layout
|
||||
selected_card_panel = Panel.new()
|
||||
selected_card_panel.visible = false
|
||||
selected_card_panel.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
selected_card_panel.z_index = 200
|
||||
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.08, 0.08, 0.12, 0.95)
|
||||
style.border_color = Color(0.5, 0.4, 0.2)
|
||||
style.set_border_width_all(2)
|
||||
style.set_corner_radius_all(6)
|
||||
# Add padding via content margins
|
||||
style.content_margin_left = 15
|
||||
style.content_margin_right = 15
|
||||
style.content_margin_top = 15
|
||||
style.content_margin_bottom = 15
|
||||
selected_card_panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
add_child(selected_card_panel)
|
||||
|
||||
# Use HBoxContainer inside the panel for horizontal layout
|
||||
var hbox = HBoxContainer.new()
|
||||
hbox.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
hbox.add_theme_constant_override("separation", 20) # Gap between card and menu
|
||||
selected_card_panel.add_child(hbox)
|
||||
|
||||
# Card image container with fixed size
|
||||
card_image_container = Control.new()
|
||||
card_image_container.custom_minimum_size = Vector2(SELECTED_CARD_WIDTH, SELECTED_CARD_HEIGHT)
|
||||
card_image_container.name = "CardContainer"
|
||||
card_image_container.clip_contents = false
|
||||
hbox.add_child(card_image_container)
|
||||
|
||||
# Action menu - VBoxContainer for vertical button layout
|
||||
action_menu = VBoxContainer.new()
|
||||
action_menu.custom_minimum_size = Vector2(MENU_WIDTH, SELECTED_CARD_HEIGHT)
|
||||
action_menu.add_theme_constant_override("separation", 10)
|
||||
hbox.add_child(action_menu)
|
||||
|
||||
# Set panel size based on contents (padding + card + gap + menu + padding)
|
||||
var panel_width = 15 + SELECTED_CARD_WIDTH + 20 + MENU_WIDTH + 15
|
||||
var panel_height = 15 + SELECTED_CARD_HEIGHT + 15
|
||||
selected_card_panel.custom_minimum_size = Vector2(panel_width, panel_height)
|
||||
selected_card_panel.size = Vector2(panel_width, panel_height)
|
||||
|
||||
|
||||
func _create_debug_markers() -> void:
|
||||
# Create a visible outline around the hand container bounds
|
||||
# RED = hand container area
|
||||
debug_container_outline = ColorRect.new()
|
||||
debug_container_outline.color = Color(1, 0, 0, 0.3) # Semi-transparent red
|
||||
debug_container_outline.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
debug_container_outline.z_index = -1 # Behind cards
|
||||
add_child(debug_container_outline)
|
||||
|
||||
# GREEN line = where card bottoms should be (base_y + CARD_HEIGHT = 0 + 91 = 91)
|
||||
var card_bottom_line = ColorRect.new()
|
||||
card_bottom_line.color = Color(0, 1, 0, 0.8) # Bright green
|
||||
card_bottom_line.position = Vector2(0, CARD_HEIGHT) # y = 91
|
||||
card_bottom_line.size = Vector2(2000, 3) # Thin horizontal line
|
||||
card_bottom_line.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
card_bottom_line.z_index = 300
|
||||
add_child(card_bottom_line)
|
||||
|
||||
# BLUE line = where card tops should be (base_y = 0)
|
||||
var card_top_line = ColorRect.new()
|
||||
card_top_line.color = Color(0, 0, 1, 0.8) # Bright blue
|
||||
card_top_line.position = Vector2(0, 0)
|
||||
card_top_line.size = Vector2(2000, 3)
|
||||
card_top_line.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
card_top_line.z_index = 300
|
||||
add_child(card_top_line)
|
||||
|
||||
# Print positioning info
|
||||
call_deferred("_print_debug_info")
|
||||
|
||||
func _print_debug_info() -> void:
|
||||
var viewport = get_viewport()
|
||||
var vp_size = viewport.get_visible_rect().size if viewport else Vector2.ZERO
|
||||
print("=== HAND DISPLAY DEBUG ===")
|
||||
print("Viewport size: ", vp_size)
|
||||
print("HandDisplay global_position: ", global_position)
|
||||
print("HandDisplay size: ", size)
|
||||
print("Card base_y in container: 0")
|
||||
print("Card height: ", CARD_HEIGHT)
|
||||
print("Card global top: ", global_position.y)
|
||||
print("Card global bottom: ", global_position.y + CARD_HEIGHT)
|
||||
print("Distance from viewport bottom: ", vp_size.y - (global_position.y + CARD_HEIGHT))
|
||||
print("=== END DEBUG ===")
|
||||
|
||||
func _on_resized() -> void:
|
||||
_layout_cards()
|
||||
if DEBUG_MARKERS and debug_container_outline:
|
||||
# Update debug outline to match container size
|
||||
debug_container_outline.position = Vector2.ZERO
|
||||
debug_container_outline.size = size
|
||||
call_deferred("_print_debug_info")
|
||||
|
||||
## Update hand display with cards
|
||||
func update_hand(cards: Array) -> void:
|
||||
@@ -37,6 +151,9 @@ func update_hand(cards: Array) -> void:
|
||||
hand_cards.clear()
|
||||
card_instances.clear()
|
||||
|
||||
# Deselect any selected card
|
||||
_deselect_card()
|
||||
|
||||
# Store card instances
|
||||
for card in cards:
|
||||
if card is CardInstance:
|
||||
@@ -56,85 +173,56 @@ func _create_card_visuals() -> void:
|
||||
hand_cards.append(card_ui)
|
||||
|
||||
func _create_card_ui(card: CardInstance, index: int) -> Control:
|
||||
# Use Panel for better input handling
|
||||
var container = Panel.new()
|
||||
container.custom_minimum_size = Vector2(CARD_WIDTH, CARD_HEIGHT)
|
||||
container.size = Vector2(CARD_WIDTH, CARD_HEIGHT)
|
||||
container.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
|
||||
# Style the panel with element color
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = _get_element_color(card.card_data.get_primary_element())
|
||||
style.border_color = Color.BLACK
|
||||
style.set_border_width_all(2)
|
||||
style.bg_color = Color.TRANSPARENT
|
||||
style.border_color = Color(0.2, 0.2, 0.2)
|
||||
style.set_border_width_all(1)
|
||||
style.set_corner_radius_all(4)
|
||||
container.add_theme_stylebox_override("panel", style)
|
||||
|
||||
# Card background (keep for highlighting)
|
||||
var bg = ColorRect.new()
|
||||
bg.size = Vector2(CARD_WIDTH, CARD_HEIGHT)
|
||||
bg.color = _get_element_color(card.card_data.get_primary_element())
|
||||
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE # Let parent handle input
|
||||
container.add_child(bg)
|
||||
var texture = CardDatabase.get_card_texture(card.card_data)
|
||||
|
||||
# Card name
|
||||
var name_label = Label.new()
|
||||
name_label.text = card.card_data.name
|
||||
name_label.position = Vector2(5, 5)
|
||||
name_label.size = Vector2(CARD_WIDTH - 10, 50)
|
||||
name_label.add_theme_font_size_override("font_size", 11)
|
||||
name_label.add_theme_color_override("font_color", Color.BLACK)
|
||||
name_label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
||||
name_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(name_label)
|
||||
if texture:
|
||||
var tex_rect = TextureRect.new()
|
||||
tex_rect.texture = texture
|
||||
tex_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
tex_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
tex_rect.stretch_mode = TextureRect.STRETCH_SCALE
|
||||
tex_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(tex_rect)
|
||||
else:
|
||||
# Fallback: colored background with card info
|
||||
var bg = ColorRect.new()
|
||||
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
bg.color = _get_element_color(card.card_data.get_primary_element())
|
||||
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(bg)
|
||||
|
||||
# Cost indicator (top right)
|
||||
var cost_bg = ColorRect.new()
|
||||
cost_bg.size = Vector2(28, 28)
|
||||
cost_bg.position = Vector2(CARD_WIDTH - 32, 4)
|
||||
cost_bg.color = Color(0.2, 0.2, 0.2)
|
||||
cost_bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(cost_bg)
|
||||
var name_label = Label.new()
|
||||
name_label.text = card.card_data.name
|
||||
name_label.position = Vector2(5, 5)
|
||||
name_label.size = Vector2(CARD_WIDTH - 10, 40)
|
||||
name_label.add_theme_font_size_override("font_size", 10)
|
||||
name_label.add_theme_color_override("font_color", Color.BLACK)
|
||||
name_label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
||||
name_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(name_label)
|
||||
|
||||
var cost_label = Label.new()
|
||||
cost_label.text = str(card.card_data.cost)
|
||||
cost_label.position = Vector2(CARD_WIDTH - 32, 4)
|
||||
cost_label.size = Vector2(28, 28)
|
||||
cost_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
cost_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
cost_label.add_theme_font_size_override("font_size", 16)
|
||||
cost_label.add_theme_color_override("font_color", Color.WHITE)
|
||||
cost_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(cost_label)
|
||||
var cost_label = Label.new()
|
||||
cost_label.text = str(card.card_data.cost)
|
||||
cost_label.position = Vector2(CARD_WIDTH - 25, 5)
|
||||
cost_label.size = Vector2(20, 20)
|
||||
cost_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
cost_label.add_theme_font_size_override("font_size", 14)
|
||||
cost_label.add_theme_color_override("font_color", Color.WHITE)
|
||||
cost_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(cost_label)
|
||||
|
||||
# Type indicator (bottom left)
|
||||
var type_label = Label.new()
|
||||
type_label.text = Enums.card_type_to_string(card.card_data.type)
|
||||
type_label.position = Vector2(5, CARD_HEIGHT - 22)
|
||||
type_label.add_theme_font_size_override("font_size", 10)
|
||||
type_label.add_theme_color_override("font_color", Color.BLACK)
|
||||
type_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(type_label)
|
||||
|
||||
# Power for forwards (bottom right)
|
||||
if card.card_data.type == Enums.CardType.FORWARD:
|
||||
var power_bg = ColorRect.new()
|
||||
power_bg.size = Vector2(45, 20)
|
||||
power_bg.position = Vector2(CARD_WIDTH - 50, CARD_HEIGHT - 24)
|
||||
power_bg.color = Color(0.3, 0.1, 0.1, 0.8)
|
||||
power_bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(power_bg)
|
||||
|
||||
var power_label = Label.new()
|
||||
power_label.text = str(card.card_data.power)
|
||||
power_label.position = Vector2(CARD_WIDTH - 50, CARD_HEIGHT - 24)
|
||||
power_label.size = Vector2(45, 20)
|
||||
power_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
power_label.add_theme_font_size_override("font_size", 12)
|
||||
power_label.add_theme_color_override("font_color", Color.WHITE)
|
||||
power_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
container.add_child(power_label)
|
||||
|
||||
# Connect signals
|
||||
container.gui_input.connect(_on_card_gui_input.bind(index))
|
||||
container.mouse_entered.connect(_on_card_mouse_entered.bind(index))
|
||||
container.mouse_exited.connect(_on_card_mouse_exited.bind(index))
|
||||
@@ -143,7 +231,6 @@ func _create_card_ui(card: CardInstance, index: int) -> Control:
|
||||
|
||||
func _get_element_color(element: Enums.Element) -> Color:
|
||||
var color = Enums.get_element_color(element)
|
||||
# Lighten for card background
|
||||
return color.lightened(0.4)
|
||||
|
||||
func _layout_cards() -> void:
|
||||
@@ -151,34 +238,36 @@ func _layout_cards() -> void:
|
||||
if card_count == 0:
|
||||
return
|
||||
|
||||
# Get actual display width - use size if available, otherwise viewport
|
||||
var display_width = size.x
|
||||
|
||||
if display_width <= 0:
|
||||
var viewport = get_viewport()
|
||||
if viewport:
|
||||
display_width = viewport.get_visible_rect().size.x - 100 # Leave margins
|
||||
|
||||
display_width = viewport.get_visible_rect().size.x - 100
|
||||
if display_width <= 0:
|
||||
display_width = 1820 # Fallback
|
||||
display_width = 1820
|
||||
|
||||
# Calculate total width needed
|
||||
var total_width = CARD_WIDTH + (card_count - 1) * CARD_OVERLAP
|
||||
var start_x = (display_width - total_width) / 2.0
|
||||
|
||||
# Position each card
|
||||
# Base Y position - cards at y=0 in container, hover lifts them up (negative y)
|
||||
var base_y = 0.0
|
||||
|
||||
for i in range(card_count):
|
||||
var card_ui = hand_cards[i]
|
||||
|
||||
# X position with overlap
|
||||
var x = start_x + i * CARD_OVERLAP
|
||||
var y = base_y
|
||||
|
||||
# Y position (near top of container, with hover lift)
|
||||
var y = 10.0
|
||||
if i == hovered_card_index:
|
||||
y -= HOVER_LIFT
|
||||
# Lift hovered card slightly
|
||||
if i == hovered_card_index and selected_card_index == -1:
|
||||
y -= HOVER_LIFT # Lift by 15px
|
||||
|
||||
# Dim selected card in hand
|
||||
if i == selected_card_index:
|
||||
card_ui.modulate = Color(0.5, 0.5, 0.5, 0.7)
|
||||
else:
|
||||
card_ui.modulate = Color.WHITE
|
||||
|
||||
# Rotation based on position in fan
|
||||
var center_offset = i - (card_count - 1) / 2.0
|
||||
var angle = center_offset * FAN_ANGLE
|
||||
|
||||
@@ -192,13 +281,17 @@ func _on_card_gui_input(event: InputEvent, index: int) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
if index >= 0 and index < card_instances.size():
|
||||
card_selected.emit(card_instances[index])
|
||||
if selected_card_index == index:
|
||||
_deselect_card()
|
||||
else:
|
||||
_select_card(index)
|
||||
|
||||
func _on_card_mouse_entered(index: int) -> void:
|
||||
hovered_card_index = index
|
||||
_layout_cards()
|
||||
if index >= 0 and index < card_instances.size():
|
||||
card_hovered.emit(card_instances[index])
|
||||
# Hover signal is no longer used for GameUI preview (selection panel shows card instead)
|
||||
# Keep the signal for potential future use but don't emit it
|
||||
pass
|
||||
|
||||
func _on_card_mouse_exited(index: int) -> void:
|
||||
if hovered_card_index == index:
|
||||
@@ -206,31 +299,186 @@ func _on_card_mouse_exited(index: int) -> void:
|
||||
_layout_cards()
|
||||
card_unhovered.emit()
|
||||
|
||||
func _select_card(index: int) -> void:
|
||||
if index < 0 or index >= card_instances.size():
|
||||
return
|
||||
|
||||
selected_card_index = index
|
||||
var card = card_instances[index]
|
||||
|
||||
# Emit selection signal first (so Main.gd can hide hover preview)
|
||||
card_selected.emit(card)
|
||||
# Also emit unhovered to ensure hover state is cleared
|
||||
card_unhovered.emit()
|
||||
|
||||
# Clear previous card image from the card container
|
||||
for child in card_image_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# Clear action menu buttons
|
||||
for child in action_menu.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# Add card image to the card container
|
||||
var texture = CardDatabase.get_card_texture(card.card_data)
|
||||
if texture:
|
||||
var tex_rect = TextureRect.new()
|
||||
tex_rect.texture = texture
|
||||
tex_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
tex_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
tex_rect.stretch_mode = TextureRect.STRETCH_SCALE
|
||||
tex_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
card_image_container.add_child(tex_rect)
|
||||
else:
|
||||
# Fallback colored rect for cards without images
|
||||
var color_rect = ColorRect.new()
|
||||
color_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
color_rect.color = _get_element_color(card.card_data.get_primary_element())
|
||||
card_image_container.add_child(color_rect)
|
||||
|
||||
var name_label = Label.new()
|
||||
name_label.text = card.card_data.name
|
||||
name_label.position = Vector2(5, 10)
|
||||
name_label.size = Vector2(SELECTED_CARD_WIDTH - 10, 50)
|
||||
name_label.add_theme_font_size_override("font_size", 16)
|
||||
name_label.add_theme_color_override("font_color", Color.BLACK)
|
||||
name_label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
||||
name_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
card_image_container.add_child(name_label)
|
||||
|
||||
# Add action buttons (right side via action_menu VBoxContainer)
|
||||
_add_action_button("Play Card", "play")
|
||||
_add_action_button("Discard for CP", "discard_cp")
|
||||
_add_action_button("View Details", "view")
|
||||
_add_action_button("Cancel", "cancel")
|
||||
|
||||
# Position the panel centered above the hand
|
||||
var viewport = get_viewport()
|
||||
if viewport:
|
||||
var vp_size = viewport.get_visible_rect().size
|
||||
|
||||
# Center horizontally relative to screen
|
||||
var panel_x = (vp_size.x - selected_card_panel.size.x) / 2.0 - global_position.x
|
||||
|
||||
# Position above hand container
|
||||
var panel_y = -selected_card_panel.size.y - 20
|
||||
|
||||
# Clamp to stay on screen
|
||||
var global_y = global_position.y + panel_y
|
||||
if global_y < 90:
|
||||
panel_y = 90 - global_position.y
|
||||
|
||||
var global_x = global_position.x + panel_x
|
||||
if global_x < 10:
|
||||
panel_x = 10 - global_position.x
|
||||
if global_x + selected_card_panel.size.x > vp_size.x - 10:
|
||||
panel_x = vp_size.x - 10 - selected_card_panel.size.x - global_position.x
|
||||
|
||||
selected_card_panel.position = Vector2(panel_x, panel_y)
|
||||
|
||||
selected_card_panel.visible = true
|
||||
_layout_cards()
|
||||
|
||||
func _add_action_button(text: String, action: String) -> void:
|
||||
var button = Button.new()
|
||||
button.text = text
|
||||
button.custom_minimum_size = Vector2(MENU_WIDTH - 10, 40)
|
||||
|
||||
var style_normal = StyleBoxFlat.new()
|
||||
style_normal.bg_color = Color(0.25, 0.25, 0.3)
|
||||
style_normal.border_color = Color(0.5, 0.5, 0.6)
|
||||
style_normal.set_border_width_all(1)
|
||||
style_normal.set_corner_radius_all(5)
|
||||
style_normal.content_margin_top = 8
|
||||
style_normal.content_margin_bottom = 8
|
||||
button.add_theme_stylebox_override("normal", style_normal)
|
||||
|
||||
var style_hover = StyleBoxFlat.new()
|
||||
style_hover.bg_color = Color(0.35, 0.35, 0.45)
|
||||
style_hover.border_color = Color(0.7, 0.6, 0.3)
|
||||
style_hover.set_border_width_all(2)
|
||||
style_hover.set_corner_radius_all(5)
|
||||
style_hover.content_margin_top = 8
|
||||
style_hover.content_margin_bottom = 8
|
||||
button.add_theme_stylebox_override("hover", style_hover)
|
||||
|
||||
var style_pressed = StyleBoxFlat.new()
|
||||
style_pressed.bg_color = Color(0.2, 0.2, 0.25)
|
||||
style_pressed.border_color = Color(0.7, 0.6, 0.3)
|
||||
style_pressed.set_border_width_all(2)
|
||||
style_pressed.set_corner_radius_all(5)
|
||||
style_pressed.content_margin_top = 8
|
||||
style_pressed.content_margin_bottom = 8
|
||||
button.add_theme_stylebox_override("pressed", style_pressed)
|
||||
|
||||
button.add_theme_font_size_override("font_size", 14)
|
||||
button.pressed.connect(_on_action_pressed.bind(action))
|
||||
action_menu.add_child(button)
|
||||
|
||||
func _on_action_pressed(action: String) -> void:
|
||||
if selected_card_index < 0 or selected_card_index >= card_instances.size():
|
||||
_deselect_card()
|
||||
return
|
||||
|
||||
var card = card_instances[selected_card_index]
|
||||
|
||||
if action == "cancel":
|
||||
_deselect_card()
|
||||
else:
|
||||
card_action_requested.emit(card, action)
|
||||
if action != "view":
|
||||
_deselect_card()
|
||||
|
||||
func _deselect_card() -> void:
|
||||
selected_card_index = -1
|
||||
selected_card_panel.visible = false
|
||||
_layout_cards()
|
||||
|
||||
## Public method to deselect (called from Main when action completes)
|
||||
func deselect() -> void:
|
||||
_deselect_card()
|
||||
|
||||
## Check if a card is currently selected
|
||||
func has_selection() -> bool:
|
||||
return selected_card_index >= 0
|
||||
|
||||
## Highlight playable cards
|
||||
func highlight_playable(predicate: Callable) -> void:
|
||||
for i in range(hand_cards.size()):
|
||||
var card_ui = hand_cards[i]
|
||||
var card = card_instances[i]
|
||||
var first_child = card_ui.get_child(0) if card_ui.get_child_count() > 0 else null
|
||||
|
||||
var bg = card_ui.get_child(0) as ColorRect
|
||||
if bg:
|
||||
if first_child is TextureRect:
|
||||
if predicate.call(card):
|
||||
# Add glow effect - brighter
|
||||
bg.color = _get_element_color(card.card_data.get_primary_element()).lightened(0.2)
|
||||
first_child.modulate = Color(1.2, 1.2, 1.2)
|
||||
else:
|
||||
# Dim non-playable
|
||||
bg.color = _get_element_color(card.card_data.get_primary_element()).darkened(0.4)
|
||||
first_child.modulate = Color(0.5, 0.5, 0.5)
|
||||
elif first_child is ColorRect:
|
||||
if predicate.call(card):
|
||||
first_child.color = _get_element_color(card.card_data.get_primary_element()).lightened(0.2)
|
||||
else:
|
||||
first_child.color = _get_element_color(card.card_data.get_primary_element()).darkened(0.4)
|
||||
|
||||
## Clear all highlights
|
||||
func clear_highlights() -> void:
|
||||
for i in range(hand_cards.size()):
|
||||
var card_ui = hand_cards[i]
|
||||
var card = card_instances[i]
|
||||
var first_child = card_ui.get_child(0) if card_ui.get_child_count() > 0 else null
|
||||
|
||||
var bg = card_ui.get_child(0) as ColorRect
|
||||
if bg:
|
||||
bg.color = _get_element_color(card.card_data.get_primary_element())
|
||||
if first_child is TextureRect:
|
||||
first_child.modulate = Color.WHITE
|
||||
elif first_child is ColorRect:
|
||||
first_child.color = _get_element_color(card.card_data.get_primary_element())
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_RESIZED:
|
||||
_layout_cards()
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
# Close selection on Escape
|
||||
if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE:
|
||||
if selected_card_index >= 0:
|
||||
_deselect_card()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
Reference in New Issue
Block a user