ChessBuilder/Systems/CardDisplay.gd

172 lines
6.4 KiB
GDScript

class_name CardDisplay extends Control
# Base card dimensions
const BASE_CARD_WIDTH = 150
const BASE_CARD_HEIGHT = 250
const CARD_MARGIN = 10
const MAX_HAND_WIDTH_RATIO = 0.7 # Maximum portion of screen width to use for hand
var cardDisplays = [] # Array of {panel: Node, card: Card}
var selectedCard = null
var container: HBoxContainer
var cardPreviewScene = preload("res://card_preview_panel.tscn")
var currently_hovered_card = null
# Preview card panel instance for hovering
var hoveredPreview: CardPreviewPanel = null
var isPreviewVisible = false
func _ready():
# Create the container for the hand
container = HBoxContainer.new()
container.name = "Hand"
container.position = Vector2(10, 500)
container.size_flags_horizontal = SIZE_EXPAND_FILL
add_child(container)
# Create a hover preview panel that will follow the mouse
hoveredPreview = cardPreviewScene.instantiate()
hoveredPreview.visible = false
add_child(hoveredPreview)
func update_hand(hand: Array):
clear_cards()
# Calculate card sizes based on hand size and screen width
var card_size = calculate_card_size(hand.size())
for card in hand:
add_card_display(card, card_size)
func calculate_card_size(hand_size: int) -> Vector2:
# Get screen dimensions
var screen_width = get_viewport_rect().size.x
var screen_height = get_viewport_rect().size.y
var max_hand_width = screen_width * MAX_HAND_WIDTH_RATIO
var width_per_card = max_hand_width / max(hand_size, 1)
# Ensure minimum size and preserve aspect ratio
var card_width = clamp(width_per_card - CARD_MARGIN, 80, BASE_CARD_WIDTH)
var card_height = card_width * (BASE_CARD_HEIGHT / BASE_CARD_WIDTH)
# Ensure cards don't extend off the bottom of the screen
var max_height = screen_height * 0.4 # Use at most 40% of screen height
if card_height > max_height:
card_height = max_height
card_width = card_height * (BASE_CARD_WIDTH / BASE_CARD_HEIGHT)
return Vector2(card_width, card_height)
func add_card_display(card, card_size: Vector2 = Vector2(BASE_CARD_WIDTH, BASE_CARD_HEIGHT)):
# Create a container for the card
var cardContainer = PanelContainer.new()
cardContainer.custom_minimum_size = card_size
# Create a stylebox for selection highlighting
var style = StyleBoxFlat.new()
style.bg_color = Utils.DARK_CELL
style.corner_radius_top_left = 5
style.corner_radius_top_right = 5
style.corner_radius_bottom_left = 5
style.corner_radius_bottom_right = 5
cardContainer.add_theme_stylebox_override("panel", style)
# Create compact card display
var compact_card = CompactCardDisplay.new()
compact_card.set_anchors_preset(Control.PRESET_FULL_RECT)
compact_card.mouse_filter = Control.MOUSE_FILTER_PASS
# Add to container
cardContainer.add_child(compact_card)
compact_card.set_card(card)
# Connect signals
cardContainer.gui_input.connect(func(event): _on_card_clicked(event, card))
cardContainer.mouse_entered.connect(func(): _on_card_mouse_entered(card))
cardContainer.mouse_exited.connect(func(): _on_card_mouse_exited())
# Add to hand container
container.add_child(cardContainer)
# Add to display list
cardDisplays.append({
"panel": cardContainer,
"card": card
})
func _on_card_clicked(event: InputEvent, card: Card):
if event is InputEventMouseButton and event.pressed:
if selectedCard == null || selectedCard.id != card.id:
selectedCard = card
container.emit_signal("card_pressed", card)
elif selectedCard.id == card.id:
selectedCard = null
highlight_selectedCard(selectedCard)
func _on_card_mouse_entered(card: Card):
# Show card preview when hovering
print("_on_card_mouse_entered")
currently_hovered_card = card
hoveredPreview.preview_card(card)
hoveredPreview.visible = true
# Position it above the hand area
var mouse_pos = get_viewport().get_mouse_position()
hoveredPreview.position = Vector2(mouse_pos.x - hoveredPreview.size.x/2, mouse_pos.y - hoveredPreview.size.y - 20)
# Make sure it's visible within screen bounds
hoveredPreview.position.x = clamp(hoveredPreview.position.x, 10, get_viewport_rect().size.x - hoveredPreview.size.x - 10)
hoveredPreview.position.y = clamp(hoveredPreview.position.y, 10, get_viewport_rect().size.y - hoveredPreview.size.y - 10)
isPreviewVisible = true
func _on_card_mouse_exited():
# Only hide the preview after a delay and if we're not hovering over a new card
var exited_card = currently_hovered_card
currently_hovered_card = null
# Wait a bit before hiding
await get_tree().create_timer(0.2).timeout
# Only hide if we're not hovering over a new card
if exited_card == currently_hovered_card or currently_hovered_card == null:
hoveredPreview.visible = false
isPreviewVisible = false
func _process(delta):
# If preview is visible, update its position to follow the mouse
if isPreviewVisible:
var mouse_pos = get_viewport().get_mouse_position()
hoveredPreview.position = Vector2(mouse_pos.x - hoveredPreview.size.x/2, mouse_pos.y - hoveredPreview.size.y - 20)
hoveredPreview.position.x = clamp(hoveredPreview.position.x, 10, get_viewport_rect().size.x - hoveredPreview.size.x - 10)
hoveredPreview.position.y = clamp(hoveredPreview.position.y, 10, get_viewport_rect().size.y - hoveredPreview.size.y - 10)
func highlight_selectedCard(selected: Card) -> void:
for card_data in cardDisplays:
var panel = card_data.panel
var compact_card = panel.get_child(0) as CompactCardDisplay
if selected && card_data.card.id == selected.id:
# Apply highlighting to the CompactCardDisplay
if compact_card:
compact_card.set_selected(true)
else:
# Reset highlighting
if compact_card:
compact_card.set_selected(false)
func get_card_by_uuid(uuid: String) -> Card:
for card_data in cardDisplays:
if card_data.card.id == uuid:
return card_data.card
return null
func getSelectedCard() -> Card:
return selectedCard
func clear_cards():
for card_data in cardDisplays:
card_data.panel.queue_free()
cardDisplays.clear()
selectedCard = null