Instance tables refactor part 8: Output the type of the input data with the Mirror node as well (#2699)

* Flatten output of mirror node

* Enable reflection based on pivot, not just bounds

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
James Lindsay 2025-06-07 23:12:32 +01:00 committed by Keavon Chambers
parent 57bf2f873e
commit bf7caef6fb
2 changed files with 27 additions and 23 deletions

View File

@ -334,6 +334,15 @@ pub fn reference_point_widget(parameter_widgets_info: ParameterWidgetsInfo, disa
if let Some(&TaggedValue::ReferencePoint(reference_point)) = input.as_non_exposed_value() { if let Some(&TaggedValue::ReferencePoint(reference_point)) = input.as_non_exposed_value() {
widgets.extend_from_slice(&[ widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(),
CheckboxInput::new(reference_point != ReferencePoint::None)
.on_update(update_value(
move |x: &CheckboxInput| TaggedValue::ReferencePoint(if x.checked { ReferencePoint::Center } else { ReferencePoint::None }),
node_id,
index,
))
.disabled(disabled)
.widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(),
ReferencePointInput::new(reference_point) ReferencePointInput::new(reference_point)
.on_update(update_value(move |x: &ReferencePointInput| TaggedValue::ReferencePoint(x.value), node_id, index)) .on_update(update_value(move |x: &ReferencePointInput| TaggedValue::ReferencePoint(x.value), node_id, index))
.disabled(disabled) .disabled(disabled)

View File

@ -357,20 +357,19 @@ where
result_table result_table
} }
// TODO: Make this node return Instances<I> instead of GraphicGroupTable, while preserving the current transform behavior as the `reference_point` and `offset` parameters are varied
#[node_macro::node(category("Vector"), path(graphene_core::vector))] #[node_macro::node(category("Vector"), path(graphene_core::vector))]
async fn mirror<I: 'n + Send + Clone>( async fn mirror<I: 'n + Send + Clone>(
_: impl Ctx, _: impl Ctx,
#[implementations(GraphicGroupTable, VectorDataTable, RasterDataTable<CPU>)] instance: Instances<I>, #[implementations(GraphicGroupTable, VectorDataTable, RasterDataTable<CPU>)] instance: Instances<I>,
#[default(ReferencePoint::Center)] reference_point: ReferencePoint, #[default(ReferencePoint::Center)] relative_to_bounds: ReferencePoint,
offset: f64, offset: f64,
#[range((-90., 90.))] angle: Angle, #[range((-90., 90.))] angle: Angle,
#[default(true)] keep_original: bool, #[default(true)] keep_original: bool,
) -> GraphicGroupTable ) -> Instances<I>
where where
Instances<I>: GraphicElementRendered, Instances<I>: GraphicElementRendered,
{ {
let mut result_table = GraphicGroupTable::default(); let mut result_table = Instances::default();
// Normalize the direction vector // Normalize the direction vector
let normal = DVec2::from_angle(angle.to_radians()); let normal = DVec2::from_angle(angle.to_radians());
@ -380,12 +379,8 @@ where
return result_table; return result_table;
}; };
// TODO: If the reference point is not None, use the current behavior but make it work correctly with local pivot origins of each Instances<I> row let reference_point_location = relative_to_bounds.point_in_bounding_box((bounding_box[0], bounding_box[1]).into());
let reference_point_location = reference_point.point_in_bounding_box((bounding_box[0], bounding_box[1]).into()).unwrap_or_else(|| { let mirror_reference_point = reference_point_location.map(|point| point + normal * offset);
// TODO: In this None case, use the input's local pivot origin point instead of a point relative to its bounding box
(bounding_box[0] + bounding_box[1]) / 2.
});
let mirror_reference_point = reference_point_location + normal * offset;
// Create the reflection matrix // Create the reflection matrix
let reflection = DAffine2::from_mat2_translation( let reflection = DAffine2::from_mat2_translation(
@ -397,25 +392,25 @@ where
); );
// Apply reflection around the reference point // Apply reflection around the reference point
let transform = DAffine2::from_translation(mirror_reference_point) * reflection * DAffine2::from_translation(-mirror_reference_point); let reflected_transform = if let Some(mirror_reference_point) = mirror_reference_point {
DAffine2::from_translation(mirror_reference_point) * reflection * DAffine2::from_translation(-mirror_reference_point)
} else {
reflection * DAffine2::from_translation(DVec2::from_angle(angle.to_radians()) * DVec2::splat(-offset))
};
// Add original instance depending on the keep_original flag // Add original instance depending on the keep_original flag
if keep_original { if keep_original {
result_table.push(Instance { for instance in instance.clone().instance_iter() {
instance: instance.to_graphic_element().clone(), result_table.push(instance);
transform: DAffine2::IDENTITY, }
alpha_blending: Default::default(),
source_node_id: None,
});
} }
// Create and add mirrored instance // Create and add mirrored instance
result_table.push(Instance { for mut instance in instance.instance_iter() {
instance: instance.to_graphic_element(), instance.transform = reflected_transform * instance.transform;
transform, instance.source_node_id = None;
alpha_blending: Default::default(), result_table.push(instance);
source_node_id: None, }
});
result_table result_table
} }