Files
hcie-rust-v3.05/.kilo/plans/1784597466971-vector-state-management-fix.md
T
phantom e5d899d72d feat: add watercolor brush category with presets and splat renderer
- Implemented a new crate `hcie-watercolor-brushes` containing watercolor brush presets and a procedural splat preview renderer.
- Integrated watercolor brushes into the iced GUI's Brushes panel, adding a new category for watercolor brushes.
- Updated the `BrushCategory` enum to include `Watercolor` and modified the rendering logic to display watercolor presets.
- Added functionality to generate watercolor splat thumbnails using a noise-based algorithm.
- Ensured that existing brush styles and engine crates remain unmodified, adhering to project constraints.
2026-07-21 06:07:12 +03:00

181 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Watercolor Brush Category — Implementation Plan
## Goal
Add a new **Watercolor** brush category to the iced GUI's Brushes panel. Each brush has a watercolor-splat preview (not the standard sine-wave stroke). The brushes simulate realistic watercolor effects. Implemented as a new crate with zero modification to existing brush/engine crates.
## Architecture Overview
### Existing brush flow
1. `hcie-brush-engine` defines `BrushStyle` enum (33 variants including `Watercolor`) and `BrushPreset` struct
2. `hcie-engine-api` re-exports `BrushPreset` and provides `draw_specialized_stroke` → dispatches to `draw_watercolor_brush` for `BrushStyle::Watercolor`
3. `hcie-iced-gui/src/panels/brushes.rs` defines `BrushCategory` enum, `BRUSH_STYLES` static array, and `generate_brush_preview()` for thumbnails
4. When a preset is selected → `Message::BrushPresetSelected(preset)` → sets `tool_state.brush_style`, `brush_size`, `brush_opacity`, `brush_hardness`, `brush_spacing`, `active_brush_preset`
### Key constraint
Engine crates (`hcie-brush-engine`, `hcie-protocol`, `hcie-engine-api`, `hcie-draw`) are **locked** — agents must not modify them. The new crate lives in the GUI layer and reuses the engine's existing `BrushStyle::Watercolor` rendering path.
### New crate strategy
- Define watercolor presets using existing `BrushPreset` (from `hcie-engine-api`) with `style: BrushStyle::Watercolor`
- Provide a **watercolor splat preview renderer** that generates RGBA pixels for thumbnails
- The brushes panel integrates the new crate's presets under a "Watercolor" category tab
- Actual drawing uses the engine's existing watercolor brush rendering — no engine changes needed
---
## Step 1: Create the new crate `hcie-watercolor-brushes`
**Path:** `hcie-iced-app/crates/hcie-watercolor-brushes/`
### `Cargo.toml`
```toml
[package]
name = "hcie-watercolor-brushes"
version.workspace = true
edition.workspace = true
[dependencies]
hcie-engine-api = { path = "../../../hcie-engine-api" }
```
### `src/lib.rs` — Presets + Preview Renderer
Exports:
- `pub fn watercolor_presets() -> Vec<BrushPreset>` — returns 8 watercolor brush presets
- `pub fn render_watercolor_splat(style: BrushStyle, base_color: [u8; 3]) -> Vec<u8>` — generates 64×64 RGBA watercolor splat preview
#### Presets (8 brushes)
| ID | Name | Size | Opacity | Hardness | Spacing | Description |
|----|------|------|---------|----------|---------|-------------|
| `wc_wash` | Watercolor Wash | 80 | 0.25 | 0.0 | 0.08 | Large, transparent wash |
| `wc_wet` | Wet Watercolor | 60 | 0.35 | 0.0 | 0.06 | Medium, wet-on-wet |
| `wc_dry` | Dry Brush | 30 | 0.70 | 0.6 | 0.12 | Small, textured, high opacity |
| `wc_glaze` | Glazing | 50 | 0.15 | 0.0 | 0.10 | Very transparent, layered |
| `wc_splat` | Splatter | 40 | 0.50 | 0.2 | 0.30 | Scattered droplets |
| `wc_bleed` | Color Bleed | 70 | 0.30 | 0.0 | 0.07 | Heavy diffusion edges |
| `wc_grain` | Granulation | 45 | 0.40 | 0.3 | 0.09 | Visible paper grain texture |
| `wc_bloom` | Bloom | 90 | 0.20 | 0.0 | 0.05 | Soft, blooming edges |
All use `BrushStyle::Watercolor` as the engine style — the engine's existing `draw_watercolor_brush` handles the actual stroke rendering.
#### Watercolor Splat Preview Algorithm (64×64 RGBA)
The splat is generated procedurally using multi-octave value noise:
1. **Base shape:** Radial gradient from center, `alpha = (1 - dist/radius)^1.5`
2. **Edge displacement:** Displace the radius at each angle using 3-octave value noise → irregular organic boundary
3. **Multiple layers:** 3-5 overlapping semi-transparent blobs at slightly offset positions
4. **Color variation:** Shift hue slightly per layer (±10°) for color separation
5. **Granulation:** High-frequency noise modulates alpha in the outer 40% of the radius
6. **Wet edge:** Slightly darker/more saturated ring near the boundary (wet-edge accumulation effect)
The noise function is a simple hash-based value noise (no external deps):
```rust
fn value_noise(x: f32, y: f32) -> f32 {
// hash-based pseudo-random, returns 0.0..1.0
}
fn fbm(x: f32, y: f32, octaves: u32) -> f32 {
// fractal Brownian motion using value_noise
}
```
---
## Step 2: Register the crate in the workspace
**File:** `Cargo.toml` (workspace root)
Add to `[workspace] members`:
```toml
"hcie-iced-app/crates/hcie-watercolor-brushes",
```
---
## Step 3: Add `hcie-watercolor-brushes` dependency to `hcie-iced-gui`
**File:** `hcie-iced-app/crates/hcie-iced-gui/Cargo.toml`
Add:
```toml
hcie-watercolor-brushes = { path = "../hcie-watercolor-brushes" }
```
---
## Step 4: Update the Brushes panel
**File:** `hcie-iced-app/crates/hcie-iced-gui/src/panels/brushes.rs`
### 4a. Add `Watercolor` variant to `BrushCategory`
```rust
pub enum BrushCategory {
All,
Drawing,
Painting,
Watercolor, // ← NEW
Effects,
Custom,
Imported,
}
```
### 4b. Update `category_matches_style` for the new variant
```rust
BrushCategory::Watercolor => style_category == BrushCategory::Watercolor,
```
### 4c. Add Watercolor tab to the category tabs array
```rust
(BrushCategory::Watercolor, "Watercolor", "icons/brush.svg"),
```
### 4d. Render watercolor presets when Watercolor category is active
When `active_category == BrushCategory::Watercolor`:
- Call `hcie_watercolor_brushes::watercolor_presets()` to get the preset list
- For each preset, call `hcie_watercolor_brushes::render_watercolor_splat(...)` for the thumbnail
- Render as a grid (same 2-column layout as existing brushes)
- Each cell sends `Message::BrushPresetSelected(preset)` on click
### 4e. Update `view` function signature
The function already accepts `imported_presets: &[BrushPreset]`. No signature change needed — the watercolor presets are fetched internally from the new crate.
### 4f. Update test `catalog_contains_every_engine_brush_style`
The test asserts `BRUSH_STYLES.len() == 34`. This doesn't change (watercolor presets are separate from `BRUSH_STYLES`). The test remains valid.
---
## Step 5: Add "Watercolor" to the egui GUI category filter (optional, for parity)
**File:** `hcie-egui-app/crates/hcie-gui-egui/src/app/tools/brushes_panel.rs`
Add "Watercolor" to the categories array and update `matches_style_category` to map it to `BrushStyle::Watercolor`. This is a minimal change for parity — the watercolor presets themselves would need separate integration in the egui panel if desired.
**Note:** This step is optional for the initial implementation. The user's request focuses on the iced GUI.
---
## Files Changed
| File | Change |
|------|--------|
| `hcie-iced-app/crates/hcie-watercolor-brushes/Cargo.toml` | **New** — crate manifest |
| `hcie-iced-app/crates/hcie-watercolor-brushes/src/lib.rs` | **New** — presets + splat renderer |
| `Cargo.toml` (workspace root) | Add member `hcie-iced-app/crates/hcie-watercolor-brushes` |
| `hcie-iced-app/crates/hcie-iced-gui/Cargo.toml` | Add dependency `hcie-watercolor-brushes` |
| `hcie-iced-app/crates/hcie-iced-gui/src/panels/brushes.rs` | Add `Watercolor` category, tab, and grid rendering |
**Files NOT modified:** All engine crates (`hcie-brush-engine`, `hcie-protocol`, `hcie-engine-api`, `hcie-draw`), existing brush definitions, existing `BRUSH_STYLES` array.
---
## Validation
1. `cargo check -p hcie-watercolor-brushes` — new crate compiles
2. `cargo check -p hcie-iced-gui` — GUI compiles with new dependency
3. `cargo test -p hcie-iced-gui` — all existing tests pass
4. `cargo test -p hcie-watercolor-brushes` — new crate tests pass
5. `cargo test --test feature_scorecard` — scorecard passes
6. Visual: launch the app, open Brushes panel, click "Watercolor" tab → 8 watercolor presets with splat previews appear
7. Visual: select a watercolor brush → draw on canvas → realistic watercolor stroke rendered
8. Regression: existing Drawing/Painting/Effects brushes unchanged