172 lines
7.7 KiB
GDScript
172 lines
7.7 KiB
GDScript
class_name ABGM52CostModule
|
|
extends Control
|
|
|
|
const MarketChrome = preload("res://ui/shared/market_chrome.gd")
|
|
const UIFactory = preload("res://ui/shared/ui_factory.gd")
|
|
const COST_BADGE = preload("res://assets/ui_m52_components/v2_trimmed/frames/cost_badge.png")
|
|
const COIN_ICON = preload("res://assets/ui_m52_components/v2_trimmed/icons/coin.png")
|
|
|
|
var status := ""
|
|
var cost := ""
|
|
var ledger_mode := false
|
|
var text_scale := 1.0
|
|
|
|
func configure(next_status: String, next_cost: String, next_text_scale := 1.0) -> ABGM52CostModule:
|
|
status = next_status
|
|
cost = next_cost
|
|
text_scale = next_text_scale
|
|
return self
|
|
|
|
func set_compact(compact: bool, show_status := false) -> void:
|
|
var status_label := get_node_or_null("AvailabilityLabel") as Label
|
|
var cost_label := get_node_or_null("CostLabel") as Label
|
|
var icon := get_node_or_null("CoinIcon") as Control
|
|
if status_label == null or cost_label == null:
|
|
return
|
|
ledger_mode = compact and show_status
|
|
var card_compact_mode := compact and not show_status
|
|
var plate := get_node_or_null("CostPlate") as CanvasItem
|
|
if plate != null:
|
|
plate.visible = not ledger_mode and not card_compact_mode
|
|
# M73: at 130% text the availability + amount pair needs the decorative
|
|
# socket band as well; the two labels still never overlap.
|
|
if text_scale > 1.15:
|
|
# Keep the coin socket band free: icon 0.02..0.19, availability next,
|
|
# amount last; all three columns must stay clear of each other.
|
|
var large_icon := get_node_or_null("CoinIcon") as Control
|
|
if large_icon != null:
|
|
large_icon.anchor_left = 0.02
|
|
large_icon.anchor_right = 0.19
|
|
# "999 COIN" measured 153px against a 136px column; the amount owns the
|
|
# wider half at 130% while the availability label keeps the left column.
|
|
status_label.anchor_left = 0.11
|
|
status_label.anchor_right = 0.46
|
|
cost_label.anchor_left = 0.48
|
|
cost_label.offset_right = -2.0
|
|
# M82: measured columns keep one row at both scales. The coin socket owns
|
|
# 0.02..0.17, the availability label 0.18..0.45 and the amount 0.46..0.99,
|
|
# so the icon never rests on the HIRED / 已招募 text.
|
|
var label_font := status_label.get_theme_font("font")
|
|
var font_px := status_label.get_theme_font_size("font_size")
|
|
var status_need := 0.0
|
|
if label_font != null:
|
|
status_need = label_font.get_string_size(status_label.text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_px).x
|
|
var socket_icon := get_node_or_null("CoinIcon") as Control
|
|
if socket_icon != null:
|
|
socket_icon.anchor_left = 0.02
|
|
socket_icon.anchor_right = 0.15
|
|
var icon_slot := size.x * 0.15
|
|
var status_slot := size.x * 0.27
|
|
if status_need > status_slot:
|
|
# A very narrow ledger is the only case that needs the wider split.
|
|
status_label.anchor_left = 0.17
|
|
status_label.anchor_right = 0.53
|
|
cost_label.anchor_left = 0.55
|
|
else:
|
|
status_label.anchor_left = 0.18
|
|
status_label.anchor_right = 0.45
|
|
cost_label.anchor_left = 0.46
|
|
status_label.anchor_top = 0.0
|
|
status_label.anchor_bottom = 1.0
|
|
cost_label.anchor_top = 0.0
|
|
cost_label.anchor_bottom = 1.0
|
|
var exceptional := status.contains("不足") or status.to_lower().contains("insufficient")
|
|
# The card row only has room for the coin socket and the amount; the full
|
|
# availability + currency string belongs to the detail ledger. Keeping the
|
|
# card label visible truncated it to "可招" once type honoured the floor.
|
|
status_label.visible = show_status or exceptional
|
|
if compact:
|
|
status_label.anchor_left = 0.30
|
|
status_label.anchor_right = 0.58
|
|
cost_label.anchor_left = 0.61
|
|
cost_label.offset_right = -4.0
|
|
# The compact ledger amount column is intentionally narrow. Keep the
|
|
# project's normal type family, but give this one value its measured
|
|
# inner size so “14 金币” remains a complete runtime string.
|
|
status_label.add_theme_font_size_override("font_size", ABGUI_Tokens.font_size("micro", text_scale))
|
|
cost_label.add_theme_font_size_override("font_size", ABGUI_Tokens.font_size("micro" if show_status else "label", text_scale))
|
|
if show_status:
|
|
# Detail-ledger variant: do not use the card's centered coin socket.
|
|
# Give the icon, availability and amount three non-overlapping columns.
|
|
var large_text := text_scale > 1.15
|
|
if icon != null:
|
|
icon.anchor_left = 0.02 if large_text else 0.03
|
|
icon.anchor_right = 0.20 if large_text else 0.25
|
|
icon.offset_left = 0.0
|
|
icon.offset_right = 0.0
|
|
status_label.anchor_left = 0.20 if large_text else 0.25
|
|
status_label.anchor_right = 0.62 if large_text else 0.56
|
|
cost_label.anchor_left = 0.64 if large_text else 0.60
|
|
else:
|
|
# Card compact variant: one icon slot and one centered amount slot.
|
|
if icon != null:
|
|
icon.anchor_left = 0.02
|
|
icon.anchor_right = 0.26
|
|
icon.offset_left = 0.0
|
|
icon.offset_right = 0.0
|
|
status_label.visible = false
|
|
cost_label.anchor_left = 0.27
|
|
cost_label.anchor_right = 0.94
|
|
cost_label.offset_right = -2.0
|
|
cost_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
|
|
func _ready() -> void:
|
|
clip_contents = true
|
|
# This asset is authored as a left coin socket plus a stretchable paper
|
|
# strip. NinePatch preserves the socket/corners instead of shrinking the
|
|
# whole silhouette into a thin centered thumbnail on phone layouts.
|
|
# Proportional cost strip: the leftmost fraction is the coin socket and the
|
|
# labels own the band to its right, so nothing can be painted over a glyph.
|
|
var plate := MarketChrome.new().configure("cost_strip")
|
|
plate.name = "CostPlate"
|
|
plate.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
plate.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(plate)
|
|
var icon := TextureRect.new()
|
|
icon.name = "CoinIcon"
|
|
icon.texture = COIN_ICON
|
|
icon.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
# The generated plate's round socket is the coin position: the plate's left
|
|
# patch margin is exactly that socket, so anchor the icon to those pixels
|
|
# instead of a fraction that drifted over the availability label.
|
|
icon.anchor_left = 0.0
|
|
icon.anchor_right = 0.19
|
|
icon.offset_left = 0.0
|
|
icon.offset_right = 0.0
|
|
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
|
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
|
|
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(icon)
|
|
var status_label := UIFactory.label(status, "micro", text_scale, MarketChrome.INK)
|
|
status_label.name = "AvailabilityLabel"
|
|
status_label.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
# The generated cost plate has a decorative circular socket in the middle.
|
|
# Keep status left of that ornament and reserve the right column for the
|
|
# amount so neither dynamic label is painted over the socket.
|
|
status_label.anchor_left = 0.19
|
|
status_label.anchor_right = 0.56
|
|
status_label.offset_left = 0.0
|
|
status_label.offset_right = 0.0
|
|
status_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
|
status_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
status_label.clip_text = true
|
|
status_label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
status_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(status_label)
|
|
var cost_label := UIFactory.label(cost, "label", text_scale, MarketChrome.INK)
|
|
cost_label.name = "CostLabel"
|
|
cost_label.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
# "999 金币" is a complete runtime string; the old 0.60-1.0 column was
|
|
# measured at 113px and trimmed it. The amount owns the wider right band.
|
|
cost_label.anchor_left = 0.58
|
|
cost_label.anchor_right = 1.0
|
|
cost_label.offset_left = 0.0
|
|
cost_label.offset_right = -2.0
|
|
cost_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
|
cost_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
cost_label.clip_text = true
|
|
cost_label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
cost_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(cost_label)
|