Implement the Brush tool (#1099)

* Implement Brush Node

* Add color Input

* Add VectorPointsNode

* Add Erase Node

* Adapt compilation infrastructure to allow non Image Frame inputs

* Remove debug output from TransformNode

* Fix transform calculation

* Fix Blending by making the brush texture use associated alpha

* Code improvements and UX polish

* Rename Opacity to Flow

* Add erase option to brush node + fix freehand tool

* Fix crash

* Revert erase implementation

* Fix flattening id calculation

* Fix some transformation issues

* Fix changing the pivot location

* Fix vector data modify bounds

* Minor fn name cleanup

* Fix some tests

* Fix tests

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
Co-authored-by: hypercube <0hypercube@gmail.com>
This commit is contained in:
Dennis Kobert
2023-04-11 10:35:21 +02:00
committed by Keavon Chambers
co-authored by Keavon Chambers hypercube
parent 758f757775
commit 589ff9a2d3
36 changed files with 1527 additions and 406 deletions
+26 -3
View File
@@ -239,12 +239,11 @@ fn brighten_color_node(color: Color, brightness: f32) -> Color {
}
#[derive(Debug)]
pub struct ForEachNode<Iter, MapNode> {
pub struct ForEachNode<MapNode> {
map_node: MapNode,
_iter: PhantomData<Iter>,
}
#[node_macro::node_fn(ForEachNode<_Iter>)]
#[node_macro::node_fn(ForEachNode)]
fn map_node<_Iter: Iterator, MapNode>(input: _Iter, map_node: &'any_input MapNode) -> ()
where
MapNode: for<'any_input> Node<'any_input, _Iter::Item, Output = ()> + 'input,
@@ -359,6 +358,15 @@ mod image {
data: Vec::new(),
}
}
pub fn new(width: u32, height: u32, color: Color) -> Self {
Self {
width,
height,
data: vec![color; (width * height) as usize],
}
}
pub fn as_slice(&self) -> ImageSlice {
ImageSlice {
width: self.width,
@@ -366,6 +374,15 @@ mod image {
data: self.data.as_slice(),
}
}
pub fn get_mut(&mut self, x: u32, y: u32) -> Option<&mut Color> {
self.data.get_mut((y * self.width + x) as usize)
}
pub fn get(&self, x: u32, y: u32) -> Option<&Color> {
self.data.get((y * self.width + x) as usize)
}
/// Generate Image from some frontend image data (the canvas pixels as u8s in a flat array)
pub fn from_image_data(image_data: &[u8], width: u32, height: u32) -> Self {
let data = image_data.chunks_exact(4).map(|v| Color::from_rgba8(v[0], v[1], v[2], v[3])).collect();
@@ -451,6 +468,12 @@ mod image {
}
}
impl AsRef<ImageFrame> for ImageFrame {
fn as_ref(&self) -> &ImageFrame {
self
}
}
impl Hash for ImageFrame {
fn hash<H: Hasher>(&self, state: &mut H) {
self.image.hash(state);