Make the node graph use Table<GradientStops> instead of GradientStops (#3837)
* Switch from GradientStops to Table<GradientStops> in all nodes * Remove TaggedValue::ColorNotInTable * Fix bug Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Add migrations * Fix default gradient on empty table * Update demo artwork --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
parent
81c73d11ff
commit
f1cbc4b396
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -214,19 +214,19 @@ pub(crate) fn property_from_type(
|
||||||
Some(x) if x == TypeId::of::<String>() => text_widget(default_info).into(),
|
Some(x) if x == TypeId::of::<String>() => text_widget(default_info).into(),
|
||||||
Some(x) if x == TypeId::of::<DVec2>() => vec2_widget(default_info, "X", "Y", "", None, false),
|
Some(x) if x == TypeId::of::<DVec2>() => vec2_widget(default_info, "X", "Y", "", None, false),
|
||||||
Some(x) if x == TypeId::of::<DAffine2>() => transform_widget(default_info, &mut extra_widgets),
|
Some(x) if x == TypeId::of::<DAffine2>() => transform_widget(default_info, &mut extra_widgets),
|
||||||
Some(x) if x == TypeId::of::<Color>() => color_widget(default_info, ColorInput::default()),
|
|
||||||
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(default_info, ColorInput::default()),
|
|
||||||
// ==========================
|
// ==========================
|
||||||
// PRIMITIVE COLLECTION TYPES
|
// PRIMITIVE COLLECTION TYPES
|
||||||
// ==========================
|
// ==========================
|
||||||
Some(x) if x == TypeId::of::<Vec<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
|
Some(x) if x == TypeId::of::<Vec<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
|
||||||
Some(x) if x == TypeId::of::<Vec<DVec2>>() => array_of_vec2_widget(default_info, TextInput::default()).into(),
|
Some(x) if x == TypeId::of::<Vec<DVec2>>() => array_of_vec2_widget(default_info, TextInput::default()).into(),
|
||||||
|
// ===========
|
||||||
|
// TABLE TYPES
|
||||||
|
// ===========
|
||||||
|
Some(x) if x == TypeId::of::<Table<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
||||||
|
Some(x) if x == TypeId::of::<Table<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
||||||
// ============
|
// ============
|
||||||
// STRUCT TYPES
|
// STRUCT TYPES
|
||||||
// ============
|
// ============
|
||||||
Some(x) if x == TypeId::of::<Table<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
|
||||||
Some(x) if x == TypeId::of::<Table<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
|
||||||
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
|
||||||
Some(x) if x == TypeId::of::<Font>() => font_widget(default_info),
|
Some(x) if x == TypeId::of::<Font>() => font_widget(default_info),
|
||||||
Some(x) if x == TypeId::of::<Curve>() => curve_widget(default_info),
|
Some(x) if x == TypeId::of::<Curve>() => curve_widget(default_info),
|
||||||
Some(x) if x == TypeId::of::<Footprint>() => footprint_widget(default_info, &mut extra_widgets),
|
Some(x) if x == TypeId::of::<Footprint>() => footprint_widget(default_info, &mut extra_widgets),
|
||||||
|
|
@ -1145,14 +1145,6 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
|
||||||
|
|
||||||
// Add the color input
|
// Add the color input
|
||||||
match &**tagged_value {
|
match &**tagged_value {
|
||||||
TaggedValue::ColorNotInTable(color) => widgets.push(
|
|
||||||
color_button
|
|
||||||
.value(FillChoice::Solid(*color))
|
|
||||||
.allow_none(false)
|
|
||||||
.on_update(update_value(|input: &ColorInput| TaggedValue::ColorNotInTable(input.value.as_solid().unwrap()), node_id, index))
|
|
||||||
.on_commit(commit_value)
|
|
||||||
.widget_instance(),
|
|
||||||
),
|
|
||||||
TaggedValue::Color(color_table) => widgets.push(
|
TaggedValue::Color(color_table) => widgets.push(
|
||||||
color_button
|
color_button
|
||||||
.value(match color_table.iter().next() {
|
.value(match color_table.iter().next() {
|
||||||
|
|
@ -1171,7 +1163,7 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
|
||||||
color_button
|
color_button
|
||||||
.value(match gradient_table.iter().next() {
|
.value(match gradient_table.iter().next() {
|
||||||
Some(row) => FillChoice::Gradient(row.element.clone()),
|
Some(row) => FillChoice::Gradient(row.element.clone()),
|
||||||
None => FillChoice::None,
|
None => FillChoice::Gradient(GradientStops::default()),
|
||||||
})
|
})
|
||||||
.on_update(update_value(
|
.on_update(update_value(
|
||||||
|input: &ColorInput| TaggedValue::GradientTable(input.value.as_gradient().iter().map(|&gradient| TableRow::new_from_element(gradient.clone())).collect()),
|
|input: &ColorInput| TaggedValue::GradientTable(input.value.as_gradient().iter().map(|&gradient| TableRow::new_from_element(gradient.clone())).collect()),
|
||||||
|
|
@ -1181,18 +1173,7 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
|
||||||
.on_commit(commit_value)
|
.on_commit(commit_value)
|
||||||
.widget_instance(),
|
.widget_instance(),
|
||||||
),
|
),
|
||||||
TaggedValue::GradientStops(gradient_stops) => widgets.push(
|
x => warn!("Color {x:?}"),
|
||||||
color_button
|
|
||||||
.value(FillChoice::Gradient(gradient_stops.clone()))
|
|
||||||
.on_update(update_value(
|
|
||||||
|input: &ColorInput| TaggedValue::GradientStops(input.value.as_gradient().cloned().unwrap_or_default()),
|
|
||||||
node_id,
|
|
||||||
index,
|
|
||||||
))
|
|
||||||
.on_commit(commit_value)
|
|
||||||
.widget_instance(),
|
|
||||||
),
|
|
||||||
x => warn!("Colour {x:?}"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutGroup::Row { widgets }
|
LayoutGroup::Row { widgets }
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ impl FrontendGraphDataType {
|
||||||
TaggedValue::Raster(_) => Self::Raster,
|
TaggedValue::Raster(_) => Self::Raster,
|
||||||
TaggedValue::Vector(_) => Self::Vector,
|
TaggedValue::Vector(_) => Self::Vector,
|
||||||
TaggedValue::Color(_) => Self::Color,
|
TaggedValue::Color(_) => Self::Color,
|
||||||
TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) | TaggedValue::GradientTable(_) => Self::Gradient,
|
TaggedValue::Gradient(_) | TaggedValue::GradientTable(_) => Self::Gradient,
|
||||||
TaggedValue::String(_) | TaggedValue::VecString(_) => Self::Typography,
|
TaggedValue::String(_) | TaggedValue::VecString(_) => Self::Typography,
|
||||||
_ => Self::General,
|
_ => Self::General,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl TypeSource {
|
||||||
TaggedValue::Raster(_) => FrontendGraphDataType::Raster,
|
TaggedValue::Raster(_) => FrontendGraphDataType::Raster,
|
||||||
TaggedValue::Vector(_) => FrontendGraphDataType::Vector,
|
TaggedValue::Vector(_) => FrontendGraphDataType::Vector,
|
||||||
TaggedValue::Color(_) => FrontendGraphDataType::Color,
|
TaggedValue::Color(_) => FrontendGraphDataType::Color,
|
||||||
TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) | TaggedValue::GradientTable(_) => FrontendGraphDataType::Gradient,
|
TaggedValue::Gradient(_) | TaggedValue::GradientTable(_) => FrontendGraphDataType::Gradient,
|
||||||
TaggedValue::String(_) => FrontendGraphDataType::Typography,
|
TaggedValue::String(_) => FrontendGraphDataType::Typography,
|
||||||
_ => FrontendGraphDataType::General,
|
_ => FrontendGraphDataType::General,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -282,13 +282,15 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||||
node: graphene_std::math_nodes::footprint_value::IDENTIFIER,
|
node: graphene_std::math_nodes::footprint_value::IDENTIFIER,
|
||||||
aliases: &["graphene_math_nodes::FootprintValueNode", "graphene_core::ops::FootprintValueNode"],
|
aliases: &["graphene_math_nodes::FootprintValueNode", "graphene_core::ops::FootprintValueNode"],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
|
||||||
node: graphene_std::math_nodes::gradient_table_value::IDENTIFIER,
|
|
||||||
aliases: &["graphene_math_nodes::GradientTableValueNode", "graphene_core::ops::GradientTableValueNode"],
|
|
||||||
},
|
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::math_nodes::gradient_value::IDENTIFIER,
|
node: graphene_std::math_nodes::gradient_value::IDENTIFIER,
|
||||||
aliases: &["graphene_math_nodes::GradientValueNode", "graphene_core::ops::GradientValueNode"],
|
aliases: &[
|
||||||
|
"graphene_math_nodes::GradientValueNode",
|
||||||
|
"graphene_core::ops::GradientValueNode",
|
||||||
|
"graphene_math_nodes::GradientTableValueNode",
|
||||||
|
"graphene_core::ops::GradientTableValueNode",
|
||||||
|
"math_nodes::GradientTableValueNode",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::math_nodes::greater_than::IDENTIFIER,
|
node: graphene_std::math_nodes::greater_than::IDENTIFIER,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ use std::hash::Hash;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
pub use std::sync::Arc;
|
pub use std::sync::Arc;
|
||||||
|
use text_nodes::vector_types::GradientStop;
|
||||||
|
|
||||||
pub struct TaggedValueTypeError;
|
pub struct TaggedValueTypeError;
|
||||||
|
|
||||||
|
|
@ -182,7 +183,6 @@ tagged_value! {
|
||||||
U64(u64),
|
U64(u64),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
String(String),
|
String(String),
|
||||||
ColorNotInTable(Color),
|
|
||||||
// ========================
|
// ========================
|
||||||
// LISTS OF PRIMITIVE TYPES
|
// LISTS OF PRIMITIVE TYPES
|
||||||
// ========================
|
// ========================
|
||||||
|
|
@ -209,8 +209,10 @@ tagged_value! {
|
||||||
#[serde(alias = "ArtboardGroup")]
|
#[serde(alias = "ArtboardGroup")]
|
||||||
Artboard(Table<Artboard>),
|
Artboard(Table<Artboard>),
|
||||||
#[serde(deserialize_with = "core_types::misc::migrate_color")] // TODO: Eventually remove this migration document upgrade code
|
#[serde(deserialize_with = "core_types::misc::migrate_color")] // TODO: Eventually remove this migration document upgrade code
|
||||||
#[serde(alias = "ColorTable", alias = "OptionalColor")]
|
#[serde(alias = "ColorTable", alias = "OptionalColor", alias = "ColorNotInTable")]
|
||||||
Color(Table<Color>),
|
Color(Table<Color>),
|
||||||
|
#[serde(deserialize_with = "graphic_types::vector_types::gradient::migrate_gradient_stops")] // TODO: Eventually remove this migration document upgrade code
|
||||||
|
#[serde(alias = "GradientPositions", alias = "GradientStops")]
|
||||||
GradientTable(Table<GradientStops>),
|
GradientTable(Table<GradientStops>),
|
||||||
// ============
|
// ============
|
||||||
// STRUCT TYPES
|
// STRUCT TYPES
|
||||||
|
|
@ -222,8 +224,6 @@ tagged_value! {
|
||||||
DAffine2(DAffine2),
|
DAffine2(DAffine2),
|
||||||
Stroke(graphic_types::vector_types::vector::style::Stroke),
|
Stroke(graphic_types::vector_types::vector::style::Stroke),
|
||||||
Gradient(graphic_types::vector_types::vector::style::Gradient),
|
Gradient(graphic_types::vector_types::vector::style::Gradient),
|
||||||
#[serde(alias = "GradientPositions")] // TODO: Eventually remove this alias document upgrade code
|
|
||||||
GradientStops(GradientStops),
|
|
||||||
Font(text_nodes::Font),
|
Font(text_nodes::Font),
|
||||||
BrushStrokes(Vec<BrushStroke>),
|
BrushStrokes(Vec<BrushStroke>),
|
||||||
BrushCache(BrushCache),
|
BrushCache(BrushCache),
|
||||||
|
|
@ -333,6 +333,35 @@ impl TaggedValue {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_gradient(input: &str) -> Option<GradientStops> {
|
||||||
|
// String syntax: (e.g. "000000ff, ff0000ff")
|
||||||
|
let stops = input.split(',').filter_map(|s| to_color(s.trim())).collect::<Vec<_>>();
|
||||||
|
if stops.len() == 1 {
|
||||||
|
Some(GradientStops::new(vec![
|
||||||
|
GradientStop {
|
||||||
|
position: 0.,
|
||||||
|
midpoint: 0.5,
|
||||||
|
color: stops[0],
|
||||||
|
},
|
||||||
|
GradientStop {
|
||||||
|
position: 1.,
|
||||||
|
midpoint: 0.5,
|
||||||
|
color: stops[0],
|
||||||
|
},
|
||||||
|
]))
|
||||||
|
} else if stops.len() >= 2 {
|
||||||
|
let step = 1. / (stops.len() - 1) as f64;
|
||||||
|
Some(GradientStops::new(stops.into_iter().enumerate().map(|(i, color)| GradientStop {
|
||||||
|
position: i as f64 * step,
|
||||||
|
midpoint: 0.5,
|
||||||
|
color,
|
||||||
|
})))
|
||||||
|
} else {
|
||||||
|
log::error!("Invalid default value gradient string: {input}");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn to_reference_point(input: &str) -> Option<ReferencePoint> {
|
fn to_reference_point(input: &str) -> Option<ReferencePoint> {
|
||||||
let mut choices = input.split("::");
|
let mut choices = input.split("::");
|
||||||
let (first, second) = (choices.next()?.trim(), choices.next()?.trim());
|
let (first, second) = (choices.next()?.trim(), choices.next()?.trim());
|
||||||
|
|
@ -375,9 +404,8 @@ impl TaggedValue {
|
||||||
() if ty == TypeId::of::<u32>() => FromStr::from_str(string).map(TaggedValue::U32).ok()?,
|
() if ty == TypeId::of::<u32>() => FromStr::from_str(string).map(TaggedValue::U32).ok()?,
|
||||||
() if ty == TypeId::of::<DVec2>() => to_dvec2(string).map(TaggedValue::DVec2)?,
|
() if ty == TypeId::of::<DVec2>() => to_dvec2(string).map(TaggedValue::DVec2)?,
|
||||||
() if ty == TypeId::of::<bool>() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?,
|
() if ty == TypeId::of::<bool>() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?,
|
||||||
() if ty == TypeId::of::<Color>() => to_color(string).map(TaggedValue::ColorNotInTable)?,
|
|
||||||
() if ty == TypeId::of::<Option<Color>>() => TaggedValue::ColorNotInTable(to_color(string)?),
|
|
||||||
() if ty == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
|
() if ty == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
|
||||||
|
() if ty == TypeId::of::<Table<GradientStops>>() => to_gradient(string).map(|color| TaggedValue::GradientTable(Table::new_from_element(color)))?,
|
||||||
() if ty == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
|
() if ty == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
|
||||||
() if ty == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
|
() if ty == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
|
@ -537,8 +565,3 @@ mod fake_hash {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_construct_color() {
|
|
||||||
assert_eq!(TaggedValue::from_type(&concrete!(Color)).unwrap(), TaggedValue::ColorNotInTable(Color::default()));
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,6 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::style::StrokeAlign]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::style::StrokeAlign]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::style::Stroke]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::style::Stroke]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::style::Gradient]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::style::Gradient]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => GradientStops]),
|
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<graphene_std::uuid::NodeId>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<graphene_std::uuid::NodeId>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Box<graphene_std::vector::VectorModification>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Box<graphene_std::vector::VectorModification>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::CentroidType]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::CentroidType]),
|
||||||
|
|
@ -157,7 +156,6 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Color>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Color>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Image<Color>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Image<Color>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<GradientStops>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<GradientStops>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => GradientStops]),
|
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<DVec2>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<DVec2>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<NodeId>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<NodeId>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<f64>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<f64>]),
|
||||||
|
|
@ -183,7 +181,6 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<f64>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<f64>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Color]),
|
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<Color>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<Color>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => [f64; 4]]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => [f64; 4]]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Graphic]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Graphic]),
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,8 @@ use core_types::uuid::{NodeId, generate_uuid};
|
||||||
use dyn_any::DynAny;
|
use dyn_any::DynAny;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::Vector;
|
use graphic_types::Vector;
|
||||||
use graphic_types::raster_types::BitmapMut;
|
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster};
|
||||||
use graphic_types::raster_types::Image;
|
use graphic_types::vector_types::gradient::{GradientStops, GradientType};
|
||||||
use graphic_types::raster_types::{CPU, GPU, Raster};
|
|
||||||
use graphic_types::vector_types::gradient::GradientStops;
|
|
||||||
use graphic_types::vector_types::gradient::GradientType;
|
|
||||||
use graphic_types::vector_types::subpath::Subpath;
|
use graphic_types::vector_types::subpath::Subpath;
|
||||||
use graphic_types::vector_types::vector::click_target::{ClickTarget, FreePoint};
|
use graphic_types::vector_types::vector::click_target::{ClickTarget, FreePoint};
|
||||||
use graphic_types::vector_types::vector::style::{Fill, PaintOrder, RenderMode, Stroke, StrokeAlign};
|
use graphic_types::vector_types::vector::style::{Fill, PaintOrder, RenderMode, Stroke, StrokeAlign};
|
||||||
|
|
|
||||||
|
|
@ -447,6 +447,24 @@ impl Gradient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Eventually remove this migration document upgrade code
|
||||||
|
pub fn migrate_gradient_stops<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<core_types::table::Table<GradientStops>, D::Error> {
|
||||||
|
use core_types::table::Table;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum GradientStopsFormat {
|
||||||
|
GradientStops(GradientStops),
|
||||||
|
GradientTable(Table<GradientStops>),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match GradientStopsFormat::deserialize(deserializer)? {
|
||||||
|
GradientStopsFormat::GradientStops(stops) => Table::new_from_element(stops),
|
||||||
|
GradientStopsFormat::GradientTable(table) => table,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl core_types::bounds::BoundingBox for GradientStops {
|
impl core_types::bounds::BoundingBox for GradientStops {
|
||||||
fn bounding_box(&self, _transform: DAffine2, _include_stroke: bool) -> core_types::bounds::RenderBoundingBox {
|
fn bounding_box(&self, _transform: DAffine2, _include_stroke: bool) -> core_types::bounds::RenderBoundingBox {
|
||||||
core_types::bounds::RenderBoundingBox::Infinite
|
core_types::bounds::RenderBoundingBox::Infinite
|
||||||
|
|
|
||||||
|
|
@ -1455,11 +1455,9 @@ mod tests {
|
||||||
() -> Table<Raster<CPU>>,
|
() -> Table<Raster<CPU>>,
|
||||||
() -> Table<Color>,
|
() -> Table<Color>,
|
||||||
() -> Table<GradientStops>,
|
() -> Table<GradientStops>,
|
||||||
() -> GradientStops,
|
|
||||||
Footprint -> Table<Raster<CPU>>,
|
Footprint -> Table<Raster<CPU>>,
|
||||||
Footprint -> Table<Color>,
|
Footprint -> Table<Color>,
|
||||||
Footprint -> Table<GradientStops>,
|
Footprint -> Table<GradientStops>,
|
||||||
Footprint -> GradientStops,
|
|
||||||
)]
|
)]
|
||||||
image: impl Node<F, Output = T>,
|
image: impl Node<F, Output = T>,
|
||||||
) -> T {
|
) -> T {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ use core_types::transform::Footprint;
|
||||||
use core_types::uuid::NodeId;
|
use core_types::uuid::NodeId;
|
||||||
use core_types::{CloneVarArgs, Color, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
|
use core_types::{CloneVarArgs, Color, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::{Artboard, Graphic, Vector, vector_types::GradientStops};
|
use graphic_types::vector_types::GradientStops;
|
||||||
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
|
|
||||||
const DAY: f64 = 1000. * 3600. * 24.;
|
const DAY: f64 = 1000. * 3600. * 24.;
|
||||||
|
|
@ -84,7 +85,6 @@ async fn quantize_real_time<T>(
|
||||||
Context -> Table<Color>,
|
Context -> Table<Color>,
|
||||||
Context -> Table<Artboard>,
|
Context -> Table<Artboard>,
|
||||||
Context -> Table<GradientStops>,
|
Context -> Table<GradientStops>,
|
||||||
Context -> GradientStops,
|
|
||||||
Context -> (),
|
Context -> (),
|
||||||
)]
|
)]
|
||||||
value: impl Node<'n, Context<'static>, Output = T>,
|
value: impl Node<'n, Context<'static>, Output = T>,
|
||||||
|
|
@ -128,7 +128,6 @@ async fn quantize_animation_time<T>(
|
||||||
Context -> Table<Color>,
|
Context -> Table<Color>,
|
||||||
Context -> Table<Artboard>,
|
Context -> Table<Artboard>,
|
||||||
Context -> Table<GradientStops>,
|
Context -> Table<GradientStops>,
|
||||||
Context -> GradientStops,
|
|
||||||
Context -> (),
|
Context -> (),
|
||||||
)]
|
)]
|
||||||
value: impl Node<'n, Context<'static>, Output = T>,
|
value: impl Node<'n, Context<'static>, Output = T>,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ use core_types::transform::Footprint;
|
||||||
use core_types::uuid::NodeId;
|
use core_types::uuid::NodeId;
|
||||||
use core_types::{Color, OwnedContextImpl};
|
use core_types::{Color, OwnedContextImpl};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::{Artboard, Graphic, Vector, vector_types::GradientStops};
|
use graphic_types::vector_types::GradientStops;
|
||||||
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
|
|
||||||
/// Filters out what should be unused components of the context based on the specified requirements.
|
/// Filters out what should be unused components of the context based on the specified requirements.
|
||||||
|
|
@ -37,7 +38,6 @@ async fn context_modification<T>(
|
||||||
Context -> Table<Color>,
|
Context -> Table<Color>,
|
||||||
Context -> Table<Artboard>,
|
Context -> Table<Artboard>,
|
||||||
Context -> Table<GradientStops>,
|
Context -> Table<GradientStops>,
|
||||||
Context -> GradientStops,
|
|
||||||
)]
|
)]
|
||||||
value: impl Node<Context<'static>, Output = T>,
|
value: impl Node<Context<'static>, Output = T>,
|
||||||
/// The parts of the context to keep when evaluating the input value. All other parts are nullified.
|
/// The parts of the context to keep when evaluating the input value. All other parts are nullified.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ use core_types::registry::types::TextArea;
|
||||||
use core_types::table::Table;
|
use core_types::table::Table;
|
||||||
use core_types::{Context, Ctx};
|
use core_types::{Context, Ctx};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::{Artboard, Graphic, Vector, vector_types::GradientStops};
|
use graphic_types::vector_types::GradientStops;
|
||||||
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
|
|
||||||
/// Type-asserts a value to be a string.
|
/// Type-asserts a value to be a string.
|
||||||
|
|
@ -152,7 +153,7 @@ async fn switch<T, C: Send + 'n + Clone>(
|
||||||
Context -> Table<Raster<CPU>>,
|
Context -> Table<Raster<CPU>>,
|
||||||
Context -> Table<Raster<GPU>>,
|
Context -> Table<Raster<GPU>>,
|
||||||
Context -> Table<Color>,
|
Context -> Table<Color>,
|
||||||
Context -> GradientStops,
|
Context -> Table<GradientStops>,
|
||||||
)]
|
)]
|
||||||
if_true: impl Node<C, Output = T>,
|
if_true: impl Node<C, Output = T>,
|
||||||
#[expose]
|
#[expose]
|
||||||
|
|
@ -171,7 +172,7 @@ async fn switch<T, C: Send + 'n + Clone>(
|
||||||
Context -> Table<Raster<CPU>>,
|
Context -> Table<Raster<CPU>>,
|
||||||
Context -> Table<Raster<GPU>>,
|
Context -> Table<Raster<GPU>>,
|
||||||
Context -> Table<Color>,
|
Context -> Table<Color>,
|
||||||
Context -> GradientStops,
|
Context -> Table<GradientStops>,
|
||||||
)]
|
)]
|
||||||
if_false: impl Node<C, Output = T>,
|
if_false: impl Node<C, Output = T>,
|
||||||
) -> T {
|
) -> T {
|
||||||
|
|
|
||||||
|
|
@ -318,22 +318,47 @@ pub async fn flatten_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl C
|
||||||
|
|
||||||
/// Constructs a gradient from a table of colors, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
|
/// Constructs a gradient from a table of colors, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
|
||||||
#[node_macro::node(category("Color"))]
|
#[node_macro::node(category("Color"))]
|
||||||
fn colors_to_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Color>)] colors: T) -> GradientStops {
|
fn colors_to_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Color>)] colors: T) -> Table<GradientStops> {
|
||||||
let colors = colors.into_flattened_table::<Color>();
|
let colors = colors.into_flattened_table::<Color>();
|
||||||
let total_colors = colors.len();
|
let total_colors = colors.len();
|
||||||
|
|
||||||
if total_colors == 0 {
|
if total_colors == 0 {
|
||||||
return GradientStops::new(vec![GradientStop {
|
return Table::new_from_element(GradientStops::new(vec![
|
||||||
position: 0.,
|
GradientStop {
|
||||||
midpoint: 0.5,
|
position: 0.,
|
||||||
color: Color::BLACK,
|
midpoint: 0.5,
|
||||||
}]);
|
color: Color::BLACK,
|
||||||
|
},
|
||||||
|
GradientStop {
|
||||||
|
position: 1.,
|
||||||
|
midpoint: 0.5,
|
||||||
|
color: Color::BLACK,
|
||||||
|
},
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (Some(color), None) = {
|
||||||
|
let mut colors_iter = colors.iter();
|
||||||
|
(colors_iter.next(), colors_iter.next())
|
||||||
|
} {
|
||||||
|
return Table::new_from_element(GradientStops::new(vec![
|
||||||
|
GradientStop {
|
||||||
|
position: 0.,
|
||||||
|
midpoint: 0.5,
|
||||||
|
color: *color.element,
|
||||||
|
},
|
||||||
|
GradientStop {
|
||||||
|
position: 1.,
|
||||||
|
midpoint: 0.5,
|
||||||
|
color: *color.element,
|
||||||
|
},
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
let colors = colors.into_iter().enumerate().map(|(index, row)| GradientStop {
|
let colors = colors.into_iter().enumerate().map(|(index, row)| GradientStop {
|
||||||
position: index as f64 / (total_colors - 1).max(1) as f64,
|
position: index as f64 / (total_colors - 1) as f64,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
color: row.element,
|
color: row.element,
|
||||||
});
|
});
|
||||||
GradientStops::new(colors)
|
Table::new_from_element(GradientStops::new(colors))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -767,21 +767,17 @@ fn color_value(_: impl Ctx, _primary: (), #[default(Color::BLACK)] color: Table<
|
||||||
|
|
||||||
/// Constructs a gradient value which may be set to any sequence of color stops to represent the transition between colors.
|
/// Constructs a gradient value which may be set to any sequence of color stops to represent the transition between colors.
|
||||||
#[node_macro::node(category("Value"))]
|
#[node_macro::node(category("Value"))]
|
||||||
fn gradient_value(_: impl Ctx, _primary: (), gradient: GradientStops) -> GradientStops {
|
fn gradient_value(_: impl Ctx, _primary: (), gradient: Table<GradientStops>) -> Table<GradientStops> {
|
||||||
gradient
|
gradient
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a gradient value which may be set to any sequence of color stops to represent the transition between colors.
|
|
||||||
#[node_macro::node(category("Value"))]
|
|
||||||
fn gradient_table_value(_: impl Ctx, _primary: (), gradient: GradientStops) -> Table<GradientStops> {
|
|
||||||
Table::new_from_element(gradient)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the color at the specified position along the gradient, given a position from 0 (left) to 1 (right).
|
/// Gets the color at the specified position along the gradient, given a position from 0 (left) to 1 (right).
|
||||||
#[node_macro::node(category("Color"))]
|
#[node_macro::node(category("Color"))]
|
||||||
fn sample_gradient(_: impl Ctx, _primary: (), gradient: GradientStops, position: Fraction) -> Table<Color> {
|
fn sample_gradient(_: impl Ctx, _primary: (), gradient: Table<GradientStops>, position: Fraction) -> Table<Color> {
|
||||||
|
let Some(row) = gradient.get(0) else { return Table::new() };
|
||||||
|
|
||||||
let position = position.clamp(0., 1.);
|
let position = position.clamp(0., 1.);
|
||||||
let color = gradient.evaluate(position);
|
let color = row.element.evaluate(position);
|
||||||
Table::new_from_element(color)
|
Table::new_from_element(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ fn luminance<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -80,7 +79,6 @@ fn gamma_correction<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -102,7 +100,6 @@ fn extract_channel<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -127,7 +124,6 @@ fn make_opaque<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -154,7 +150,6 @@ fn brightness_contrast_classic<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -186,7 +181,6 @@ fn brightness_contrast<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -268,7 +262,6 @@ fn levels<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
@ -337,7 +330,6 @@ fn black_and_white<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
@ -411,7 +403,6 @@ fn hue_saturation<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -447,7 +438,6 @@ fn invert<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -471,7 +461,6 @@ fn threshold<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
@ -518,7 +507,6 @@ fn vibrance<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
@ -684,7 +672,6 @@ fn channel_mixer<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
@ -815,7 +802,6 @@ fn selective_color<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
@ -962,7 +948,6 @@ fn posterize<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
@ -997,7 +982,6 @@ fn exposure<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,6 @@ fn blend<T: Blend<Color> + Send>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
over: T,
|
over: T,
|
||||||
|
|
@ -145,7 +144,6 @@ fn blend<T: Blend<Color> + Send>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
under: T,
|
under: T,
|
||||||
|
|
@ -162,7 +160,6 @@ fn color_overlay<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,17 @@ async fn gradient_map<T: Adjust<Color>>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
GradientStops,
|
|
||||||
)]
|
)]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
gradient: GradientStops,
|
gradient: Table<GradientStops>,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
) -> T {
|
) -> T {
|
||||||
|
let Some(row) = gradient.get(0) else { return image };
|
||||||
|
|
||||||
image.adjust(|color| {
|
image.adjust(|color| {
|
||||||
let intensity = color.luminance_srgb();
|
let intensity = color.luminance_srgb();
|
||||||
let intensity = if reverse { 1. - intensity } else { intensity };
|
let intensity = if reverse { 1. - intensity } else { intensity };
|
||||||
gradient.evaluate(intensity as f64).to_linear_srgb()
|
row.element.evaluate(intensity as f64).to_linear_srgb()
|
||||||
});
|
});
|
||||||
|
|
||||||
image
|
image
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ async fn assign_colors<T>(
|
||||||
stroke: bool,
|
stroke: bool,
|
||||||
/// The range of colors to select from.
|
/// The range of colors to select from.
|
||||||
#[widget(ParsedWidgetOverride::Custom = "assign_colors_gradient")]
|
#[widget(ParsedWidgetOverride::Custom = "assign_colors_gradient")]
|
||||||
gradient: GradientStops,
|
gradient: Table<GradientStops>,
|
||||||
/// Whether to reverse the gradient.
|
/// Whether to reverse the gradient.
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
/// Whether to randomize the color selection for each element from throughout the gradient.
|
/// Whether to randomize the color selection for each element from throughout the gradient.
|
||||||
|
|
@ -76,8 +76,10 @@ async fn assign_colors<T>(
|
||||||
where
|
where
|
||||||
T: VectorTableIterMut + 'n + Send,
|
T: VectorTableIterMut + 'n + Send,
|
||||||
{
|
{
|
||||||
|
let Some(row) = gradient.into_iter().next() else { return content };
|
||||||
|
|
||||||
let length = content.vector_iter_mut().count();
|
let length = content.vector_iter_mut().count();
|
||||||
let gradient = if reverse { gradient.reversed() } else { gradient };
|
let gradient = if reverse { row.element.reversed() } else { row.element };
|
||||||
|
|
||||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into());
|
let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue