Files
hcie-rust-v3.05/hcie-iced-app/crates/hcie-digital-brushes/src/lib.rs
T
Your Name e509def0b2
mandatory-regression-gate / deterministic-tests (push) Has been cancelled
mandatory-regression-gate / protected-performance-path (push) Has been cancelled
feat: Add digital, dry, ink, and paint brush presets; implement regression testing hooks
- Introduced new crates for digital brushes, dry media brushes, ink brushes, and paint brushes, each containing various presets.
- Updated the menus to include "Paste Special" and "Paste as New Layer" options.
- Enhanced the feature scorecard tests to validate selection texture encoding.
- Added a regression gate workflow for automated testing on push and pull requests.
- Implemented Git hooks for pre-commit checks to ensure code formatting and run tests before commits.
- Created a settings file for local configurations.
2026-07-23 02:28:49 +03:00

152 lines
4.4 KiB
Rust

//! Digital-native raster, blend, texture, FX, and vector brush descriptors.
//!
//! **Purpose:** Separates digital-only tools from traditional-media catalogs. **Logic & Workflow:**
//! Raster tools return engine `BrushPreset` values; vector tools use a distinct descriptor so they
//! are never misrouted through the raster brush engine. **Side Effects / Dependencies:** None.
use hcie_engine_api::brush::{BrushStyle, BrushTip};
use hcie_engine_api::BrushPreset;
/// Vector-path brush metadata consumed by GUI vector tooling rather than raster drawing.
#[derive(Debug, Clone, PartialEq)]
pub struct VectorBrushPreset {
/// Stable preset identifier.
pub id: &'static str,
/// User-facing preset name.
pub name: &'static str,
/// Default path stroke width.
pub width: f32,
/// Whether pressure changes path width.
pub pressure_width: bool,
/// Input-path smoothing strength in `0..=1`.
pub smoothing: f32,
}
/// Builds one digital raster preset.
fn preset(id: &str, name: &str, category: &str, tip: BrushTip) -> BrushPreset {
BrushPreset {
id: id.into(),
name: name.into(),
category: category.into(),
style: tip.style,
tip,
pressure_size: true,
pressure_opacity: true,
pressure_flow: true,
jitter_position: 0.0,
jitter_angle: 0.0,
}
}
/// Returns digital raster, blend, texture, and FX presets.
pub fn digital_presets() -> Vec<BrushPreset> {
vec![
preset(
"digital_pixel",
"Pixel / Raster Brush",
"Digital Raster",
BrushTip {
style: BrushStyle::HardRound,
size: 8.0,
opacity: 1.0,
hardness: 1.0,
spacing: 0.05,
..BrushTip::default()
},
),
preset(
"digital_smudge",
"Smudge / Blender",
"Digital Blend",
BrushTip {
style: BrushStyle::Blender,
size: 40.0,
opacity: 0.65,
hardness: 0.0,
spacing: 0.05,
..BrushTip::default()
},
),
preset(
"digital_stamp",
"Stamp / Texture",
"Digital Texture",
BrushTip {
style: BrushStyle::Texture,
size: 48.0,
opacity: 0.9,
hardness: 0.8,
spacing: 0.35,
jitter_amount: 0.3,
scatter_amount: 0.6,
rotation_random: 0.5,
density: 0.7,
..BrushTip::default()
},
),
preset(
"digital_fx_glow",
"FX Glow",
"Digital FX",
BrushTip {
style: BrushStyle::Glow,
size: 30.0,
opacity: 0.8,
hardness: 0.0,
spacing: 0.04,
..BrushTip::default()
},
),
preset(
"digital_fx_particles",
"FX Particles",
"Digital FX",
BrushTip {
style: BrushStyle::Spray,
size: 60.0,
opacity: 0.7,
hardness: 0.5,
spacing: 0.2,
spray_particle_size: 2.0,
spray_density: 120,
..BrushTip::default()
},
),
]
}
/// Returns vector brush descriptors for the vector path subsystem.
pub fn vector_brush_presets() -> Vec<VectorBrushPreset> {
vec![
VectorBrushPreset {
id: "digital_vector_clean",
name: "Clean Vector Brush",
width: 4.0,
pressure_width: true,
smoothing: 0.65,
},
VectorBrushPreset {
id: "digital_vector_ink",
name: "Vector Ink Brush",
width: 7.0,
pressure_width: true,
smoothing: 0.35,
},
]
}
#[cfg(test)]
mod tests {
use super::{digital_presets, vector_brush_presets};
/// Ensures vector tools remain separate from raster brush presets.
#[test]
fn digital_catalog_separates_raster_and_vector_tools() {
assert_eq!(digital_presets().len(), 5);
assert_eq!(vector_brush_presets().len(), 2);
assert!(digital_presets()
.iter()
.all(|preset| preset.style == preset.tip.style));
}
}