|
1 | 1 | --- |
2 | 2 | name: Rust WIP refactor plan |
3 | | -description: Structural work to complete in rust-wip before selectively moving domains into rust-stable |
| 3 | +description: Remaining structural work in rust-wip before selectively moving domains into rust-stable |
4 | 4 | --- |
5 | 5 |
|
6 | 6 | # Rust WIP refactor plan |
7 | 7 |
|
8 | | -## Purpose |
9 | | - |
10 | 8 | `rust-wip` is functionally broad but developed as a fast, exploratory workspace. |
11 | | -Before work is transferred into `rust-stable`, make its ownership boundaries and |
12 | | -module structure match [conventions.md](conventions.md). The stable branch should |
13 | | -then receive small, reviewable domain slices rather than architectural cleanup. |
14 | | - |
15 | | -This is a plan, not a license to cherry-pick the existing WIP history. The |
16 | | -current 87 WIP-only commits are archaeological evidence; WIP is the source |
17 | | -snapshot and stable receives deliberate file-level transfers. |
18 | | - |
19 | | -## Assessment baseline |
20 | | - |
21 | | -On 2026-07-18, `rust-stable` was the merge base of `rust-wip`. The committed |
22 | | -delta was 463 files, +44,043 / -2,642 lines. The largest native additions were |
23 | | -the panel UI (+13,421 lines), Chonsole (+3,729), editing states (+2,999), and |
24 | | -developer console (+1,944). |
25 | | - |
26 | | -The backend is already mostly feature-first: commands, models, and tests are |
27 | | -generally co-located under their feature directories. The main exception is the |
28 | | -native UI, which is organized by rendering technology under `panels/editors`. |
29 | | - |
30 | | -## Refactors required before stable transfers |
31 | | - |
32 | | -### 1. Make feature UI feature-owned |
| 9 | +Before work transfers into `rust-stable`, its ownership boundaries and module |
| 10 | +structure must match [conventions.md](conventions.md), so the stable branch |
| 11 | +receives small, reviewable domain slices rather than architectural cleanup. |
33 | 12 |
|
34 | | -`panels/` must retain only reusable RmlUi infrastructure: host/document |
35 | | -lifecycle, fields, modal primitives, grid, input, and shared theme. Move actual |
36 | | -editor behaviour beside the feature it represents: |
| 13 | +## Done |
37 | 14 |
|
38 | | -```text |
39 | | -objects/ui/{definitions,properties,collision}/ |
40 | | -heightmap/ui/ |
41 | | -grass/ui/ |
42 | | -metal/ui/ |
43 | | -textures/ui/ |
44 | | -map_settings/ui/ |
45 | | -teams/ui/ |
46 | | -project/ui/ |
47 | | -``` |
| 15 | +- Feature UI is feature-owned (`<feature>/ui/`, each editor split into |
| 16 | + `model` / `layout` / `behavior`); the old `panels/editors/` is gone. |
| 17 | +- `ModelShader` extracted to `sbc/render/`; `states` no longer imports panel UI. |
| 18 | +- `PanelManager` decomposed into `EditorSlot` / `FieldSession` / `ModalStack` / |
| 19 | + `ActionDispatcher` / `BrushSync`; the wide `Editor` trait is implemented once |
| 20 | + by the generic `Runtime<B>`. |
| 21 | +- Shared theme split into `panels/theme/*.rcss`. |
| 22 | +- Concrete UI moved out of `panels/`: the dev editor → `dev/`, the new-project |
| 23 | + dialog → `project/`, def thumbnails → `objects/`. Reusable pieces grouped |
| 24 | + under `panels/{controls,dialogs,cursor,fields,runtime,theme}`. |
48 | 25 |
|
49 | | -The generic panel registry can remain shared, but each feature must register its |
50 | | -own editor. This is the highest-value refactor: an Objects or Textures transfer |
51 | | -then becomes a coherent domain copy rather than surgery inside a generic folder. |
| 26 | +## Remaining |
52 | 27 |
|
53 | | -### 2. Remove the state → panel dependency |
| 28 | +### Objects boundary |
54 | 29 |
|
55 | | -Editing states currently depend on `panels::ModelShader` for ghost previews, |
56 | | -selection highlights, movement, and rotation. Extract world rendering to |
57 | | -`states` or a neutral renderer module. Map interaction must not depend on the |
58 | | -right-hand panel implementation. |
| 30 | +Properties and Collision still duplicate selection projection and object-field |
| 31 | +mapping. Extract a shared `objects/ui/selection.rs` both project through. Also |
| 32 | +TODO #1: replace the generic JSON Area/Feature/Unit object commands with |
| 33 | +concrete typed commands, and cache static object-field descriptors. |
59 | 34 |
|
60 | | -### 3. Shrink the panel coordinator and editor contract |
| 35 | +### Split project IO from the Project feature |
61 | 36 |
|
62 | | -`PanelManager` currently owns document lifecycle, editor lifecycle, actions, |
63 | | -field commits/drags, modal coordination, state synchronisation, and cursor tips. |
64 | | -Keep a small composition point, but extract active-editor lifecycle, modal |
65 | | -coordination, toolbar actions, and field commits into focused components. |
| 37 | +Finish extracting project paths + save/load/export registrations into a neutral |
| 38 | +project-IO/workspace module (`io_registries`, `paths` exist but still sit inside |
| 39 | +`project/`). Scenario metadata, archive export, reload, map info, and the |
| 40 | +project editor stay in `project/`. This is TODO #16; it stops each saving |
| 41 | +feature depending on the whole Project feature. |
66 | 42 |
|
67 | | -Likewise split the broad `Editor` trait into explicit capabilities around |
68 | | -lifecycle/rendering, field hosting, brush/state binding, and optional modal |
69 | | -ownership. Do not introduce a general event bus or UI framework: retain the |
70 | | -explicit update/input order, just give each concern a narrow owner. |
| 43 | +### Texture material ownership |
71 | 44 |
|
72 | | -### 4. Finish the Objects boundary |
| 45 | +`list_materials` / `material_of` still live in `textures/ui/model.rs`. Move |
| 46 | +material discovery/parsing into the `textures` feature proper; the editor |
| 47 | +consumes it. Texture/material ownership must not be trapped in a panel editor |
| 48 | +before the Textures domain transfers. |
73 | 49 |
|
74 | | -Refactor the Objects UI into definitions/catalog/filtering/placement/thumbnails, |
75 | | -properties, and collision submodules. Properties and collision must share |
76 | | -selection projection and object-field mapping rather than duplicate conversion |
77 | | -logic. |
| 50 | +### Split the E2ERun monolith |
78 | 51 |
|
79 | | -At the same time, complete TODO #1 in [todo.md](todo.md): replace generic |
80 | | -JSON-based Area/Feature/Unit object commands with concrete typed commands, and |
81 | | -cache static object-field descriptors. This makes Objects safer and smaller to |
82 | | -review in stable. |
| 52 | +`tools/e2e/runner.py` (~1150 lines) into engine-session lifecycle, input, |
| 53 | +assertions + command-log reading, screenshots/artifacts, and reporting. Semantic |
| 54 | +UI coordinates already live in `scenarios/geometry.py`. |
83 | 55 |
|
84 | | -### 5. Split project persistence from the Project feature |
| 56 | +### Finish the panels/ toolkit |
85 | 57 |
|
86 | | -Extract project paths plus save/load/export registrations into a neutral |
87 | | -project-IO/workspace module. Leave scenario metadata, archive export, reload, |
88 | | -map info, and project-editor functionality in `project/`. This is TODO #16 and |
89 | | -prevents each saving feature from depending on the whole Project feature. |
| 58 | +- `brush.rs` is misnamed: it is the brush-editor action-strip UI plus a couple |
| 59 | + of asset-field helpers, not "a brush". Rename to reflect that it is UI (e.g. an |
| 60 | + action-strip control) — it must stay in the UI layer, because it renders RML |
| 61 | + and moving it out reintroduces the `states → panel` dependency. |
| 62 | +- `modal_stack` enumerates concrete dialogs as fields |
| 63 | + (`new_project: NewProjectDialog`). If it is meant to be the app-wide modal |
| 64 | + concept, dialogs should self-register (inventory, like editors) rather than be |
| 65 | + listed. Also review what `modal_stack` actually does. |
| 66 | +- `tokens.rcss`: a single source for colours/spacing/sizes needs build-time |
| 67 | + substitution, because RmlUi's RCSS has no variables. |
90 | 68 |
|
91 | | -### 6. Split the texture editor by ownership |
| 69 | +### Loud duplicate registration |
92 | 70 |
|
93 | | -Move material discovery/parsing into `textures`, separate saved-brush state, and |
94 | | -leave a thin UI composition layer. Texture/material ownership must not be |
95 | | -trapped in one large panel editor before the Textures domain is transferred. |
| 71 | +Duplicate model-factory registration should fail loudly, as duplicate command |
| 72 | +registration already does. |
96 | 73 |
|
97 | | -### 7. Establish a shared native RmlUi theme |
| 74 | +## Do not rewrite first |
98 | 75 |
|
99 | | -Centralize common text, color, border, opacity, button, toggle, dropdown, and |
100 | | -tooltip rules. Keep only document-specific layout in panel, Chonsole, and |
101 | | -developer-console stylesheets. This prevents future stable slices from changing |
102 | | -three visual systems for one control correction. |
103 | | - |
104 | | -### 8. Separate E2E runner responsibilities |
105 | | - |
106 | | -Split the `E2ERun` monolith into engine session lifecycle, input, assertions and |
107 | | -command-log reading, screenshots/artifacts, and reporting. Keep semantic UI |
108 | | -coordinates centralized in `scenarios/geometry.py`; that file already fixes the |
109 | | -previous scattered-coordinate problem. |
110 | | - |
111 | | -## Do not rewrite these first |
112 | | - |
113 | | -- Chonsole is already sensibly divided into catalog, completion, input, history, |
114 | | - model, and views. Transfer it as one domain after shared RmlUi lifecycle work. |
115 | | -- Developer console has a useful actions/log/metrics/manager/view split. Limit |
116 | | - restructuring to common lifecycle and theme extraction. |
| 76 | +- Chonsole (catalog/completion/input/history/model/views) and the developer |
| 77 | + console (actions/log/metrics/manager/view) are already sensibly divided; |
| 78 | + transfer each as one domain after shared RmlUi lifecycle work. |
117 | 79 | - Do not replace the command system wholesale; reconcile only its required WIP |
118 | 80 | delta against stable. |
119 | | - |
120 | | -## Completion criteria |
121 | | - |
122 | | -Before the first stable transfer: |
123 | | - |
124 | | -1. Feature UI no longer lives in `panels/editors`. |
125 | | -2. `states` no longer imports panel UI/rendering. |
126 | | -3. Project IO is independent of the Project feature. |
127 | | -4. The shared native theme has a single source of truth. |
128 | | -5. The E2E harness and verification ledger identify a feature's tests without |
129 | | - relying on obsolete phase documents. |
130 | | -6. Duplicate model-factory registration fails loudly, as duplicate command |
131 | | - registration already does. |
0 commit comments