# Plan: Brush Editor — Dynamics, Real Preview, Scrollable Panels ## Goal Extend the existing Krita-style brush editor in `hcie-egui-app/crates/hcie-gui-egui/src/app/brush_editor.rs` so it exposes real brush dynamics, shows an accurate engine-rendered preview, and keeps all dock panels scrollable by mouse wheel / pan without visible scrollbars. ## Current State - A basic brush editor modal exists with four categories: **Brush Tip**, **Dynamics**, **Color**, **Texture**. - `BrushConfig` (in `hcie-protocol/src/tools.rs`) exposes only `size`, `opacity`, `hardness`, `flow`, `spacing`, `style`, `blend_mode`, `cyclic_color`, `cyclic_speed`, `color_variant`, `variant_amount`, `density`. - Engine `BrushTip` already has `jitter_amount`, `scatter_amount`, `angle`, `roundness`, but the GUI never sets them (canvas code hard-codes `0.0` / `1.0`). - Preview is procedural (`brushes_panel::draw_brush_preview`) and does not reflect actual engine output. - Dock panels vary: some use `ScrollArea`, some do not; scrollbars are visible. ## Decisions ### 1. New brush dynamics fields Add to `hcie-protocol/src/tools.rs` `BrushConfig`: ```rust pub jitter_amount: f32, pub scatter_amount: f32, pub angle: f32, pub roundness: f32, pub drawing_angle: bool, pub rotation_random: f32, pub time_enabled: bool, pub time_size_start: f32, pub time_size_end: f32, pub time_opacity_start: f32, pub time_opacity_end: f32, pub time_angle_start: f32, pub time_angle_end: f32, ``` Defaults: `0.0`, `0.0`, `0.0`, `1.0`, `false`, `0.0`, `false`, `1.0/1.0/1.0/1.0/0.0/0.0`. ### 2. GUI controls - **Brush Tip panel**: keep `Diameter`, `Hardness`, `Spacing`, `Style`, `Blend Mode`; add **Angle**, **Roundness**, **Drawing Angle** checkbox, **Rotation Random**. - **Dynamics panel**: keep `Opacity`, `Flow`, `Pressure Curve` placeholder; add **Jitter**, **Scatter**. - **Color panel**: keep `Color Variant`, `Cyclic Color`; add a **Time** subsection with checkbox and start/end sliders for `size`, `opacity`, `angle`. - Every slider pairs with a right-aligned `DragValue` so mouse users can click/type exact values. - Angles displayed and edited in **degrees**, stored in **radians**. ### 3. Engine wiring - `hcie-egui-app/crates/hcie-gui-egui/src/canvas/mod.rs`: when building `BrushTip`, copy `jitter_amount`, `scatter_amount`, `angle` (converted to radians), `roundness` from `state.tool_configs.brush`. - `hcie-brush-engine/src/lib.rs`: update `generate_brush_stamp` and dab dispatchers so that: - `drawing_angle == true` overrides `angle` with the stroke segment direction. - `rotation_random` adds a per-dab random offset to the effective angle. - `roundness` scales the stamp along the effective angle (elliptical dab). - `hcie-engine-api/src/stroke_brush.rs`: apply `time_*` interpolation using accumulated stroke distance (`brush_accumulated_dist`) before passing size/opacity/angle to the dab functions. Reset at stroke start (`begin_stroke`). ### 4. Real preview - Add `Engine::render_brush_preview(&self, width, height, tip, color, stroke_points) -> Vec` in `hcie-engine-api/src/lib.rs`. - It creates a temporary 1-layer document, draws the supplied stroke points, composites, and returns RGBA pixels. - `brush_editor.rs` calls this on every significant parameter change (when `brush_editor_instant_preview` is true), caches the texture, and draws it in the preview area instead of the procedural function. - Guard with a small debounce to avoid 4K-preview cost. ### 5. Scrollable panels - Create a helper `scrollable_panel(ui, id, contents)` in a new file `hcie-egui-app/crates/hcie-gui-egui/src/app/scrollable_panel.rs`. - It wraps `egui::ScrollArea::vertical().always_show_scroll(false)` and implements drag-to-pan by tracking pointer delta over the content rect when the left button is held and no widget is being dragged. - Apply the helper to every dock panel body: - `brushes_panel::show_brushes_ui` - `panels.rs` tool-property bodies (Tools, Layers, History, Properties, etc.) - `brush_editor.rs` right-hand settings area - Keep existing `ScrollArea` calls but switch them to the helper so behavior is consistent. ## Affected Boundaries (Locked Crates) The following crates are normally locked by `hcie-guard`; the implementation agent must run `unlock.sh `, edit, then `lock.sh `: - `hcie-protocol/src/tools.rs` — `BrushConfig` fields - `hcie-engine-api/src/lib.rs` — new public preview API - `hcie-engine-api/src/stroke_brush.rs` — time interpolation - `hcie-brush-engine/src/lib.rs` — drawing angle / rotation / roundness behavior GUI-only files (open to agent edits): - `hcie-egui-app/crates/hcie-gui-egui/src/app/brush_editor.rs` - `hcie-egui-app/crates/hcie-gui-egui/src/app/brushes_panel.rs` - `hcie-egui-app/crates/hcie-gui-egui/src/app/panels.rs` - `hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rs` - `hcie-egui-app/crates/hcie-gui-egui/src/canvas/mod.rs` ## Task Order 1. Extend `BrushConfig` in `hcie-protocol` and rebuild engine. 2. Implement engine preview API. 3. Implement `drawing_angle`, `rotation_random`, `roundness` in `hcie-brush-engine`. 4. Implement time interpolation in `hcie-engine-api/src/stroke_brush.rs`. 5. Wire new fields from GUI config to `BrushTip` in `canvas/mod.rs`. 6. Extend `brush_editor.rs` UI (new sliders, real preview, scrollable right panel). 7. Implement `scrollable_panel` helper and apply to all dock panels. 8. Run `cargo test -p hcie-engine-api --test visual_regression` and `cargo test -p hcie-engine-api --test performance_stroke_4k`. 9. Lock affected engine crates. 10. Capture screenshots of brush editor and each scrollable panel. ## Validation - Visual regression tests (`visual_regression`) must still pass. - Performance regression benchmark (`performance_stroke_4k`) must not regress beyond 5%. - Brush editor preview updates within 200 ms of parameter change. - All dock panels scroll by mouse wheel and pan-drag without visible scrollbars. ## Risks - `hcie-brush-engine` angle/roundness changes can alter default brush appearance if defaults are wrong; test with `visual_regression`. - Real preview allocates a temporary engine/document per frame; debounce/caching is mandatory. - Locked crate modifications require `unlock.sh` / `lock.sh` and possible terminal password prompt. ## Open Questions - None remaining; user confirmed all decisions.