mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 14:58:05 +08:00
106 lines
4.8 KiB
Rust
106 lines
4.8 KiB
Rust
use core_types::list::Item;
|
|
use core_types::{Color, ExtractVarArgs};
|
|
use core_types::{Ctx, ExtractIndex, ExtractPosition};
|
|
use glam::DVec2;
|
|
use graphic_types::vector_types::Gradient;
|
|
use graphic_types::{Graphic, Vector};
|
|
use raster_types::{CPU, Raster};
|
|
|
|
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
|
fn read_graphic(ctx: impl Ctx + ExtractVarArgs) -> Item<Graphic> {
|
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
|
let var_arg = var_arg as &dyn std::any::Any;
|
|
|
|
var_arg.downcast_ref().cloned().unwrap_or_default()
|
|
}
|
|
|
|
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
|
fn read_vector(ctx: impl Ctx + ExtractVarArgs) -> Item<Vector> {
|
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
|
let var_arg = var_arg as &dyn std::any::Any;
|
|
|
|
var_arg.downcast_ref().cloned().unwrap_or_default()
|
|
}
|
|
|
|
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
|
fn read_raster(ctx: impl Ctx + ExtractVarArgs) -> Item<Raster<CPU>> {
|
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
|
let var_arg = var_arg as &dyn std::any::Any;
|
|
|
|
var_arg.downcast_ref().cloned().unwrap_or_default()
|
|
}
|
|
|
|
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
|
fn read_color(ctx: impl Ctx + ExtractVarArgs) -> Item<Color> {
|
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
|
let var_arg = var_arg as &dyn std::any::Any;
|
|
|
|
var_arg.downcast_ref().cloned().unwrap_or_default()
|
|
}
|
|
|
|
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
|
fn read_gradient(ctx: impl Ctx + ExtractVarArgs) -> Item<Gradient> {
|
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
|
let var_arg = var_arg as &dyn std::any::Any;
|
|
|
|
var_arg.downcast_ref().cloned().unwrap_or_default()
|
|
}
|
|
|
|
/// Reads the current number from within a **Map** node's loop.
|
|
#[node_macro::node(category("Context"))]
|
|
fn read_number(ctx: impl Ctx + ExtractVarArgs) -> Item<f64> {
|
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
|
let var_arg = var_arg as &dyn std::any::Any;
|
|
|
|
if let Some(item) = var_arg.downcast_ref::<Item<f64>>() {
|
|
return item.clone();
|
|
}
|
|
|
|
// Numeric lists carry several possible element types, so probe each and widen to f64, keeping the item's attributes
|
|
if let Some(item) = var_arg.downcast_ref::<Item<f32>>() {
|
|
let (element, attributes) = item.clone().into_parts();
|
|
return Item::from_parts(element as f64, attributes);
|
|
}
|
|
if let Some(item) = var_arg.downcast_ref::<Item<u32>>() {
|
|
let (element, attributes) = item.clone().into_parts();
|
|
return Item::from_parts(element as f64, attributes);
|
|
}
|
|
if let Some(item) = var_arg.downcast_ref::<Item<u64>>() {
|
|
let (element, attributes) = item.clone().into_parts();
|
|
return Item::from_parts(element as f64, attributes);
|
|
}
|
|
|
|
Default::default()
|
|
}
|
|
|
|
#[node_macro::node(category("Context"), path(core_types::vector))]
|
|
async fn read_position(
|
|
ctx: impl Ctx + ExtractPosition,
|
|
_primary: (),
|
|
/// The number of nested loops to traverse outwards (from the innermost loop) to get the position from. The most upstream loop is level 0, and downstream loops add levels.
|
|
///
|
|
/// In programming terms: inside the double loop `i { j { ... } }`, *Loop Level* 0 = `j` and 1 = `i`. After inserting a third loop `k { ... }`, inside it, levels would be 0 = `k`, 1 = `j`, and 2 = `i`.
|
|
loop_level: Item<u32>,
|
|
) -> Item<DVec2> {
|
|
let loop_level = *loop_level.element();
|
|
Item::new_from_element(ctx.try_position().and_then(|mut iter| iter.nth(loop_level as usize).or_else(|| iter.last())).unwrap_or(DVec2::ZERO))
|
|
}
|
|
|
|
// TODO: Return u32, u64, or usize instead of f64 after #1621 is resolved and has allowed us to implement automatic type conversion in the node graph for nodes with generic type inputs.
|
|
// TODO: (Currently automatic type conversion only works for concrete types, via the Graphene preprocessor and not the full Graphene type system.)
|
|
/// Produces the index of the current iteration of a loop by reading from the evaluation context, which is supplied by downstream nodes such as *Repeat*.
|
|
///
|
|
/// Nested loops can enable 2D or higher-dimensional iteration by using the *Loop Level* parameter to read the index from outer levels of loops.
|
|
#[node_macro::node(category("Context"), path(core_types::vector))]
|
|
async fn read_index(
|
|
ctx: impl Ctx + ExtractIndex,
|
|
_primary: (),
|
|
/// The number of nested loops to traverse outwards (from the innermost loop) to get the index from. The most upstream loop is level 0, and downstream loops add levels.
|
|
///
|
|
/// In programming terms: inside the double loop `i { j { ... } }`, *Loop Level* 0 = `j` and 1 = `i`. After inserting a third loop `k { ... }`, inside it, levels would be 0 = `k`, 1 = `j`, and 2 = `i`.
|
|
loop_level: Item<u32>,
|
|
) -> Item<f64> {
|
|
let loop_level = *loop_level.element();
|
|
Item::new_from_element(ctx.try_index().and_then(|mut iter| iter.nth(loop_level as usize).or_else(|| iter.last())).unwrap_or(0) as f64)
|
|
}
|