Files
cards/scripts/ui/card_view.gd
Team3 dfcd3cb713
Some checks failed
Tests / headless (push) Has been cancelled
Tests / fenster-schnell (push) Has been cancelled
Tests / fenster-voll (push) Has been cancelled
Tests / balance (push) Has been cancelled
update
2026-09-22 13:23:02 +02:00

88 lines
4.0 KiB
GDScript

class_name CardView
extends Control
## Zeichnet eine Karte (Hand, Sammlung, Booster, Vorschau).
signal clicked(view: CardView)
signal hover(card: Cards.Card, entered: bool)
var card: Cards.Card
var border = null # Color oder null (dann Seltenheitsfarbe)
var rarity := "gewöhnlich" # nur Optik: Rahmenfarbe der eigenen Stufe
var dim := false
## focusable: per Gamepad oder Tab anwählbar (Sammlung, Booster); A bzw. Enter wirkt wie ein Klick.
func _init(c: Cards.Card, sz: Vector2, focusable: bool = false, rar: String = "gewöhnlich") -> void:
card = c
rarity = rar
custom_minimum_size = sz
size = sz
mouse_filter = Control.MOUSE_FILTER_STOP
mouse_entered.connect(func(): hover.emit(card, true))
mouse_exited.connect(func(): hover.emit(card, false))
if focusable:
focus_mode = Control.FOCUS_ALL
focus_entered.connect(func():
hover.emit(card, true)
queue_redraw())
focus_exited.connect(func():
hover.emit(card, false)
queue_redraw())
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
accept_event()
clicked.emit(self)
elif has_focus() and event.is_action_pressed("ui_accept"):
accept_event()
clicked.emit(self)
func _draw() -> void:
var rect := Rect2(Vector2.ZERO, size)
var big := size.x >= 180
var mid := size.x >= 115
var f_name := 18 if big else (14 if mid else 12)
var f_text := 14 if big else (11 if mid else 10)
var f_stat := 24 if big else (18 if mid else 15)
Style.fill_elements(self, rect, card.elements, 8)
var bcol: Color = border if border != null else Cards.RARITY_COLORS[rarity]
Style.border(self, rect, bcol, 3 if big else 2, 8)
# Kosten
var r := 16 if big else 12
var cc := Vector2(r + 4, r + 4)
draw_circle(cc, r, Color("14141c"))
Style.text(self, str(card.cost), f_stat, Style.GOLD, cc, "center", true)
# Name und Kombo
var name_left := 2 * r + 10
var nm := Style.fit(card.title(), true, f_name, size.x - name_left - 6)
Style.text(self, nm, f_name, Style.TEXT, Vector2((name_left + size.x - 6) / 2.0, 4), "midtop", true)
if mid:
var sub: String = tr(card.combo()) if card.is_combo() else ""
Style.text(self, sub, f_text, Color("e6e6e6"), Vector2(size.x / 2, 2 * r + 4), "midtop")
# Textfeld: Höhe folgt dem umbrochenen Text und der Schriftgröße, das Bild bekommt den Rest
var tsize := Style.fs(f_text)
var text_w: float = size.x - 20
var needed: float = Style.FONT.get_multiline_string_size(card.text(), HORIZONTAL_ALIGNMENT_LEFT, text_w, tsize).y + 8 if card.text() != "" else size.y * 0.42
var box_bottom: float = size.y - (28 if big else 22)
var band_top: float = 2 * r + 4 + (f_text + 6 if mid else 0) # unter Name und Kombo
var box_top: float = maxf(maxf(size.y * 0.30, band_top), box_bottom - maxf(needed, size.y * 0.42))
var box := Rect2(6, box_top, size.x - 12, box_bottom - box_top)
# Bild
var band_bottom: float = box_top - 4
if band_bottom - band_top > 14:
var gsize: float = minf(band_bottom - band_top, size.x * 0.42)
Style.glyph(self, card, Vector2(size.x / 2, (band_top + band_bottom) / 2), gsize)
draw_rect(box, Color(0.06, 0.06, 0.09, 0.67))
var max_lines := maxi(1, int((box.size.y - 6) / Style.FONT.get_height(tsize))) # große Schrift: lieber kürzen als überlaufen
draw_multiline_string(Style.FONT, Vector2(box.position.x + 4, box.position.y + 4 + Style.FONT.get_ascent(tsize)),
card.text(), HORIZONTAL_ALIGNMENT_LEFT, box.size.x - 8, tsize, max_lines, Style.TEXT)
# Werte
Style.text(self, str(card.attack), f_stat, Style.YELLOW, Vector2(10, size.y - 6), "bottomleft", true)
Style.text(self, str(card.health), f_stat, Style.RED, Vector2(size.x - 10, size.y - 6), "bottomright", true)
if dim:
draw_rect(rect, Color(0, 0, 0, 0.47))
if has_focus():
Style.border(self, rect, Style.GOLD, 4, 8)