mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 07:18:04 +08:00
Add "Loop Level" to the Position context reader node (#3679)
* Add "Loop Level" to the Position context reader node * Remove InjectPosition
This commit is contained in:
@@ -1,28 +1,15 @@
|
||||
use core_types::Color;
|
||||
use core_types::table::{Table, TableRowRef};
|
||||
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractIndex, ExtractVarArgs, InjectVarArgs, OwnedContextImpl};
|
||||
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractIndex, ExtractPosition, OwnedContextImpl};
|
||||
use glam::DVec2;
|
||||
use graphic_types::Graphic;
|
||||
use graphic_types::Vector;
|
||||
use graphic_types::raster_types::{CPU, Raster};
|
||||
use vector_types::GradientStops;
|
||||
|
||||
use log::*;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(dyn_any::DynAny)]
|
||||
struct HashableDVec2(DVec2);
|
||||
|
||||
impl std::hash::Hash for HashableDVec2 {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.x.to_bits().hash(state);
|
||||
self.0.y.to_bits().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[node_macro::node(name("Instance on Points"), category("Instancing"), path(core_types::vector))]
|
||||
async fn instance_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
|
||||
ctx: impl ExtractAll + CloneVarArgs + Sync + Ctx + InjectVarArgs,
|
||||
ctx: impl ExtractAll + CloneVarArgs + Sync + Ctx,
|
||||
points: Table<Vector>,
|
||||
#[implementations(
|
||||
Context -> Table<Graphic>,
|
||||
@@ -40,7 +27,7 @@ async fn instance_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>
|
||||
let mut iteration = async |index, point| {
|
||||
let transformed_point = transform.transform_point2(point);
|
||||
|
||||
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index).with_vararg(Box::new(HashableDVec2(transformed_point)));
|
||||
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index).with_position(transformed_point);
|
||||
let generated_instance = instance.eval(new_ctx.into_context()).await;
|
||||
|
||||
for mut generated_row in generated_instance.into_iter() {
|
||||
@@ -97,13 +84,23 @@ async fn instance_repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Instancing"), path(core_types::vector))]
|
||||
async fn instance_position(ctx: impl Ctx + ExtractVarArgs) -> DVec2 {
|
||||
match ctx.vararg(0).map(|dynamic| dynamic.downcast_ref::<HashableDVec2>()) {
|
||||
Ok(Some(position)) => return position.0,
|
||||
Ok(_) => warn!("Extracted value of incorrect type"),
|
||||
Err(e) => warn!("Cannot extract position vararg: {e:?}"),
|
||||
async fn instance_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: u32,
|
||||
) -> DVec2 {
|
||||
let Some(position_iter) = ctx.try_position() else { return DVec2::ZERO };
|
||||
let mut last = DVec2::ZERO;
|
||||
for (i, position) in position_iter.enumerate() {
|
||||
if i == loop_level as usize {
|
||||
return position;
|
||||
}
|
||||
last = position;
|
||||
}
|
||||
Default::default()
|
||||
last
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -160,7 +157,13 @@ mod test {
|
||||
let owned = OwnedContextImpl::default().into_context();
|
||||
let rect = RectangleNode::new(
|
||||
FutureWrapperNode(()),
|
||||
ExtractXyNode::new(InstancePositionNode {}, FutureWrapperNode(XY::Y)),
|
||||
ExtractXyNode::new(
|
||||
InstancePositionNode {
|
||||
_primary: FutureWrapperNode(()),
|
||||
loop_level: FutureWrapperNode(0),
|
||||
},
|
||||
FutureWrapperNode(XY::Y),
|
||||
),
|
||||
FutureWrapperNode(2_f64),
|
||||
FutureWrapperNode(false),
|
||||
FutureWrapperNode(0_f64),
|
||||
|
||||
Reference in New Issue
Block a user