The research table's LOCAL column was not merely equal to BANKED, it was the same store: research lives on the mothership, the mothership is also the bank, and building_inventory() redirects any bank-capable building to bank_inventory itself. ResourceBar now drops LOCAL wherever it resolves to the bank and lets the remaining two columns share the width. Anywhere else - a crafter, a lab, the transfer panel - the column is untouched. The "Research" heading went with it. It named a panel you can only reach by pressing the research button, and it cost the tree canvas 128px, which the table and the tree have now taken back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
165 lines
6.2 KiB
GDScript
165 lines
6.2 KiB
GDScript
class_name ResourceBar
|
|
extends Control
|
|
|
|
# Compact resource table shared by crafting, research and the ship lab.
|
|
# Rows are resources; columns are locations. Adding another material to
|
|
# The resource-definition catalog automatically gives each material a row.
|
|
|
|
var building_id: int = 0
|
|
|
|
# Header band and font sizes were all set for a 84px-tall box, which made the
|
|
# table read as a dense strip of small numbers. The hosting menus now give it
|
|
# 136px, so the rows have somewhere to breathe and the text can be legible at
|
|
# arm's length on a phone.
|
|
const HEADER_HEIGHT: float = 30.0
|
|
# Vertical gap between rows. Previously rows were flush against each other and
|
|
# the only separation was colour.
|
|
const ROW_GAP: float = 4.0
|
|
const HEADER_FONT_SIZE: int = 20
|
|
const NAME_FONT_SIZE: int = 23
|
|
const VALUE_FONT_SIZE: int = 24
|
|
const RULE_COLOR: Color = Color(0.25, 0.55, 0.7)
|
|
const FLEET_COLOR: Color = Color(1.0, 0.78, 0.25)
|
|
const LOCAL_COLOR: Color = Color(0.45, 0.9, 0.55)
|
|
|
|
var _header_labels: Array[Label] = []
|
|
var _rows: Dictionary = {}
|
|
|
|
# The value columns, in the order they are drawn. LOCAL is dropped from this
|
|
# list at a building that IS the bank - see _local_is_banked().
|
|
const VALUE_KEYS: Array = ["bank", "fleet", "local"]
|
|
var _local_shown: bool = true
|
|
|
|
|
|
func _ready() -> void:
|
|
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
for heading in ["", "BANKED", "FLEET", "LOCAL"]:
|
|
var label := _make_label(heading, HEADER_FONT_SIZE, Color(0.62, 0.78, 0.86))
|
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
add_child(label)
|
|
_header_labels.append(label)
|
|
|
|
for resource_type in GameState.resource_types():
|
|
var glyph := ResourceGlyph.new()
|
|
glyph.resource_type = resource_type
|
|
add_child(glyph)
|
|
var name_label := _make_label(GameState.resource_name(resource_type).to_upper(),
|
|
NAME_FONT_SIZE, GameState.resource_color(resource_type))
|
|
add_child(name_label)
|
|
var bank_label := _make_value_label(GameState.resource_color(resource_type))
|
|
var fleet_label := _make_value_label(FLEET_COLOR)
|
|
var local_label := _make_value_label(LOCAL_COLOR)
|
|
for label in [bank_label, fleet_label, local_label]:
|
|
add_child(label)
|
|
_rows[resource_type] = {
|
|
"glyph": glyph, "name": name_label, "bank": bank_label,
|
|
"fleet": fleet_label, "local": local_label,
|
|
}
|
|
|
|
resized.connect(_layout)
|
|
_layout()
|
|
queue_redraw()
|
|
|
|
|
|
func _make_label(text_value: String, font_size: int, colour: Color) -> Label:
|
|
var label := Label.new()
|
|
label.text = text_value
|
|
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
label.add_theme_font_size_override("font_size", font_size)
|
|
label.add_theme_color_override("font_color", colour)
|
|
label.add_theme_color_override("font_outline_color", Color(0.01, 0.01, 0.035, 0.95))
|
|
label.add_theme_constant_override("outline_size", 2)
|
|
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
return label
|
|
|
|
|
|
func _make_value_label(colour: Color) -> Label:
|
|
var label := _make_label("0", VALUE_FONT_SIZE, colour)
|
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
return label
|
|
|
|
|
|
# #95: at a building that IS the bank - the mothership carries both the "bank"
|
|
# and the "research" capability, so the research menu is always opened from one
|
|
# - building_inventory() redirects to bank_inventory itself, and LOCAL is not
|
|
# merely equal to BANKED but the very same store read twice. Printing the
|
|
# number again teaches nothing and costs a third of the table, so the column
|
|
# goes away there and the remaining two share the width.
|
|
func _local_is_banked() -> bool:
|
|
if building_id == 0:
|
|
return false
|
|
return GameState.building_inventory(building_id) == GameState.bank_inventory
|
|
|
|
|
|
func _visible_value_keys() -> Array:
|
|
return VALUE_KEYS if _local_shown else VALUE_KEYS.slice(0, 2)
|
|
|
|
|
|
func _layout() -> void:
|
|
if _header_labels.is_empty():
|
|
return
|
|
var keys: Array = _visible_value_keys()
|
|
var resource_width: float = size.x * 0.25
|
|
var value_width: float = (size.x - resource_width) / float(keys.size())
|
|
var columns: Array = [0.0]
|
|
var widths: Array = [resource_width]
|
|
for i in range(keys.size()):
|
|
columns.append(resource_width + value_width * float(i))
|
|
widths.append(value_width)
|
|
for i in range(_header_labels.size()):
|
|
var shown: bool = i < columns.size()
|
|
_header_labels[i].visible = shown
|
|
if not shown:
|
|
continue
|
|
_header_labels[i].position = Vector2(columns[i], 0.0)
|
|
_header_labels[i].size = Vector2(widths[i], HEADER_HEIGHT)
|
|
|
|
var rows: float = maxf(1.0, float(_rows.size()))
|
|
# The gap is taken OUT of the available height rather than added on top of
|
|
# each row, so the table still ends exactly where its box does however many
|
|
# resources the catalog grows to.
|
|
var row_height: float = (size.y - HEADER_HEIGHT - ROW_GAP) / rows
|
|
var row_index: int = 0
|
|
for resource_type in GameState.resource_types():
|
|
var row: Dictionary = _rows[resource_type]
|
|
var y: float = HEADER_HEIGHT + float(row_index) * row_height
|
|
var content_height: float = row_height - ROW_GAP
|
|
row.glyph.position = Vector2(2.0, y + ROW_GAP * 0.5)
|
|
row.glyph.size = Vector2(content_height, content_height)
|
|
row.name.position = Vector2(content_height + 10.0, y)
|
|
row.name.size = Vector2(resource_width - content_height - 10.0, row_height)
|
|
for i in range(VALUE_KEYS.size()):
|
|
var label: Label = row[VALUE_KEYS[i]]
|
|
label.visible = i < keys.size()
|
|
if not label.visible:
|
|
continue
|
|
label.position = Vector2(columns[i + 1], y)
|
|
label.size = Vector2(widths[i + 1], row_height)
|
|
row_index += 1
|
|
queue_redraw()
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
# building_id is assigned by whichever panel opens, so the column count can
|
|
# change between frames; re-lay out only when it actually flips.
|
|
var local_shown: bool = not _local_is_banked()
|
|
if local_shown != _local_shown:
|
|
_local_shown = local_shown
|
|
_layout()
|
|
for resource_type in GameState.resource_types():
|
|
var row: Dictionary = _rows.get(resource_type, {})
|
|
if row.is_empty():
|
|
continue
|
|
row.bank.text = str(GameState.banked_resource(resource_type))
|
|
row.fleet.text = str(GameState.fleet_resource(resource_type))
|
|
row.local.text = str(GameState.building_resource(building_id, resource_type)) \
|
|
if building_id != 0 else "—"
|
|
|
|
|
|
static func natural_height() -> float:
|
|
return 84.0
|
|
|
|
|
|
func _draw() -> void:
|
|
NeonDraw.draw_glowing_line(self, Vector2(0.0, size.y), Vector2(size.x, size.y),
|
|
RULE_COLOR, 0.55, 1.0)
|