New nodes: Colors to Gradient, Flatten Color, and Flatten Gradient (#3835)
* New nodes: Colors to Gradient, Flatten Color, and Flatten Gradient * Fix Data panel not showing GradientStops * Fix wrong category
This commit is contained in:
parent
da7437c023
commit
cde7d5f951
|
|
@ -166,11 +166,12 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
|
||||||
Table<Raster<GPU>>,
|
Table<Raster<GPU>>,
|
||||||
Table<Color>,
|
Table<Color>,
|
||||||
Table<GradientStops>,
|
Table<GradientStops>,
|
||||||
Vec<String>,
|
GradientStops,
|
||||||
f64,
|
f64,
|
||||||
u32,
|
u32,
|
||||||
u64,
|
u64,
|
||||||
bool,
|
bool,
|
||||||
|
Vec<String>,
|
||||||
String,
|
String,
|
||||||
Option<f64>,
|
Option<f64>,
|
||||||
DVec2,
|
DVec2,
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,102 @@ pub trait IntoGraphicTable {
|
||||||
flatten_table(&mut output, content);
|
flatten_table(&mut output, content);
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deeply flattens any color content within a graphic table, discarding non-color content, and returning a table of only color elements.
|
||||||
|
fn into_flattened_color_table(self) -> Table<Color>
|
||||||
|
where
|
||||||
|
Self: std::marker::Sized,
|
||||||
|
{
|
||||||
|
let content = self.into_graphic_table();
|
||||||
|
|
||||||
|
fn flatten_table(output_color_table: &mut Table<Color>, current_graphic_table: Table<Graphic>) {
|
||||||
|
for current_graphic_row in current_graphic_table.iter() {
|
||||||
|
let current_graphic = current_graphic_row.element.clone();
|
||||||
|
let source_node_id = *current_graphic_row.source_node_id;
|
||||||
|
|
||||||
|
match current_graphic {
|
||||||
|
// If we're allowed to recurse, flatten any tables we encounter
|
||||||
|
Graphic::Graphic(mut current_graphic_table) => {
|
||||||
|
// Apply the parent graphic's transform to all child elements
|
||||||
|
for graphic in current_graphic_table.iter_mut() {
|
||||||
|
*graphic.transform = *current_graphic_row.transform * *graphic.transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatten_table(output_color_table, current_graphic_table);
|
||||||
|
}
|
||||||
|
// Push any leaf Color elements we encounter
|
||||||
|
Graphic::Color(color_table) => {
|
||||||
|
for current_color_row in color_table.iter() {
|
||||||
|
output_color_table.push(TableRow {
|
||||||
|
element: *current_color_row.element,
|
||||||
|
transform: *current_graphic_row.transform * *current_color_row.transform,
|
||||||
|
alpha_blending: AlphaBlending {
|
||||||
|
blend_mode: current_color_row.alpha_blending.blend_mode,
|
||||||
|
opacity: current_graphic_row.alpha_blending.opacity * current_color_row.alpha_blending.opacity,
|
||||||
|
fill: current_color_row.alpha_blending.fill,
|
||||||
|
clip: current_color_row.alpha_blending.clip,
|
||||||
|
},
|
||||||
|
source_node_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Table::new();
|
||||||
|
flatten_table(&mut output, content);
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deeply flattens any gradient content within a graphic table, discarding non-gradient content, and returning a table of only gradient elements.
|
||||||
|
fn into_flattened_gradient_table(self) -> Table<GradientStops>
|
||||||
|
where
|
||||||
|
Self: std::marker::Sized,
|
||||||
|
{
|
||||||
|
let content = self.into_graphic_table();
|
||||||
|
|
||||||
|
fn flatten_table(output_gradient_table: &mut Table<GradientStops>, current_graphic_table: Table<Graphic>) {
|
||||||
|
for current_graphic_row in current_graphic_table.iter() {
|
||||||
|
let current_graphic = current_graphic_row.element.clone();
|
||||||
|
let source_node_id = *current_graphic_row.source_node_id;
|
||||||
|
|
||||||
|
match current_graphic {
|
||||||
|
// If we're allowed to recurse, flatten any tables we encounter
|
||||||
|
Graphic::Graphic(mut current_graphic_table) => {
|
||||||
|
// Apply the parent graphic's transform to all child elements
|
||||||
|
for graphic in current_graphic_table.iter_mut() {
|
||||||
|
*graphic.transform = *current_graphic_row.transform * *graphic.transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatten_table(output_gradient_table, current_graphic_table);
|
||||||
|
}
|
||||||
|
// Push any leaf GradientStops elements we encounter
|
||||||
|
Graphic::Gradient(gradient_table) => {
|
||||||
|
for current_gradient_row in gradient_table.iter() {
|
||||||
|
output_gradient_table.push(TableRow {
|
||||||
|
element: current_gradient_row.element.clone(),
|
||||||
|
transform: *current_graphic_row.transform * *current_gradient_row.transform,
|
||||||
|
alpha_blending: AlphaBlending {
|
||||||
|
blend_mode: current_gradient_row.alpha_blending.blend_mode,
|
||||||
|
opacity: current_graphic_row.alpha_blending.opacity * current_gradient_row.alpha_blending.opacity,
|
||||||
|
fill: current_gradient_row.alpha_blending.fill,
|
||||||
|
clip: current_gradient_row.alpha_blending.clip,
|
||||||
|
},
|
||||||
|
source_node_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Table::new();
|
||||||
|
flatten_table(&mut output, content);
|
||||||
|
output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoGraphicTable for Table<Graphic> {
|
impl IntoGraphicTable for Table<Graphic> {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,44 @@ use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::graphic::{Graphic, IntoGraphicTable};
|
use graphic_types::graphic::{Graphic, IntoGraphicTable};
|
||||||
use graphic_types::{Artboard, Vector};
|
use graphic_types::{Artboard, Vector};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
use vector_types::{GradientStops, ReferencePoint};
|
use vector_types::{GradientStop, GradientStops, ReferencePoint};
|
||||||
|
|
||||||
|
/// Returns the value at the specified index in the collection.
|
||||||
|
/// If no value exists at that index, the type's default value is returned.
|
||||||
|
#[node_macro::node(category("General"))]
|
||||||
|
pub fn index_elements<T: graphic_types::graphic::AtIndex + Clone + Default>(
|
||||||
|
_: impl Ctx,
|
||||||
|
/// The collection of data, such as a list or table.
|
||||||
|
#[implementations(
|
||||||
|
Vec<f64>,
|
||||||
|
Vec<u32>,
|
||||||
|
Vec<u64>,
|
||||||
|
Vec<DVec2>,
|
||||||
|
Vec<String>,
|
||||||
|
Table<Artboard>,
|
||||||
|
Table<Graphic>,
|
||||||
|
Table<Vector>,
|
||||||
|
Table<Raster<CPU>>,
|
||||||
|
Table<Raster<GPU>>,
|
||||||
|
Table<Color>,
|
||||||
|
Table<GradientStops>,
|
||||||
|
)]
|
||||||
|
collection: T,
|
||||||
|
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the collection, starting from -1 for the last item.
|
||||||
|
index: SignedInteger,
|
||||||
|
) -> T::Output
|
||||||
|
where
|
||||||
|
T::Output: Clone + Default,
|
||||||
|
{
|
||||||
|
let index = index as i32;
|
||||||
|
|
||||||
|
if index < 0 {
|
||||||
|
collection.at_index_from_end(-index as usize)
|
||||||
|
} else {
|
||||||
|
collection.at_index(index as usize)
|
||||||
|
}
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("General"))]
|
#[node_macro::node(category("General"))]
|
||||||
async fn map<Item: AnyHash + Send + Sync + std::hash::Hash>(
|
async fn map<Item: AnyHash + Send + Sync + std::hash::Hash>(
|
||||||
|
|
@ -261,45 +298,42 @@ pub async fn flatten_vector<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx
|
||||||
content.into_flattened_vector_table()
|
content.into_flattened_vector_table()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a graphic table into a vector table by deeply flattening any vector content it contains, and discarding any non-vector content.
|
/// Converts a graphic table into a raster table by deeply flattening any raster content it contains, and discarding any non-raster content.
|
||||||
#[node_macro::node(category("Vector"))]
|
#[node_macro::node(category("Raster"))]
|
||||||
pub async fn flatten_raster<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Raster<CPU>>)] content: T) -> Table<Raster<CPU>> {
|
pub async fn flatten_raster<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Raster<CPU>>)] content: T) -> Table<Raster<CPU>> {
|
||||||
content.into_flattened_raster_table()
|
content.into_flattened_raster_table()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value at the specified index in the collection.
|
/// Converts a graphic table into a color table by deeply flattening any color content it contains, and discarding any non-color content.
|
||||||
/// If no value exists at that index, the type's default value is returned.
|
|
||||||
#[node_macro::node(category("General"))]
|
#[node_macro::node(category("General"))]
|
||||||
pub fn index_elements<T: graphic_types::graphic::AtIndex + Clone + Default>(
|
pub async fn flatten_color<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Color>)] content: T) -> Table<Color> {
|
||||||
_: impl Ctx,
|
content.into_flattened_color_table()
|
||||||
/// The collection of data, such as a list or table.
|
}
|
||||||
#[implementations(
|
|
||||||
Vec<f64>,
|
/// Converts a graphic table into a gradient table by deeply flattening any gradient content it contains, and discarding any non-gradient content.
|
||||||
Vec<u32>,
|
#[node_macro::node(category("General"))]
|
||||||
Vec<u64>,
|
pub async fn flatten_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<GradientStops>)] content: T) -> Table<GradientStops> {
|
||||||
Vec<DVec2>,
|
content.into_flattened_gradient_table()
|
||||||
Vec<String>,
|
}
|
||||||
Table<Artboard>,
|
|
||||||
Table<Graphic>,
|
/// Constructs a gradient from a table of colors, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
|
||||||
Table<Vector>,
|
#[node_macro::node(category("Color"))]
|
||||||
Table<Raster<CPU>>,
|
fn colors_to_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Color>)] colors: T) -> GradientStops {
|
||||||
Table<Raster<GPU>>,
|
let colors = colors.into_flattened_color_table();
|
||||||
Table<Color>,
|
let total_colors = colors.len();
|
||||||
Table<GradientStops>,
|
|
||||||
)]
|
if total_colors == 0 {
|
||||||
collection: T,
|
return GradientStops::new(vec![GradientStop {
|
||||||
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the collection, starting from -1 for the last item.
|
position: 0.,
|
||||||
index: SignedInteger,
|
midpoint: 0.5,
|
||||||
) -> T::Output
|
color: Color::BLACK,
|
||||||
where
|
}]);
|
||||||
T::Output: Clone + Default,
|
}
|
||||||
{
|
|
||||||
let index = index as i32;
|
let colors = colors.into_iter().enumerate().map(|(index, row)| GradientStop {
|
||||||
|
position: index as f64 / (total_colors - 1).max(1) as f64,
|
||||||
if index < 0 {
|
midpoint: 0.5,
|
||||||
collection.at_index_from_end(-index as usize)
|
color: row.element,
|
||||||
} else {
|
});
|
||||||
collection.at_index(index as usize)
|
GradientStops::new(colors)
|
||||||
}
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue