mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Add the 'Basic Brush' node and replace the legacy Brush tool implementation with it (#4469)
* Draw raster images with pad extension instead of repeat * Add the GPU basic brush renderer * Rework the brush tool around the GPU basic brush * Remove the CPU brush implementation
This commit is contained in:
@@ -2,7 +2,6 @@ use super::DocumentNode;
|
||||
use crate::application_io::PlatformEditorApi;
|
||||
use crate::application_io::resource::Resource;
|
||||
use crate::proto::{Any as DAny, FutureAny};
|
||||
use brush_nodes::brush_stroke::{BrushStroke, BrushTrace};
|
||||
use brush_nodes::{BrushCache, Stroke};
|
||||
use core_types::color::SRGBA8;
|
||||
use core_types::list::{Item, List, NodeIdPath};
|
||||
@@ -94,10 +93,6 @@ macro_rules! tagged_value {
|
||||
/// (Old documents stored flat stops, a tuple list, or the ancient full `Gradient` struct under the legacy `"Gradient"` tag, all routed by `deserialize_tagged_value_with_legacy_migration`.)
|
||||
#[serde(alias = "Gradient", alias = "GradientTable", alias = "GradientPositions", alias = "GradientStops")]
|
||||
GradientRamp(GradientRamp),
|
||||
/// Stored compactly as a `Vec<BrushStroke>`, materializes as the single-value `Item<BrushTrace>` at runtime via `to_dynany`/`to_any`. Aliases recover legacy on-disk shapes.
|
||||
#[serde(deserialize_with = "brush_nodes::migrations::migrate_to_brush_strokes")] // TODO: Eventually remove this document upgrade code
|
||||
#[serde(alias = "BrushStrokeTable")]
|
||||
BrushStrokes(Vec<BrushStroke>),
|
||||
Strokes(Vec<Stroke>),
|
||||
BrushCache(BrushCache),
|
||||
// =======================
|
||||
@@ -142,7 +137,6 @@ macro_rules! tagged_value {
|
||||
Self::DashPattern(lengths) => lengths.cache_hash(state),
|
||||
Self::BoxCorners(values) => values.cache_hash(state),
|
||||
Self::GradientRamp(ramp) => ramp.cache_hash(state),
|
||||
Self::BrushStrokes(strokes) => strokes.cache_hash(state),
|
||||
Self::Strokes(strokes) => strokes.cache_hash(state),
|
||||
Self::BrushCache(cache) => cache.cache_hash(state),
|
||||
// =======================
|
||||
@@ -207,7 +201,6 @@ macro_rules! tagged_value {
|
||||
Self::DashPattern(lengths) => Box::new(Item::new_from_element(DashPattern::from(lengths))),
|
||||
Self::BoxCorners(values) => Box::new(Item::new_from_element(BoxCorners::from(values))),
|
||||
Self::GradientRamp(ramp) => Box::new(Item::<Gradient>::from(ramp)),
|
||||
Self::BrushStrokes(strokes) => Box::new(core_types::list::Item::new_from_element(BrushTrace::from(strokes))),
|
||||
Self::Strokes(strokes) => {
|
||||
let list: List<Stroke> = strokes.into_iter().map(core_types::list::Item::new_from_element).collect();
|
||||
Box::new(list)
|
||||
@@ -275,7 +268,6 @@ macro_rules! tagged_value {
|
||||
Self::DashPattern(lengths) => Arc::new(Item::new_from_element(DashPattern::from(lengths))),
|
||||
Self::BoxCorners(values) => Arc::new(Item::new_from_element(BoxCorners::from(values))),
|
||||
Self::GradientRamp(ramp) => Arc::new(Item::<Gradient>::from(ramp)),
|
||||
Self::BrushStrokes(strokes) => Arc::new(core_types::list::Item::new_from_element(BrushTrace::from(strokes))),
|
||||
Self::Strokes(strokes) => {
|
||||
let list: List<Stroke> = strokes.into_iter().map(core_types::list::Item::new_from_element).collect();
|
||||
Arc::new(list)
|
||||
@@ -309,7 +301,6 @@ macro_rules! tagged_value {
|
||||
Self::DashPattern(_) => item!(DashPattern),
|
||||
Self::BoxCorners(_) => item!(BoxCorners),
|
||||
Self::GradientRamp(_) => item!(Gradient),
|
||||
Self::BrushStrokes(_) => item!(BrushTrace),
|
||||
Self::Strokes(_) => list!(Stroke),
|
||||
Self::BrushCache(_) => item!(BrushCache),
|
||||
// =======================
|
||||
@@ -350,8 +341,6 @@ macro_rules! tagged_value {
|
||||
x if x == TypeId::of::<Item<BoxCorners>>() => Ok(TaggedValue::BoxCorners(downcast::<Item<BoxCorners>>(input).unwrap().into_element().0.iter_element_values().copied().collect())),
|
||||
x if x == TypeId::of::<Gradient>() => Ok(TaggedValue::GradientRamp(GradientRamp::from(*downcast::<Gradient>(input).unwrap()))),
|
||||
x if x == TypeId::of::<Item<Gradient>>() => Ok(TaggedValue::GradientRamp(GradientRamp::from(&*downcast::<Item<Gradient>>(input).unwrap()))),
|
||||
x if x == TypeId::of::<Vec<BrushStroke>>() => Ok(TaggedValue::BrushStrokes(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<Item<BrushTrace>>() => Ok(TaggedValue::BrushStrokes(downcast::<Item<BrushTrace>>(input).unwrap().into_element().0.iter_element_values().cloned().collect())),
|
||||
x if x == TypeId::of::<List<Stroke>>() => Ok(TaggedValue::Strokes(downcast::<List<Stroke>>(input).unwrap().into_iter().map(Item::into_element).collect())),
|
||||
x if x == TypeId::of::<Item<BrushCache>>() => Ok(TaggedValue::BrushCache(downcast::<Item<BrushCache>>(input).unwrap().into_element())),
|
||||
// =======================
|
||||
@@ -386,8 +375,6 @@ macro_rules! tagged_value {
|
||||
x if x == TypeId::of::<Item<BoxCorners>>() => Ok(TaggedValue::BoxCorners(input.downcast_ref::<Item<BoxCorners>>().unwrap().element().0.iter_element_values().copied().collect())),
|
||||
x if x == TypeId::of::<Gradient>() => Ok(TaggedValue::GradientRamp(GradientRamp::from(input.downcast_ref::<Gradient>().unwrap()))),
|
||||
x if x == TypeId::of::<Item<Gradient>>() => Ok(TaggedValue::GradientRamp(GradientRamp::from(input.downcast_ref::<Item<Gradient>>().unwrap()))),
|
||||
x if x == TypeId::of::<Vec<BrushStroke>>() => Ok(TaggedValue::BrushStrokes(input.downcast_ref::<Vec<BrushStroke>>().unwrap().clone())),
|
||||
x if x == TypeId::of::<Item<BrushTrace>>() => Ok(TaggedValue::BrushStrokes(input.downcast_ref::<Item<BrushTrace>>().unwrap().element().0.iter_element_values().cloned().collect())),
|
||||
x if x == TypeId::of::<List<Stroke>>() => Ok(TaggedValue::Strokes(input.downcast_ref::<List<Stroke>>().unwrap().iter_element_values().cloned().collect())),
|
||||
x if x == TypeId::of::<Item<BrushCache>>() => Ok(TaggedValue::BrushCache(input.downcast_ref::<Item<BrushCache>>().unwrap().element().clone())),
|
||||
// =======================
|
||||
@@ -417,7 +404,6 @@ macro_rules! tagged_value {
|
||||
if name == std::any::type_name::<DashPattern>() { return Some(TaggedValue::DashPattern(Vec::new())) }
|
||||
if name == std::any::type_name::<BoxCorners>() { return Some(TaggedValue::BoxCorners(Vec::new())) }
|
||||
$( if name == std::any::type_name::<$ty>() { return Some(TaggedValue::$identifier(Default::default())) } )*
|
||||
if name == std::any::type_name::<BrushTrace>() { return Some(TaggedValue::BrushStrokes(Vec::new())) }
|
||||
if name == std::any::type_name::<List<Stroke>>() { return Some(TaggedValue::Strokes(Vec::new())) }
|
||||
if name == std::any::type_name::<BrushCache>() { return Some(TaggedValue::BrushCache(Default::default())) }
|
||||
// Unranked types without a variant route through `TypeDefault`, with `to_dynany`/`to_any` constructing the actual default at execution time
|
||||
@@ -475,7 +461,6 @@ macro_rules! tagged_value {
|
||||
Self::DashPattern(lengths) => format!("DashPattern({lengths:?})"),
|
||||
Self::BoxCorners(values) => format!("BoxCorners({values:?})"),
|
||||
Self::GradientRamp(ramp) => format!("GradientRamp({ramp:?})"),
|
||||
Self::BrushStrokes(strokes) => format!("BrushStrokes({strokes:?})"),
|
||||
Self::Strokes(strokes) => format!("Strokes({strokes:?})"),
|
||||
Self::BrushCache(cache) => format!("{cache:?}"),
|
||||
// =======================
|
||||
|
||||
Reference in New Issue
Block a user