35858fa0fa2802cde82fc82aa3272156a816ea84
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
35858fa0fa |
feat(ui): Bookmark tab content + CharacterProfile signal payload (Workstream 6)
Fills in the Bookmark tab stubbed in W5 with the full spec from
Araminta: card list + detail view + start-button gating. Also changes
the creation_confirmed signal to carry a CharacterProfile instead of
bare CharacterVisualDescriptor, consolidating bookmark + location
selection into one payload object.
Bookmark tab (left pane, 35%):
- ScrollContainer over VBoxContainer of card Buttons, one per entry in
GameState.bookmark_catalog. Each card: title (PRIMARY_TEXT,
font_header 15px) / subtitle (DIM_TEXT, font_small 10px, clipped) /
career badge (ACCENT_ACTIVE, all-caps). Selected state uses existing
ITEM_SELECTED_BG + ITEM_SELECTED_BORDER. custom_minimum_size
Vector2(180, 64).
Detail view (right pane, 65%):
- ImplantPanel composed via add_component:
- ImplantHeader (bookmark.title, bookmark.subtitle)
- ImplantSeparator
- ImplantTextBlock (flavor, autowrap, PRIMARY_TEXT)
- ImplantSeparator
- ImplantDataRow CAREER (accent_active) / CAPITAL (accent_positive,
format "%d Tractus") / STARTING LOCATION
- ImplantSeparator
- [location picker space reserved — W7 fills it]
Selection:
- Card click stores _selected_bookmark_id, auto-assigns
_selected_location_id from bookmark.default_location, rebuilds
detail view.
- Start button (footer) gated on both _selected_bookmark_id and
_selected_location_id non-empty.
- Randomize while Bookmark tab is active picks a random bookmark +
one of its allowed_locations and skips appearance randomization.
Signal contract change:
- creation_confirmed(profile: CharacterProfile) replaces
creation_confirmed(descriptor: CharacterVisualDescriptor).
- CharacterProfile now extends RefCounted (was Resource) with
non-exported fields — it's a one-shot signal payload, never
persisted. This also sidesteps the scanner error that the prior
@export var descriptor: CharacterVisualDescriptor on a Resource
caused (RefCounted types cannot be @export-ed).
- _on_start emits a CharacterProfile built from _descriptor +
_selected_bookmark_id + _selected_location_id, then sends
ConfirmBookmark via SimBridge.send_named_action before scene
transition.
Test updates:
- test_character_creation_sprint28.gd signal receivers switched to
untyped to accept CharacterProfile without hitting class_name
parse-order at test-suite scan time. 88/88 pass.
Verification:
- gdlint clean
- godot --headless --path client --quit — no SCRIPT ERROR (prior
character_profile.gd scanner noise now gone after the RefCounted
conversion)
- test_character_creation_sprint28 88/88, test_protocol 62/62,
test_implant_nav_stack 52/52
Workstream 7 (location picker as sub-component of the Bookmark detail
view) follows. W8 fills the Skills tab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
256703e9b7 |
feat(ui): 3-tab restructure of character creation (Workstream 5)
Consolidates the character creation TabContainer from 8 flat tabs
(Body / Head / Hair / Clothing / Accessories / Debug plus the two
being-added Skills / Bookmark) into 4 top-level tabs per Araminta's
revised spec: Bookmark, Appearance, Skills, Debug.
The existing five appearance sub-tabs (Body, Head, Hair, Clothing,
Accessories) now live inside the Appearance tab as a horizontal
segmented sub-navigation using the existing `_make_slot_btn()` pattern
— consistent with the Clothing/Accessories slot row vocabulary.
Selected sub-section uses existing ITEM_SELECTED_BG / BORDER styling.
Structural changes:
- New APPEARANCE_SUB_NAMES const lists the five sub-sections.
- Renamed _tab_search → _appearance_search, _tab_grids →
_appearance_grids. Scope changed from "top-level tabs" to
"Appearance sub-sections" but index 0..4 semantics preserved.
- Added _appearance_active_idx, _appearance_sub_btns,
_appearance_sub_sections state.
- _ready() builds exactly 4 top-level tabs; tab builders invoked
explicitly per index.
- New _build_bookmark_tab / _build_skills_tab render TEXT_DIM
placeholder labels ("Bookmark content lands in Workstream 6", etc.)
— actual content in W6/W8.
- _build_appearance_tab constructs the sub-nav strip and stacks all
5 sub-sections up front with visibility-toggle swap
(_on_appearance_sub_selected). Comment explains the up-front build
choice and the free-and-rebuild fallback if performance regresses.
- Existing _build_body_tab / _head / _hair / _clothing / _accessories /
_debug remain unchanged — they now receive Appearance sub-section
Controls as their tab argument instead of top-level tabs. _make_tab_vbox
anchors full-rect in both parent contexts, so layout is preserved.
Verification:
- gdlint clean
- godot --headless --path client --quit — no SCRIPT ERROR
- test_protocol 62/62, test_client_p3 24/24, test_ui_framework_sprint15
54/54, test_implant_nav_stack 52/52, test_implant_registry 42/42,
test_implant_app_lifecycle 36/36
Workstream 6 (Bookmark tab content: card list + detail view + location
picker per Araminta's spec) lands next. W7 (location picker as a
sub-component of Bookmark tab) follows. W8 (Skills stub content) is
last. Hoshe's parallel Task #21 (test hygiene triage) commits
separately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
2104348000 |
feat(client): Option A pre-game flow + ESC priority chain (Workstream 4)
main_menu now connects SimBridge before character_creation opens, gating the transition on first ObserverSnapshot carrying a bookmark_catalog. Loading screen is shown during the connect; on cancel the SimBridge subprocess is torn down and the player returns to main_menu. Catalog is read straight from GameState.bookmark_catalog in W6. Flow (Option A): 1. New Game → SessionManager.new_game() creates save dir 2. main_menu pushes loading_screen via MetaStack with "Connecting to simulation..." message 3. SimBridge.connect_to_sim() spawned; main_menu listens on connection_state_changed, then on snapshot_received for the catalog 4. On catalog arrival: loading_screen closed, scene-transition to character_creation 5. character_creation Cancel → SimBridge.disconnect_from_sim() + scene transition back to main_menu (Tyre's recommendation: clean state per session over warm-start savings) 6. character_creation Start → ConfirmBookmark sent (stubbed for W4 with first catalog entry; real bookmark + location from W6's UI) ESC priority chain in main.gd OPEN_MENU handler: - MetaStack.handle_escape() first — closes the topmost meta overlay - HudGroups.is_implant_active() / close_app() — closes active implant - Fallback: toggle settings_dialog (existing W2 behavior) Files: - sim_bridge.gd: send_named_action(action_name, action_data) helper. Bridges named tag-enum PlayerActions (RequestBookmarkCatalog, ConfirmBookmark) into the existing outbound buffer, parallel to send_input's InputMapper.Action handling. - loading_screen.gd: set_message(text) for the connecting/loading label. - main_menu.gd: full Option A flow rewrite. Tracks _waiting_for_catalog so re-clicking New Game during connect is a no-op. - character_creation.gd: _on_back disconnect path + _on_start ConfirmBookmark stub. MAIN_MENU_SCENE / GAME_SCENE constants. - main.gd: connect_to_sim guard (don't reconnect when Option A leaves it CONNECTED). ESC chain wiring. Verification: - gdlint clean - godot --headless --path client --quit — no SCRIPT ERROR - test_protocol 62/62, test_implant_nav_stack 52/52, test_client_p3 24/24, test_ui_framework_sprint15 54/54 Pre-existing failing suites unchanged: test_sprint2_proof, test_dialogue_sprint18, test_client_p2 (camera-smoothing assertions that pre-date W4 — main.gd has disabled position_smoothing_enabled since #117 / #501 / #117 manual-lerp; tests were stale). Workstream 5 (3-tab restructure of character_creation: Bookmark / Appearance with sub-nav / Skills / Debug) lands next. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
f24d08f756 |
refactor(ui): migrate 6 meta screens to MetaScreen pattern (Workstream 2)
Relocates main_menu, character_creation, settings_dialog, debug_console,
bug_report_dialog, loading_screen from flat client/ui/ into structured
client/ui/meta/screens/<name>/. All six now extend MetaScreen instead
of Control; the base handles open/close lifecycle, visibility,
captures_input, and — for overlays — the sim-pause contract.
Screen policies set per Tyre's proposal:
- settings_dialog: pauses_sim=false, PUSHES onto MetaStack
- debug_console: pauses_sim=true, PUSHES (D-088 routing via base)
- bug_report_dialog: pauses_sim=true, PUSHES
- loading_screen: closable_by_escape=false, PUSHES
- main_menu, character_creation: scene-roots, extend MetaScreen for
the lifecycle contract only, do NOT push onto the stack
character_creation stays at its current surface (tabs, descriptor,
creation_confirmed signal unchanged). Tab consolidation and
CharacterProfile migration happen in Workstreams 5 and 6.
Knock-on changes:
- main.tscn ModalLayer CanvasLayer renamed to MetaLayer; main.gd
@onready refs updated; constants.gd comment updated; test_client_p3
and test_ui_framework_sprint15 assertions updated; test_monologue_display
and .tscn header comments updated.
- OPEN_MENU handler now pushes settings_dialog onto MetaStack before
calling open(). Full ESC priority chain lands in Workstream 4.
- atlas_app.gd: _unhandled_key_input signature widened from
InputEventKey to InputEvent with an is-check, per Godot 4 API. Pre-
existing narrowing was silently tolerated until main.tscn started
fully instantiating under the new pattern.
- test_client_p3: entity_renderer type annotations corrected from
ColorRect to Sprite2D (stale since a prior refactor); facing
indicator rotation assertion switched to angle_difference() for
modular-safe comparison.
Verification:
- gdlint client/scripts/ client/ui/ — zero problems
- godot --headless --path client --quit — no SCRIPT ERROR
- test_client_p3: 24/24 pass
- test_ui_framework_sprint15: 54/54 pass
- test_implant_nav_stack: 52/52 pass
- test_implant_registry: 42/42 pass
- test_implant_app_lifecycle: 36/36 pass
Workstream 1 foundation (
|
||
|
|
84105916cd |
feat(ui): introduce MetaScreen pattern foundation (#618, #680)
Establishes the faux-game-menu base pattern for non-diegetic UI, analogous to ImplantApp but for pre-gameplay and meta-overlay screens (main menu, character creation, settings, debug console, bug report, loading screen). Workstream 1 of the MetaScreen refactor — foundation only, no screen migrations yet. - client/ui/meta/meta_screen.gd: base class (Control) with HIDDEN/OPENING/OPEN/CLOSING phase tracking, three orthogonal policy booleans (pauses_sim, closable_by_escape, captures_input), open/close lifecycle, on_escape contract, closed + escape_pressed signals, subclass hooks (on_open, on_close). - client/ui/meta/meta_stack.gd: autoload coordinator. Overlay stack with push/pop/top/is_active; handle_escape chain; sim-pause coordination via SimBridge when pauses_sim=true; meta_active_changed signal. All class references kept inside method bodies — no top-level class_name refs, matching HudGroups / GameState autoload parse-order discipline. - client/scripts/character_profile.gd: Resource wrapping the visual descriptor with bookmark_id and start_location_id. Target of the creation_confirmed signal once the character creation flow migrates. - client/project.godot: MetaStack registered as autoload after HudGroups, before ImplantRegistry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |