diff --git a/client/ui/star_map.gd b/client/ui/star_map.gd index 41c7ddee5..5bfb96072 100644 --- a/client/ui/star_map.gd +++ b/client/ui/star_map.gd @@ -403,57 +403,15 @@ func _draw_info_panel(sz: Vector2) -> void: var font := get_theme_default_font() var panel_w: float = POPUP_WIDTH var pad: float = POPUP_PADDING + var sep_h: float = 8.0 # separator line + spacing var inner_w: float = panel_w - pad * 2.0 + var sep_color := Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.12) - # Measure GTTR text height first so we can size the panel - var gttr: String = node.get("gttr_excerpt", "") - # Strip markdown bold markers for display - gttr = gttr.replace("**", "") - var gttr_block_h: float = 0.0 - if not gttr.is_empty(): - var gttr_size: Vector2 = font.get_multiline_string_size( - gttr, HORIZONTAL_ALIGNMENT_LEFT, inner_w, POPUP_GTTR_FONT_SIZE, - POPUP_GTTR_MAX_LINES) - gttr_block_h = gttr_size.y + 6.0 - - # Fixed rows: name, id, star+hop, corridor, bodies+pop, adjacent, separator lines - var fixed_h: float = ( - POPUP_LINE_H * 2.0 # name + id - + 4.0 # separator - + POPUP_LINE_H * 3.0 # star+hop, corridor, bodies+pop - + 4.0 # separator - + gttr_block_h - + 4.0 # separator (before adjacent) - + POPUP_LINE_H # adjacent systems label - + pad * 2.0 - ) - var panel_h: float = fixed_h - - var panel_pos := Vector2(sz.x - panel_w - POPUP_MARGIN, POPUP_MARGIN) - var x: float = panel_pos.x + pad - var y: float = panel_pos.y + pad + POPUP_LINE_H # baseline offset - - # Background + border - draw_rect(Rect2(panel_pos, Vector2(panel_w, panel_h)), COLOR_INFO_BG) - draw_rect(Rect2(panel_pos, Vector2(panel_w, panel_h)), - Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.15), false, 1.0) - - # ── System name ────────────────────────────────────────────────────────── + # ── Prepare all text content before measuring ──────────────────────────── var sys_name: String = node.get("proper_name", "") if sys_name.is_empty(): sys_name = node.get("system_id", "Unknown") - draw_string(font, Vector2(x, y), sys_name, HORIZONTAL_ALIGNMENT_LEFT, inner_w, 15, COLOR_TEXT) - y += POPUP_LINE_H - draw_string(font, Vector2(x, y), node.get("system_id", ""), HORIZONTAL_ALIGNMENT_LEFT, inner_w, 10, COLOR_TEXT_DIM) - y += POPUP_LINE_H - - # Separator - draw_line(Vector2(x, y + 1.0), Vector2(panel_pos.x + panel_w - pad, y + 1.0), - Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.12), 1.0) - y += 6.0 - - # ── Stats block ────────────────────────────────────────────────────────── var star_type: String = node.get("star_type", "") var hop: int = int(node.get("hop_distance", 0)) var stat_line_1: String @@ -461,13 +419,9 @@ func _draw_info_panel(sz: Vector2) -> void: stat_line_1 = "Hop %d from Gateway" % hop else: stat_line_1 = "%s star · hop %d" % [star_type, hop] - draw_string(font, Vector2(x, y), stat_line_1, HORIZONTAL_ALIGNMENT_LEFT, inner_w, 11, COLOR_TEXT_DIM) - y += POPUP_LINE_H var sector_str: String = node.get("geographic_sector", "unknown").replace("_", " ").to_upper() var sector_color: Color = SECTOR_COLORS.get(node.get("geographic_sector", ""), COLOR_TEXT_DIM) - draw_string(font, Vector2(x, y), sector_str + " corridor", HORIZONTAL_ALIGNMENT_LEFT, inner_w, 11, sector_color) - y += POPUP_LINE_H var bodies: String = node.get("bodies", "") var population: String = node.get("population", "") @@ -479,39 +433,106 @@ func _draw_info_panel(sz: Vector2) -> void: elif not population.is_empty(): stat_line_3 = "Population: " + population else: - stat_line_3 = "%d aperture%s · %s" % [ + stat_line_3 = "%d aperture%s" % [ int(node.get("aperture_count", 0)), - "s" if int(node.get("aperture_count", 0)) != 1 else "", - node.get("gate_topology", "")] - draw_string(font, Vector2(x, y), stat_line_3, HORIZONTAL_ALIGNMENT_LEFT, inner_w, 11, COLOR_TEXT_DIM) - y += POPUP_LINE_H + "s" if int(node.get("aperture_count", 0)) != 1 else ""] - # ── GTTR excerpt ───────────────────────────────────────────────────────── - if not gttr.is_empty(): - draw_line(Vector2(x, y + 1.0), Vector2(panel_pos.x + panel_w - pad, y + 1.0), - Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.12), 1.0) - y += 6.0 - draw_multiline_string(font, Vector2(x, y), gttr, HORIZONTAL_ALIGNMENT_LEFT, - inner_w, POPUP_GTTR_FONT_SIZE, POPUP_GTTR_MAX_LINES, - Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.75)) - y += gttr_block_h + var gttr: String = node.get("gttr_excerpt", "").replace("**", "") - # ── Adjacent systems ────────────────────────────────────────────────────── - draw_line(Vector2(x, y + 1.0), Vector2(panel_pos.x + panel_w - pad, y + 1.0), - Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.12), 1.0) - y += 6.0 var adj: Array = node.get("adjacent_systems", []) - if adj.is_empty(): - draw_string(font, Vector2(x, y), "No gate connections", HORIZONTAL_ALIGNMENT_LEFT, inner_w, 10, COLOR_TEXT_DIM) - else: + var adj_line: String = "" + if not adj.is_empty(): var adj_names: Array = [] for neighbor_id: String in adj: var neighbor: Dictionary = _node_lookup.get(neighbor_id, {}) var n_name: String = neighbor.get("proper_name", "") adj_names.append(n_name if not n_name.is_empty() else neighbor_id) - var adj_line: String = " · ".join(adj_names) - draw_multiline_string(font, Vector2(x, y), adj_line, HORIZONTAL_ALIGNMENT_LEFT, - inner_w, 10, 2, COLOR_TEXT_DIM) + adj_line = " · ".join(adj_names) + + # ── Measure variable-height blocks ─────────────────────────────────────── + var gttr_h: float = 0.0 + if not gttr.is_empty(): + gttr_h = font.get_multiline_string_size( + gttr, HORIZONTAL_ALIGNMENT_LEFT, inner_w, + POPUP_GTTR_FONT_SIZE, POPUP_GTTR_MAX_LINES).y + + var adj_h: float = POPUP_LINE_H # minimum one line + if not adj_line.is_empty(): + adj_h = font.get_multiline_string_size( + adj_line, HORIZONTAL_ALIGNMENT_LEFT, inner_w, 10, 3).y + + # ── Calculate total panel height ───────────────────────────────────────── + var panel_h: float = pad # top padding + panel_h += POPUP_LINE_H # system name (15px font) + panel_h += POPUP_LINE_H # system id (10px font) + panel_h += sep_h # separator + panel_h += POPUP_LINE_H # star type + hop + panel_h += POPUP_LINE_H # corridor + panel_h += POPUP_LINE_H # bodies + pop + if not gttr.is_empty(): + panel_h += sep_h + gttr_h + panel_h += sep_h + adj_h # adjacent systems + panel_h += pad # bottom padding + + # ── Draw background ────────────────────────────────────────────────────── + var panel_pos := Vector2(sz.x - panel_w - POPUP_MARGIN, POPUP_MARGIN) + var x: float = panel_pos.x + pad + var x_right: float = panel_pos.x + panel_w - pad + var y: float = panel_pos.y + pad + POPUP_LINE_H # baseline offset + + draw_rect(Rect2(panel_pos, Vector2(panel_w, panel_h)), COLOR_INFO_BG) + draw_rect(Rect2(panel_pos, Vector2(panel_w, panel_h)), sep_color, false, 1.0) + + # ── Draw content ───────────────────────────────────────────────────────── + + # System name + draw_string(font, Vector2(x, y), sys_name, + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 15, COLOR_TEXT) + y += POPUP_LINE_H + + # System ID + draw_string(font, Vector2(x, y), node.get("system_id", ""), + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 10, COLOR_TEXT_DIM) + y += POPUP_LINE_H + + # Separator + draw_line(Vector2(x, y + 2.0), Vector2(x_right, y + 2.0), sep_color, 1.0) + y += sep_h + + # Star type + hop + draw_string(font, Vector2(x, y), stat_line_1, + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 11, COLOR_TEXT_DIM) + y += POPUP_LINE_H + + # Corridor + draw_string(font, Vector2(x, y), sector_str + " corridor", + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 11, sector_color) + y += POPUP_LINE_H + + # Bodies + population + draw_string(font, Vector2(x, y), stat_line_3, + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 11, COLOR_TEXT_DIM) + y += POPUP_LINE_H + + # GTTR excerpt + if not gttr.is_empty(): + draw_line(Vector2(x, y + 2.0), Vector2(x_right, y + 2.0), sep_color, 1.0) + y += sep_h + draw_multiline_string(font, Vector2(x, y), gttr, + HORIZONTAL_ALIGNMENT_LEFT, inner_w, POPUP_GTTR_FONT_SIZE, + POPUP_GTTR_MAX_LINES, + Color(COLOR_TEXT.r, COLOR_TEXT.g, COLOR_TEXT.b, 0.75)) + y += gttr_h + + # Adjacent systems + draw_line(Vector2(x, y + 2.0), Vector2(x_right, y + 2.0), sep_color, 1.0) + y += sep_h + if adj_line.is_empty(): + draw_string(font, Vector2(x, y), "No gate connections", + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 10, COLOR_TEXT_DIM) + else: + draw_multiline_string(font, Vector2(x, y), adj_line, + HORIZONTAL_ALIGNMENT_LEFT, inner_w, 10, 3, COLOR_TEXT_DIM) func _draw_title() -> void: