port/godot
14 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f7cadaeb68 |
M6.19: Confirm & Begin → CharacterBuilder handoff + hybrid pick plumbing
The wizard now produces a real runtime Character instead of just persisting the draft Resource. New Theriapolis.Godot/UI/CharacterAssembler bridges CharacterDraft → CharacterBuilder, picking the purebred Build or hybrid TryBuildHybrid path, threading clade/species/class/background lookups, ability scores, skill picks, dominant-parent, subclass id, and the items table for the starting kit. The captured PlayerCharacterState writes to user://character.json (resumability before the M7 save format lands) and the live Character is held in CharacterAssembler.LastBuilt for future PlayScreen pickup. StepReview.OnConfirmPressed surfaces build errors on the status label instead of crashing, logs HP/hybrid/skill totals on success, and keeps emitting the existing CharacterConfirmed signal. Hybrid lineage bonuses now match the wizard's preview math. CharacterBuilder gains HybridSireChosenAbility / HybridDamChosenAbility; TryBuildHybrid replaces the old "apply both clades' full mods + both species mods" blend with "apply each parent's chosen mod only" — species mods don't apply for hybrids per project decision. Picks stack additively when both parents land on the same ability (canidae +1 CON × ursidae +2 CON → +3 CON). Empty pick = no bonus (defensive fallback for headless builds). HybridCharacterTests' BlendsAbilityMods rewritten for the new rule, plus two new tests for stacking and empty-pick fallback. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
39117a09ed |
M6.17: Variant content + Sheep/Goat split + calling lore + uniform card layout
Species variants populated against the M6.13 schema: - Lion-Folk sex axis: Mane Guard (male) / Huntress Reflexes (female, +5 ft speed + advantage on initiative). - Elk-Folk sex axis: Antler Combat with 10 ft reach when full rack (male, retains seasonal Antler Drag) / Kick (female, prone on crit). Base traits restored to doc canon: Herd Coordination (Help → +3) + Endurance Runner (40 ft + advantage CON vs forced march); base speed bumped 30 → 40; new base detriment Herd Instinct. Ram-Folk replaced with separate Sheep-Folk + Goat-Folk species rather than a lineage-axis variant on a single Ram entry. Bovidae now has 4 species. The lineage-axis toggle UI in StepSpecies BuildCard rolled back; the schema stays for sex-axis (Lion/Elk) which auto-resolves. ContentLoadTests + HybridCharacterTests updated; Size.cs comment too. Calling lore: ClassDef gains Description; classes.json populated for all 8 callings with the doc's italic blockquote + paragraph profile. StepClass surfaces the description on the card. Card layout uniformity: StepClass / StepSubclass / StepBackground all switched to single-column ExpandFill grids (matching StepClade / StepSpecies). Each card now spans the wizard's content width so the description and feature chips have room to breathe. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
0ab4715aee |
M6.16: Unified hybrid species grid + codex-styled hover popover
StepSpecies hybrid mode now uses one grid combining sire-clade species (under a "SIRE — <Clade>" eyebrow) and dam-clade species (under "DAM — <Clade>"). Cards are click-to-select like the purebred path — since clades are guaranteed disjoint by StepClade's parent-conflict rule, the lineage is implicit from the species' clade and no per-card toggles are needed. Hover popover now picks up the codex theme: parchment Bg2 panel with a gild border, rounded 14px corners, and soft drop shadow; H3 display serif title, mono Eyebrow tag, CardBody description. Detriment popovers swap to a 3px seal-red border via the panel_detriment stylebox override (replaces the old red Modulate hack). Theme propagation fix: CanvasLayer breaks Godot's Control theme inheritance, so the popup was rendering on Godot defaults. _Ready defers a lookup of the parent Control's theme and assigns it directly to the popup so the codex parchment + Cormorant/CrimsonPro fonts actually resolve. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
479899d3d1 |
M6.15: Unified hybrid clade grid with Sire/Dam toggle headers
Replace the two stacked sire/dam clade grids in StepClade hybrid mode with one unified grid where each card carries Sire and Dam toggle buttons side-by-side in its header (right edge of the title row). A single clade can become either parent; picking Sire on a card currently set as Dam atomically clears the Dam pick (and vice versa). Card body click is disabled in hybrid mode — only the toggles change selection. Mechanics: BuildLineageCladePatch extracts the per-lineage clear logic from the old OnLineageCladePicked into a patch builder so OnHybridParentPressed can compose multi-lineage patches into one atomic Patch call (the cross-clear case applies both lineage updates in a single Changed signal). UpdateHybridCards walks the unified card dictionary and syncs both toggle states + the card's selected highlight. Drops the old _sireCards / _damCards dictionaries and the OnLineageCladePicked callback, since hybrid mode no longer routes through the per-grid click handlers. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
66055f9549 |
M6.14: Single-column card layout with clade/species descriptions
Switch Step 0 (Clade) and Step 1 (Species) from a 3-column card grid to a 1-column layout, with each card carrying a codex-voice description paragraph between the meta line and the trait chips. Rationale: establish the world's tone before mechanics — the player reads who Canidae or Wolf-Folk *are* before evaluating ability mods and trait pills. Trade is more vertical scrolling, but the card content was already going wider than three columns comfortably allowed once the parchment theme bumped padding. Schema: CladeDef and SpeciesDef gain a Description field (string, empty default). Populated for all 7 clades and 19 species, sourced from the doc's italicized blockquote + a one-sentence summary of the prose paragraph that follows. Empty descriptions fall through silently — a species without a description still renders, just without the paragraph. UI: MakeGrid in both steps becomes Columns = 1 with ExpandFill; BuildCard sets card.SizeFlagsHorizontal = ExpandFill (replaces the fixed CustomMinimumSize 200) and prepends the autowrap description label after the meta line. Hybrid mode stacks sire and dam single- column grids vertically — same logic as before, just one card wide each. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e1fb988969 |
M6.13: Sex picker + species variant schema
Adds character Sex (male/female) as a top-level CharacterDraft field
required for every character, and species variants as a layer on top
of the base species record. Two variant axes:
- "sex": auto-resolves from CharacterDraft.Sex for purebreds; for
hybrids, pinned by parent role (sire = male, dam = female)
by definition. No picker needed beyond Step 0.
- "lineage": explicit per-species pick (Ram-Folk's sheep/goat). Has
its own picker on Step 1 (purebred path under the grid;
hybrid path embedded into the per-parent pick column).
Schema (Theriapolis.Core/Data):
- SpeciesDef gains VariantAxis (string) and Variants (array of
SpeciesVariantDef { Id, Name, Traits, Detriments }).
- JSON content not yet populated — that's M6.14.
CharacterDraft adds:
- Sex (required by Step 0 validation)
- SpeciesVariant / SireSpeciesVariant / DamSpeciesVariant
- ResolveVariantId(species, role) that returns the active variant
id for a given context — used by Aside to layer variant traits
onto the base species traits.
Step 0 (StepClade): sex picker row above the hybrid toggle. Two
toggle buttons radio-style.
Step 1 (StepSpecies): purebred path renders a lineage picker below
the grid when the picked species has VariantAxis == "lineage";
hybrid path embeds a lineage picker at the top of each parent's
pick column. Hover popovers summarise each variant's contents.
Validation: Sex is required at Step 0. Lineage variant required at
Step 1 for any picked species (purebred or per-hybrid-parent) with
VariantAxis == "lineage".
Aside: AddVariantContent layers the resolved variant's extra
traits/detriments onto the base species rendering, for both purebred
and hybrid paths.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
8bf9eba2a7 |
M6.8: Hybrid trait pickers (Phase B)
Per theriapolis-rpg-clades.md "Building a Hybrid": hybrids now pick two clade traits from the dominant parent + one from the other (2/1 split keyed off DominantParent), and one species trait + one species detriment from each parent. All clade detriments still inherit fully from both parents. Universal hybrid detriments unchanged. CharacterDraft gains six new fields (sire/dam clade-trait arrays, sire/dam species trait/detriment ids) and a CladeTraitLimit(lineage) helper. Step 0/1 validators enforce the picks; Aside renders only the chosen subset for hybrids. Cascading clears: clade swap clears that lineage's bonus + clade traits + (if species also invalidated) species pick; species swap clears that lineage's species trait/detriment; dominant flip trims overflow from the end (non-destructive when possible); hybrid-off clears all six new fields. Toggle buttons in both steps wire MouseEntered/Exited into PopoverLayer so the player can read each trait's description on hover (detriment buttons get the red-tinted "DETRIMENT" popover). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e3f0296e6f |
M6.7: Parchment theme pass
Lights up the M5 codex design system across the wizard. Default palette swaps from dark leather to aged-parchment cream with sealing-wax red selection emphasis, matching the React prototype's default theme variant. CodexTheme.Build() is applied at the wizard root so every step + Aside + popover cascades through it. Theme additions: - Parchment palette in CodexPalette (Dark retained as alt) - Type variations registered for Card, CodexPopover, Pill, PillDetriment, AbilityToken, AbilitySlot, SkillRow — without SetTypeVariation, panel-stylebox lookup falls through to Godot's default dark slate, which is what was happening to every bare PanelContainer before this pass. - panel_hover stylebox on Card (gild border) wired via CodexCard's MouseEntered/Exited helper; panel_selected bumped to 3px seal-red border + soft shadow so selection reads at a glance. Card selection refactor: - Replaced the warm-cream Modulate hint on cards with stylebox swaps via the new CodexCard.SetSelected helper. The Modulate approach was a no-op on cream-on-cream parchment; the stylebox swap looks the same on either palette. - Step intros + Aside section headers now use the existing Eyebrow / H2 / H3 / CardName / CardMeta / CardBody label variations. - Confirm button on Step VIII uses the PrimaryButton variation. Popover + chip behaviour: - PopoverLayer is now MouseFilter=Ignore so clicks/scroll/hover all pass through. Adjacent chips fire reliably even when the previous popover overlaps them spatially. - Dropped the 80ms grace timer; chip MouseExited closes immediately. - TraitChip MouseFilter Stop → Pass so clicks bubble up to the parent card's GuiInput (selecting the card). Misc: - Wizard._Ready inserts a backing Panel so the parchment Bg fills the canvas — Wizard root is a plain Control, which paints nothing. - CodexTheme font lookup tries Cormorant-Medium before -Regular and globalizes res://Fonts/ for runtime FontFile load (the previous fallback used ContentPaths which points at a sibling data tree). - StepStats final-score Label rendered at font_size 22 to match the AbilityToken die. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
bb986d49f9 |
M6.6: StepReview signing + hybrid math revision
- New Step VIII (Review): name input and Confirm button that saves the finalized character to user://character.tres. - Hybrid lineage rules simplified per project decision: drop the "no-stack on overlap, take +1 free elsewhere" rule from theriapolis-rpg-clades.md. Hybrids now pick one ability mod from each parent clade and they sum if they overlap. Removes HybridFreeAbility, the free-bonus picker row, and the overlap special case from AbilityCalc + WizardValidation. - StepClade bonus rows now mutate in place (sync ButtonPressed) instead of tearing down on every Refresh — the old path freed the very button mid-Pressed-signal, leaving stale buttons next to the new ones. - StepSkills drops the redundant "Calling: X · History: Y" meta line; both are already shown in the Aside summary. - Aside hybrid section adds dual-species traits and the universal-hybrid detriment pills. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
0e5d4b7425 |
M6.5: StepSkills + ability-bonus breakdown + Aside redesign
The skills step lands as the last data-driven character creation step
(only Sign — name + confirm — remains for M6.6). Brought a few cross-
cutting refactors with it.
Scenes/Steps/StepSkills.cs:
Direct port of StepSkills in src/steps.jsx — all 18 skills laid out
in 6 ability-grouped panels (STR/DEX/CON/INT/WIS/CHA), 2-column
grid. Background-granted skills appear pre-checked and locked;
user picks `class.SkillsChoose` more from `class.SkillOptions`.
Hover the skill name → popover with the codex flavor description
(limited to the title only — hovering checkboxes / source tags
doesn't trigger the popover, avoids interference with adjacent
rows' click targets). Fixed-width [✓] / [ ] / [—] checkbox slot
so toggling doesn't shift the row layout.
UI/SkillsCatalog.cs (new):
Static skill table — JSON id, display label, governing ability,
and the codex SKILL_DESC text ported verbatim from src/data.jsx.
Mirrors Theriapolis.Core.Rules.Stats.SkillId; descriptions live
here because backgrounds.json and classes.json don't carry them.
UI/AbilityCalc.cs (new):
Final-score math — base assignment + clade and species mods, with
per-source breakdown for the bonus popover ("+1 from Canidae · +2
from Wolf"). Hybrid mode tags each clade source with its lineage
("(sire)" / "(dam)"). Used by both StepStats and the Aside so the
two views can never disagree on what a +N badge means.
UI/BackgroundAvailability.cs (new):
Extracted from StepBackground — shared rules table for hybrid-only
and clade-restricted backgrounds. Now also consulted by StepClade
when the player changes lineage: the currently-selected background
is auto-cleared if the new lineage no longer satisfies its rule
(e.g., Pack-Raised clears when switching from Canidae to Felidae,
Passer clears when toggling Hybrid off). Implemented via
Resource.Duplicate + Patch on the duplicate to evaluate the
hypothetical post-patch state without committing prematurely.
StepStats.cs:
Per-row layout extended: ability label | slot | bonus chip | final
| d20 mod. Bonus chip is a TraitChip with the per-source breakdown
in its hover description. Auto-assign now sorts empty abilities by
AbilityCalc.TotalBonus DESCENDING (with class.PrimaryAbility as
tiebreaker) — biggest pool value lands on the ability already
receiving the biggest lineage bonus, maximising final scores.
Aside.cs (significant redesign):
- Name centered at top.
- Lineage details: 2-column grid, full-width.
- Purebred: Clade | Species, then Calling | Background, then
Subclass | (empty).
- Hybrid: SIRE ★ | DAM (centered + underlined column heads),
Clade | Clade, Species | Species, then the same
calling/background/subclass rows.
- Attributes: STR/DEX/CON/INT/WIS/CHA each with bonus chip (omitted
when +0), final score, d20 modifier. Self-contained min-width
table so it can't widen the panel beyond its alloc.
- Pills: traits, detriments, level-1 features, background feature,
skill chips (BG-locked + user-chosen). All hoverable for descriptions.
- Whole panel wraps in a ScrollContainer so an over-tall summary
scrolls in place instead of pushing the wizard layout off-screen.
- Width nudged 320 → 360px. Smaller font on label tags, autowrap
on value labels so long names ("Hybrid Underground") wrap rather
than push the panel wider.
Card grids: changed all five card-grid steps (Clade, Species, Class,
Subclass, Background) from SizeFlagsHorizontal.ExpandFill →
ShrinkCenter. Cards stay at their CustomMinimumSize 200 wide and
the grid horizontally centers in PageMain. The right-side gap
between content and Aside is now uniform regardless of how many
cards or whether the last row is partial — fixes the "Clade tab
feels too padded, Background tab too tight" perception.
Closes M6.5. Per guide §12, what's left in M6: M6.6 (StepReview —
name + summary + Confirm handoff per guide §11) and M6.7 (parchment
Theme pass).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
ce87eb11ad |
M6.4: Card-grid steps + hybrid origin + clade-restricted backgrounds
Per GODOT_PORTING_GUIDE.md §12, the four "easy" card-grid steps land
together (Species / Calling / Subclass / History), plus three real
features that emerged during testing: cross-step validation gating,
hybrid origin, and clade-restricted background availability.
New step files (Scenes/Steps/):
StepSpecies.cs — cards filtered by clade; for hybrids shows two
stacked grids (Sire / Dam).
StepClass.cs — all classes; class change clears chosen skills
and the previously-selected subclass.
StepSubclass.cs — subclasses filtered by ClassDef.SubclassIds.
StepBackground.cs — backgrounds filtered by hybrid + clade rules
(see below).
UI/WizardValidation.cs (new):
Static per-step validators against CharacterDraft. Replaces the
per-instance Validate() route on the wizard side — Wizard now
computes the lock state for every step in the flow, not just the
current one. Mirrors app.jsx's firstIncomplete rule exactly.
Bug it fixes: previously the wizard checked only the current step's
validity, so picking a clade let you skip directly to Abilities
without picking species/calling/etc.
UI/CharacterDraft.cs:
Phase 6.5 hybrid fields — IsHybrid, SireCladeId, SireSpeciesId,
DamCladeId, DamSpeciesId, DominantParent. EffectiveCladeId /
EffectiveSpeciesId resolve to the dominant parent's lineage when
hybrid; downstream steps don't need to care which path. Helpers
HasClade(id) and HasAnyCladeOfKind(kind) feed the background
availability rules.
StepClade.cs:
Hybrid toggle splits the picker into Sire + Dam grids with a
Dominant Lineage radio. Validation refuses same-clade Sire+Dam.
Switched to build-once + mutate-in-place: cards are created once
during Build(), Refresh just updates Modulate per selection state.
Tearing down + rebuilding inside the click callback caused
duplicates because Free() defers when the freed node is mid-signal.
StepBackground.cs:
Availability rules table — predicates per restricted background id.
Hybrid-only: passer, hybrid_underground, former_chattel.
Clade-restricted: warren_runner (Leporidae), pack_raised (Canidae),
herd_city_born (any prey clade).
Hybrids match if either parent satisfies the rule.
Other steps (Species/Class/Subclass/Background):
Refresh dispatched via Callable.From(Refresh).CallDeferred() so the
rebuild runs after the click handler completes — same Free()-during-
signal bug as StepClade hit, fixed via deferral instead of mutate-
in-place because the card lists are dynamic (clade- / class- /
hybrid-flag-dependent).
Wizard.cs:
- RebuildStepperStates uses WizardValidation.FirstIncomplete to lock
every step past the first unsatisfied one.
- OnStepperClicked checks every step in [0..target-1].
- UpdateChrome's banner uses WizardValidation for the active step.
- Scroll preservation moved here (snapshot before step.Refresh
fires, restore in _Process); StepStats's local copy removed.
Wizard.tscn:
Scroll node marked unique_name_in_owner so Wizard can grab it.
PopoverLayer's TraitChip is reused throughout the new step cards.
Aside.cs:
Hybrid-aware summary — shows "Sire (dominant)" / "Dam" lineage rows
when IsHybrid; otherwise the existing Clade / Species rows.
Verified end-to-end:
- Walk Clade → Species → Calling → Subclass → History → Abilities
- Stepper locks every step past first unsatisfied
- Hybrid toggle works both directions, dominant changes lineage
- Hybrid-only and clade-restricted backgrounds appear / disappear
based on lineage
- Scroll position preserved across selections
- Drag-drop still works on Abilities
Closes M6.4. Per guide §12, next is M6.5 — StepSkills (class-driven
choice list with TraitChip per skill).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
ba3ebe7ff3 |
M6.3: Trait popovers — shared PopoverLayer + TraitChip triggers
Per GODOT_PORTING_GUIDE.md §6 (and §12 build order — popovers before
the easy card-grid steps because traits/skills/bonuses surface them
everywhere). One reusable popover panel; lightweight chip triggers.
Scenes/Widgets/PopoverLayer.cs:
CanvasLayer added once as a child of Wizard.tscn. Owns one
PanelContainer + close Timer; static Instance for chip-side access.
ShowFor(trigger, ...) populates and positions the popover at the
trigger's global rect with viewport clamp + flip-above logic
(mirrors src/trait-hint.jsx). 80 ms grace period when moving from
trigger to popover so the popover stays open across the gap.
Detriment popovers get a red Modulate as a placeholder for the
seal-coloured StyleBox the theming pass will install.
Scenes/Widgets/TraitChip.cs:
Lightweight PanelContainer + Label trigger. On MouseEntered asks
PopoverLayer.Instance to show; on MouseExited schedules close.
Pill styling deferred to theming (default Godot panel for now;
TraitChip / TraitChipDetriment styleboxes will land alongside
the parchment Theme pass).
Wizard.tscn:
PopoverLayer added as a top-level CanvasLayer child so popovers
float above every step's content regardless of where the trigger
is in the tree.
Steps/StepClade.cs:
Replaces the placeholder "{n} traits, {m} detriments" line with an
HFlowContainer of TraitChip per trait + per detriment. Hover any
chip → popover shows name + description (+ DETRIMENT tag for the
detriment chips).
Also: cards switched from Button to PanelContainer for content-
driven height. Button isn't a Container, so its intrinsic min
size didn't aggregate from the inner vbox — at higher trait
counts the chips overflowed into the cards below. PanelContainer
is a Container, so the card grows with its content. GuiInput
handles the click-to-select; selected state shown via Modulate
tint until the proper StyleBox swap lands in theming.
Closes M6.3. Per guide §12, next is M6.4 — easy card-grid steps
(Species / Calling / Subclass / History) variations on the StepClade
pattern, then StepSkills, then StepReview.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
4d3db17a89 |
M6.2: Step V Abilities — drag-drop assignment + roll/auto-assign
Per GODOT_PORTING_GUIDE.md §7, the highest-risk piece in the wizard.
Three reusable widgets + the orchestrating step.
Scenes/Widgets/AbilityToken.cs:
Draggable Control with Value + Origin metadata. _GetDragData returns
a Dictionary payload {kind, value, from, ability, idx} per guide
§7.1. MouseFilter = Pass so clicks propagate to the parent slot
for the click-to-return affordance (later removed; see commit body).
Drag preview is a dimmed duplicate.
Scenes/Widgets/AbilitySlot.cs:
PanelContainer drop target per guide §7.2. Accepts any
ability_value payload via _CanDropData / _DropData and emits
Dropped(payload). Each slot owns one ability id (STR/DEX/CON/INT/
WIS/CHA).
Scenes/Widgets/AbilityPool.cs:
HBoxContainer drop target per guide §7.3. Accepts only slot→pool
drops (returning an assigned value to the pool); pool→pool drops
are no-ops.
Scenes/Steps/StepStats.cs:
Direct port of StepStats in steps.jsx per guide §7.4. Standard
array (default) and roll-4d6-drop-lowest method tabs; Reroll
button visible in roll mode; Auto Assign sorts the remaining pool
descending and places the largest values into empty slots ordered
by class.PrimaryAbility. Three drag-drop cases (pool→slot,
slot→slot swap, slot→pool) all delegate to a single Patch call,
then the entire token tree rebuilds from the new draft state on
the Changed signal — handlers don't reparent anything manually.
Issues hit during development and resolved before commit:
- Initial click-to-return on slot pre-empted drag-from-slot every
time (the GuiInput fired on mouse-down, before Godot detected
the drag). Removed click-to-return — drag is the canonical
interaction; that matches the React prototype anyway.
- Token MouseFilter = Stop blocked clicks from reaching the slot
layer; switched to Pass which still works as a drag source.
- Refresh() teardown + rebuild reset the parent ScrollContainer's
scroll to 0 every drop. CallDeferred / SetDeferred / CreateTimer
all raced because layout settles over multiple frames; the fix
that worked was capturing scroll position pre-rebuild and
restoring in _Process the next frame.
Wizard.cs:
StepTypes[5] = typeof(StepStats); the Abilities step is now
reachable. (StepTypes[1..4, 6..7] still null — coming in M6.3+.)
Verified: all three drag scenarios + click handling + auto-assign
+ method switch + reroll work; scroll position holds across drops.
Closes M6.2. Next per guide §12: M6.3 — popover system (TraitChip +
shared PopoverLayer) before adding more easy card-grid steps.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
ee5439285c |
M6.1: Character creation wizard foundation (.tscn + Resource-based draft)
Pivots from M5's code-built UI to the editor-authorable .tscn pattern
recommended in GODOT_PORTING_GUIDE.md, after a session of fighting
Godot idioms with code-only layout. Default theme only; the parchment
Theme lands last per the guide's §12 build order so layout bugs surface
as layout bugs, not theming bugs.
GODOT_PORTING_GUIDE.md:
Authored by Claude Design as the canonical port reference. Maps the
React prototype's structure onto Godot 4.6 with concrete code sketches
and a build-order recommendation. Drove the M6 architecture.
Fonts/:
Cormorant Garamond (Medium + MediumItalic) and Crimson Pro (Regular +
Italic + SemiBold) under OFL — the React prototype's serif-display
and serif-body families. Not yet wired through CodexTheme.Build()
because theming is deferred; CodexTheme.LoadFontFromFonts already
picks them up automatically when the Theme pass lands.
Scenes/Wizard.tscn + Wizard.cs:
Wizard shell per guide §4: codex-header (title + folio counter) +
Stepper + Page (StepHost + Aside) + NavBar (Back / validation / Next).
All node lookups via unique-name (%) syntax; layout authored as a
scene file you can open in the editor. Step lifecycle drives the
Aside via signal binding. Stepper logic mirrors app.jsx — locked
iff some EARLIER step is unsatisfied; "type not yet implemented"
doesn't lock.
Scenes/Aside.tscn + Aside.cs:
Right-rail summary per guide §10. Single Refresh() rebuild on
CharacterDraft.Changed; cheap enough not to bother with partial
updates. Width 320 (was 380 before the layout overflow fix).
Scenes/Steps/IStep.cs + StepClade.cs:
Per-step Bind(draft) + Validate() contract. StepClade renders the
3-column clade card grid; click commits via CharacterDraft.Patch
which triggers the Resource.Changed signal that Aside and Wizard
both subscribe to.
UI/CharacterDraft.cs:
Resource (not Node) per guide §2.1. Mirrors app.jsx's `state` shape
exactly. Patch(dictionary) emits the inherited Resource.Changed
signal — listeners use `draft.Changed += handler` regardless of
which field changed. CodexContent provides lazy-loaded immutable
content tables (Clades, Species, Classes, Subclasses, Backgrounds).
Main.{cs,tscn}: Node → Control
When Main was a Node, Control children couldn't anchor to a real
parent rect — they sat at (0,0) at intrinsic min size. With wide
step content (3-column 200-px-card grid), the Wizard's min size
pushed the navbar beyond the viewport's right edge, hiding the Next
button on smaller windowed viewports. Making Main a full-rect-
anchored Control gives child scenes a proper rect to lay out in.
UI/Widgets/CodexStepper.cs:
Anchored the inner vbox to fill the button rect. Without this, the
vbox sat at the button's top-left at intrinsic size and labels
rendered in the corner — visible as the active-step label being
off-center from the highlight bar.
Verified at 1152x720 windowed and (separately) at fullscreen:
- 3-column card grid fits inside Wrap margins + Aside without
horizontal overflow
- Stepper labels centered under their highlight bars
- Next button visible after clade selection; future steps switch
to "coming soon" placeholder when clicked
- Aside summary fills in CLADE block on selection
Closes M6.1. Next per guide §12 build order: M6.2 — StepStats with
drag-drop (highest-risk piece, de-risk before easy steps).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|