Files
aetherbound-guild/runtime/ui/m52/cost_module.gd
T

156 lines
7.0 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
status_label.anchor_left = 0.20
status_label.anchor_right = 0.60
cost_label.anchor_left = 0.62
if ledger_mode and get_node_or_null("LedgerCostChrome") == null:
var chrome := MarketChrome.new().configure("ledger_cost")
chrome.name = "LedgerCostChrome"
chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
chrome.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(chrome)
move_child(chrome, 0)
if card_compact_mode and get_node_or_null("CompactCostChrome") == null:
var chrome := MarketChrome.new().configure("compact_cost")
chrome.name = "CompactCostChrome"
chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
chrome.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(chrome)
move_child(chrome, 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)