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 = {} 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 func _layout() -> void: if _header_labels.is_empty(): return var resource_width: float = size.x * 0.25 var value_width: float = (size.x - resource_width) / 3.0 var columns: Array = [0.0, resource_width, resource_width + value_width, resource_width + value_width * 2.0] var widths: Array = [resource_width, value_width, value_width, value_width] for i in range(_header_labels.size()): _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(3): var label: Label = row[["bank", "fleet", "local"][i]] 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: 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)