style(ui): gdformat atlas implant files
This commit is contained in:
@@ -36,8 +36,15 @@ const RAIL_DASH_ON: float = 6.0
|
||||
const RAIL_DASH_OFF: float = 4.0
|
||||
|
||||
const PRODUCTION_FUNCTIONS: Array = [
|
||||
"industrial", "industry", "manufacturing", "extraction", "mining",
|
||||
"refinery", "foundry", "shipyard", "production",
|
||||
"industrial",
|
||||
"industry",
|
||||
"manufacturing",
|
||||
"extraction",
|
||||
"mining",
|
||||
"refinery",
|
||||
"foundry",
|
||||
"shipyard",
|
||||
"production",
|
||||
]
|
||||
|
||||
var viewer = null # AtlasViewer (untyped to avoid cyclic ref)
|
||||
@@ -56,7 +63,9 @@ func _draw() -> void:
|
||||
|
||||
# Terrain (heightmap) — always first
|
||||
if viewer.is_overlay_visible("terrain"):
|
||||
draw_texture_rect(tex, Rect2(Vector2.ZERO, Vector2(tex_w, tex_h)), false, COLOR_HEIGHTMAP_TINT)
|
||||
draw_texture_rect(
|
||||
tex, Rect2(Vector2.ZERO, Vector2(tex_w, tex_h)), false, COLOR_HEIGHTMAP_TINT
|
||||
)
|
||||
else:
|
||||
draw_rect(Rect2(Vector2.ZERO, Vector2(tex_w, tex_h)), Color(0.05, 0.07, 0.10, 1.0))
|
||||
|
||||
@@ -128,7 +137,9 @@ func _draw_named_features(markers: Dictionary) -> void:
|
||||
if label.is_empty():
|
||||
continue
|
||||
var p: Vector2 = _center_to_canvas(ocean.get("center"))
|
||||
draw_string(font, p, label.to_upper(), HORIZONTAL_ALIGNMENT_CENTER, -1, fs, COLOR_FEATURE_LABEL)
|
||||
draw_string(
|
||||
font, p, label.to_upper(), HORIZONTAL_ALIGNMENT_CENTER, -1, fs, COLOR_FEATURE_LABEL
|
||||
)
|
||||
|
||||
for mtn: Dictionary in markers.get("mountain_ranges", []):
|
||||
var label: String = mtn.get("name", "") if mtn.get("name") else ""
|
||||
@@ -195,12 +206,16 @@ func _draw_cities(markers: Dictionary) -> void:
|
||||
var name_str: String = c.get("name", "") if c.get("name") else ""
|
||||
if not name_str.is_empty() and (tier >= 3 or is_hovered or is_selected):
|
||||
var lcolor: Color = (
|
||||
COLOR_CITY_HOVER if is_hovered or is_selected
|
||||
else Color(0.88, 0.90, 0.96, 0.85)
|
||||
COLOR_CITY_HOVER if is_hovered or is_selected else Color(0.88, 0.90, 0.96, 0.85)
|
||||
)
|
||||
draw_string(
|
||||
font, pos + Vector2(r + 2.0, r * 0.4), name_str,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 8, lcolor
|
||||
font,
|
||||
pos + Vector2(r + 2.0, r * 0.4),
|
||||
name_str,
|
||||
HORIZONTAL_ALIGNMENT_LEFT,
|
||||
-1,
|
||||
8,
|
||||
lcolor
|
||||
)
|
||||
|
||||
|
||||
@@ -304,12 +319,14 @@ func _poi_pos(poi: Dictionary) -> Vector2:
|
||||
|
||||
|
||||
func _draw_diamond(pos: Vector2, size: float, color: Color) -> void:
|
||||
var pts: PackedVector2Array = PackedVector2Array([
|
||||
pos + Vector2(0, -size),
|
||||
pos + Vector2(size, 0),
|
||||
pos + Vector2(0, size),
|
||||
pos + Vector2(-size, 0),
|
||||
])
|
||||
var pts: PackedVector2Array = PackedVector2Array(
|
||||
[
|
||||
pos + Vector2(0, -size),
|
||||
pos + Vector2(size, 0),
|
||||
pos + Vector2(0, size),
|
||||
pos + Vector2(-size, 0),
|
||||
]
|
||||
)
|
||||
draw_colored_polygon(pts, color)
|
||||
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ const PANEL_MARGIN: float = 16.0
|
||||
# ── Orbital diagram geometry ──────────────────────────────────────────────────
|
||||
const ORBITAL_CENTER_FRACTION := Vector2(0.5, 0.55)
|
||||
const STAR_RADIUS: float = 12.0
|
||||
const ORBITAL_RING_BASE: float = 65.0 # innermost planet ring radius (px)
|
||||
const ORBITAL_RING_STEP: float = 58.0 # radial gap between orbit rings
|
||||
const MOON_ORBIT_RADIUS: float = 24.0 # sub-orbit radius for moons around parent
|
||||
const STATION_SIZE: float = 6.0 # station marker half-size
|
||||
const BODY_HIT_RADIUS: float = 16.0 # click/hover detection radius
|
||||
const LABEL_OFFSET: float = 11.0 # px below body dot for label
|
||||
const ORBITAL_RING_BASE: float = 65.0 # innermost planet ring radius (px)
|
||||
const ORBITAL_RING_STEP: float = 58.0 # radial gap between orbit rings
|
||||
const MOON_ORBIT_RADIUS: float = 24.0 # sub-orbit radius for moons around parent
|
||||
const STATION_SIZE: float = 6.0 # station marker half-size
|
||||
const BODY_HIT_RADIUS: float = 16.0 # click/hover detection radius
|
||||
const LABEL_OFFSET: float = 11.0 # px below body dot for label
|
||||
|
||||
# ── Colors ────────────────────────────────────────────────────────────────────
|
||||
const COLOR_BG: Color = Color("#0d1117")
|
||||
@@ -49,28 +49,28 @@ const COLOR_TEXT_DIM: Color = Color("#667788")
|
||||
|
||||
# ── Navigation state ──────────────────────────────────────────────────────────
|
||||
var _level: Level = Level.SYSTEM_PICKER
|
||||
var _systems: Array = [] # Array[Dictionary] from star_map_data.json
|
||||
var _selected_idx: int = 0 # index into _systems
|
||||
var _systems: Array = [] # Array[Dictionary] from star_map_data.json
|
||||
var _selected_idx: int = 0 # index into _systems
|
||||
var _selected_body: Dictionary = {} # body dict at Level.BODY_ENTRY
|
||||
|
||||
# ── Orbital diagram runtime state ─────────────────────────────────────────────
|
||||
var _orbital_bodies: Array = [] # orbit_bodies for current system
|
||||
var _orbital_bodies: Array = [] # orbit_bodies for current system
|
||||
var _orbital_stations: Array = [] # stations for current system
|
||||
var _body_positions: Dictionary = {} # body_id -> Vector2
|
||||
var _station_positions: Dictionary = {} # station_id -> Vector2
|
||||
var _body_positions: Dictionary = {} # body_id -> Vector2
|
||||
var _station_positions: Dictionary = {} # station_id -> Vector2
|
||||
var _hovered_body: String = ""
|
||||
var _hovered_station: String = ""
|
||||
var _selected_station: Dictionary = {} # station clicked in orbital view
|
||||
var _dirty: bool = true
|
||||
|
||||
# ── Visual components (D-169 ImplantPanel library) ────────────────────────────
|
||||
var _implant_theme = null # ImplantTheme — loaded at runtime (autoload parse-order rule)
|
||||
var _picker_panel = null # ImplantPanel — level 0 system selector
|
||||
var _picker_nav_row = null # ImplantDataRow — nav hint text, updated on navigate
|
||||
var _body_panel = null # ImplantPanel — level 2 body entry
|
||||
var _station_panel = null # ImplantPanel — station mini, shown in level 1 on click
|
||||
var _implant_theme = null # ImplantTheme — loaded at runtime (autoload parse-order rule)
|
||||
var _picker_panel = null # ImplantPanel — level 0 system selector
|
||||
var _picker_nav_row = null # ImplantDataRow — nav hint text, updated on navigate
|
||||
var _body_panel = null # ImplantPanel — level 2 body entry
|
||||
var _station_panel = null # ImplantPanel — station mini, shown in level 1 on click
|
||||
var _screen_header: ImplantHeader = null # D-169-composed title/hint row (top-left)
|
||||
var _viewer = null # AtlasViewer — level 3 heightmap viewer (#835)
|
||||
var _viewer = null # AtlasViewer — level 3 heightmap viewer (#835)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -446,7 +446,10 @@ func _draw_stations() -> void:
|
||||
var rect: Rect2 = Rect2(pos - Vector2(half, half), Vector2(STATION_SIZE, STATION_SIZE))
|
||||
|
||||
if sid == _hovered_station:
|
||||
draw_rect(Rect2(rect.position - Vector2(3, 3), rect.size + Vector2(6, 6)), Color(1.0, 1.0, 1.0, 0.18))
|
||||
draw_rect(
|
||||
Rect2(rect.position - Vector2(3, 3), rect.size + Vector2(6, 6)),
|
||||
Color(1.0, 1.0, 1.0, 0.18)
|
||||
)
|
||||
|
||||
draw_rect(rect, COLOR_STATION)
|
||||
|
||||
@@ -454,7 +457,15 @@ func _draw_stations() -> void:
|
||||
if sid == _hovered_station:
|
||||
var label: String = s.get("proper_name", sid) if s.get("proper_name") else sid
|
||||
var lsz: Vector2 = font.get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, 9)
|
||||
draw_string(font, pos + Vector2(-lsz.x / 2.0, half + 8.0), label, HORIZONTAL_ALIGNMENT_LEFT, -1, 9, COLOR_TEXT_DIM)
|
||||
draw_string(
|
||||
font,
|
||||
pos + Vector2(-lsz.x / 2.0, half + 8.0),
|
||||
label,
|
||||
HORIZONTAL_ALIGNMENT_LEFT,
|
||||
-1,
|
||||
9,
|
||||
COLOR_TEXT_DIM
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -736,7 +747,9 @@ func _rebuild_station_panel() -> void:
|
||||
return
|
||||
|
||||
var s: Dictionary = _selected_station
|
||||
var s_name: String = s.get("proper_name", "") if s.get("proper_name") else s.get("station_id", "—")
|
||||
var s_name: String = (
|
||||
s.get("proper_name", "") if s.get("proper_name") else s.get("station_id", "—")
|
||||
)
|
||||
var s_type: String = s.get("station_type", "").replace("_", " ").to_upper()
|
||||
var gov: String = s.get("governance_type", "") if s.get("governance_type") else ""
|
||||
var role: String = s.get("economic_role", "") if s.get("economic_role") else ""
|
||||
@@ -747,7 +760,9 @@ func _rebuild_station_panel() -> void:
|
||||
_station_panel.add_component(ImplantHeader.new(s_name, s_type + " STATION"))
|
||||
_station_panel.add_component(ImplantSeparator.new())
|
||||
if not gov.is_empty():
|
||||
_station_panel.add_component(ImplantDataRow.new("operator " + gov.replace("_", " ").to_upper()))
|
||||
_station_panel.add_component(
|
||||
ImplantDataRow.new("operator " + gov.replace("_", " ").to_upper())
|
||||
)
|
||||
if not role.is_empty():
|
||||
_station_panel.add_component(ImplantDataRow.new("function " + role.replace("_", " ")))
|
||||
_station_panel.add_component(ImplantDataRow.new("currency " + czone))
|
||||
|
||||
@@ -56,28 +56,72 @@ const COLOR_EMPTY_NOTICE: Color = Color("#445566")
|
||||
## visibility ladder: always = public, toggle = observable, locked = semi-
|
||||
## private / private. Keep this table in sync with D-191 §7.
|
||||
const OVERLAY_DEFS: Array = [
|
||||
{"id": "terrain", "label": "TER", "group": "always",
|
||||
"tooltip": "Terrain — base heightmap. Always visible."},
|
||||
{"id": "infrastructure", "label": "INF", "group": "always",
|
||||
"tooltip": "Infrastructure — roads + rail. Always visible."},
|
||||
{"id": "named_features", "label": "NAM", "group": "always",
|
||||
"tooltip": "Named features — rivers, oceans, ranges. Always visible."},
|
||||
{"id": "gate_markers", "label": "GAT", "group": "always",
|
||||
"tooltip": "Gate + spaceport markers. Always visible."},
|
||||
{"id": "political_zones", "label": "POL", "group": "always",
|
||||
"tooltip": "Political zones — currency-zone bands. Always visible."},
|
||||
{"id": "population_density", "label": "POP", "group": "toggle",
|
||||
"tooltip": "Population density (D-181 public)."},
|
||||
{"id": "production_zones", "label": "PRD", "group": "toggle",
|
||||
"tooltip": "Production zones (D-181 observable — requires presence)."},
|
||||
{"id": "shadow_economy", "label": "SHD", "group": "toggle",
|
||||
"tooltip": "Shadow economy zones (D-181 observable)."},
|
||||
{"id": "corp_presence", "label": "CRP", "group": "toggle",
|
||||
"tooltip": "Corporate presence — Tier 1 only (D-181 observable)."},
|
||||
{"id": "stockpile_weeks", "label": "STK", "group": "locked",
|
||||
"tooltip": "Stockpile weeks — LOCKED. Needs corporate contact (D-181 semi-private)."},
|
||||
{"id": "production_vs_baseline", "label": "BSL", "group": "locked",
|
||||
"tooltip": "Production vs baseline — LOCKED. Needs insider access (D-181 private)."},
|
||||
{
|
||||
"id": "terrain",
|
||||
"label": "TER",
|
||||
"group": "always",
|
||||
"tooltip": "Terrain — base heightmap. Always visible."
|
||||
},
|
||||
{
|
||||
"id": "infrastructure",
|
||||
"label": "INF",
|
||||
"group": "always",
|
||||
"tooltip": "Infrastructure — roads + rail. Always visible."
|
||||
},
|
||||
{
|
||||
"id": "named_features",
|
||||
"label": "NAM",
|
||||
"group": "always",
|
||||
"tooltip": "Named features — rivers, oceans, ranges. Always visible."
|
||||
},
|
||||
{
|
||||
"id": "gate_markers",
|
||||
"label": "GAT",
|
||||
"group": "always",
|
||||
"tooltip": "Gate + spaceport markers. Always visible."
|
||||
},
|
||||
{
|
||||
"id": "political_zones",
|
||||
"label": "POL",
|
||||
"group": "always",
|
||||
"tooltip": "Political zones — currency-zone bands. Always visible."
|
||||
},
|
||||
{
|
||||
"id": "population_density",
|
||||
"label": "POP",
|
||||
"group": "toggle",
|
||||
"tooltip": "Population density (D-181 public)."
|
||||
},
|
||||
{
|
||||
"id": "production_zones",
|
||||
"label": "PRD",
|
||||
"group": "toggle",
|
||||
"tooltip": "Production zones (D-181 observable — requires presence)."
|
||||
},
|
||||
{
|
||||
"id": "shadow_economy",
|
||||
"label": "SHD",
|
||||
"group": "toggle",
|
||||
"tooltip": "Shadow economy zones (D-181 observable)."
|
||||
},
|
||||
{
|
||||
"id": "corp_presence",
|
||||
"label": "CRP",
|
||||
"group": "toggle",
|
||||
"tooltip": "Corporate presence — Tier 1 only (D-181 observable)."
|
||||
},
|
||||
{
|
||||
"id": "stockpile_weeks",
|
||||
"label": "STK",
|
||||
"group": "locked",
|
||||
"tooltip": "Stockpile weeks — LOCKED. Needs corporate contact (D-181 semi-private)."
|
||||
},
|
||||
{
|
||||
"id": "production_vs_baseline",
|
||||
"label": "BSL",
|
||||
"group": "locked",
|
||||
"tooltip": "Production vs baseline — LOCKED. Needs insider access (D-181 private)."
|
||||
},
|
||||
]
|
||||
|
||||
# ── Context (set by AtlasPanel.show_body) ─────────────────────────────────────
|
||||
@@ -112,12 +156,12 @@ var _overlay_visibility: Dictionary = {}
|
||||
var _overlay_locked: Dictionary = {}
|
||||
|
||||
# ── Child nodes ───────────────────────────────────────────────────────────────
|
||||
var _canvas: Node2D = null # transformed node holding heightmap + markers
|
||||
var _canvas: Node2D = null # transformed node holding heightmap + markers
|
||||
var _overlay_node: AtlasMarkerOverlay = null # draws on top of heightmap
|
||||
var _city_panel = null # ImplantPanel sidebar (city data)
|
||||
var _empty_notice = null # ImplantPanel shown when heightmap missing
|
||||
var _overlay_bar = null # #836 overlay toggle bar (no class_name, review #8)
|
||||
var _screen_header: ImplantHeader = null # top-left title/hint (D-169 composition)
|
||||
var _city_panel = null # ImplantPanel sidebar (city data)
|
||||
var _empty_notice = null # ImplantPanel shown when heightmap missing
|
||||
var _overlay_bar = null # #836 overlay toggle bar (no class_name, review #8)
|
||||
var _screen_header: ImplantHeader = null # top-left title/hint (D-169 composition)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -314,10 +358,7 @@ func _zoom_at(mouse_pos: Vector2, factor: float) -> void:
|
||||
func grid_to_canvas(grid_point: Vector2) -> Vector2:
|
||||
if _grid_w <= 0.0 or _grid_h <= 0.0:
|
||||
return Vector2.ZERO
|
||||
return Vector2(
|
||||
grid_point.x / _grid_w * _tex_w,
|
||||
grid_point.y / _grid_h * _tex_h
|
||||
)
|
||||
return Vector2(grid_point.x / _grid_w * _tex_w, grid_point.y / _grid_h * _tex_h)
|
||||
|
||||
|
||||
func canvas_to_screen(canvas_point: Vector2) -> Vector2:
|
||||
@@ -461,10 +502,7 @@ func city_canvas_pos(city: Dictionary) -> Vector2:
|
||||
if city.has("lat") and city.has("lon"):
|
||||
var lon: float = float(city["lon"])
|
||||
var lat: float = float(city["lat"])
|
||||
return Vector2(
|
||||
(lon + 180.0) / 360.0 * _tex_w,
|
||||
(90.0 - lat) / 180.0 * _tex_h
|
||||
)
|
||||
return Vector2((lon + 180.0) / 360.0 * _tex_w, (90.0 - lat) / 180.0 * _tex_h)
|
||||
if city.has("center") and city["center"] is Array and city["center"].size() >= 2:
|
||||
# center is [row, col] in grid space
|
||||
return grid_to_canvas(Vector2(float(city["center"][1]), float(city["center"][0])))
|
||||
@@ -526,7 +564,9 @@ func _rebuild_city_panel() -> void:
|
||||
if not czone.is_empty():
|
||||
_city_panel.add_component(ImplantDataRow.new("currency " + czone))
|
||||
var commission: bool = bool(c.get("commission_presence", false))
|
||||
_city_panel.add_component(ImplantDataRow.new("commission " + ("yes" if commission else "no")))
|
||||
_city_panel.add_component(
|
||||
ImplantDataRow.new("commission " + ("yes" if commission else "no"))
|
||||
)
|
||||
var shadow: Variant = c.get("shadow_economy_zone")
|
||||
if shadow != null and not str(shadow).is_empty():
|
||||
_city_panel.add_component(ImplantDataRow.new("shadow zone " + str(shadow)))
|
||||
@@ -570,7 +610,9 @@ func _build_empty_notice() -> void:
|
||||
_empty_notice.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_empty_notice.visible = false
|
||||
add_child(_empty_notice)
|
||||
_empty_notice.add_component(ImplantHeader.new("TERRAIN DATA PENDING", "regional atlas unavailable"))
|
||||
_empty_notice.add_component(
|
||||
ImplantHeader.new("TERRAIN DATA PENDING", "regional atlas unavailable")
|
||||
)
|
||||
_empty_notice.add_component(ImplantSeparator.new())
|
||||
var notice_text: String = (
|
||||
"The server atlas pipeline has not yet populated terrain_reference for this body (#839). "
|
||||
|
||||
Reference in New Issue
Block a user