Minor fixes for 'Round Corners' and 'Mirror' nodes (#2510)
* Fix round corners node not properly maintaing click targets, added keep_original bool to mirror node * Fixed fix for the theta angle * Add upgrade script for Mirror node --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
412dfc293a
commit
81db769737
|
|
@ -806,6 +806,22 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||||
.set_input(&InputConnector::node(*node_id, 2), NodeInput::value(TaggedValue::Bool(false), false), network_path);
|
.set_input(&InputConnector::node(*node_id, 2), NodeInput::value(TaggedValue::Bool(false), false), network_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upgrade the Mirror node to add the `keep_original` boolean input
|
||||||
|
if reference == "Mirror" && inputs_count == 3 {
|
||||||
|
let node_definition = resolve_document_node_type(reference).unwrap();
|
||||||
|
let document_node = node_definition.default_node_template().document_node;
|
||||||
|
document.network_interface.replace_implementation(node_id, network_path, document_node.implementation.clone());
|
||||||
|
|
||||||
|
let old_inputs = document.network_interface.replace_inputs(node_id, document_node.inputs.clone(), network_path);
|
||||||
|
|
||||||
|
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
|
||||||
|
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
||||||
|
document.network_interface.set_input(&InputConnector::node(*node_id, 2), old_inputs[2].clone(), network_path);
|
||||||
|
document
|
||||||
|
.network_interface
|
||||||
|
.set_input(&InputConnector::node(*node_id, 3), NodeInput::value(TaggedValue::Bool(true), false), network_path);
|
||||||
|
}
|
||||||
|
|
||||||
// Upgrade artboard name being passed as hidden value input to "To Artboard"
|
// Upgrade artboard name being passed as hidden value input to "To Artboard"
|
||||||
if reference == "Artboard" && upgrade_from_before_returning_nested_click_targets {
|
if reference == "Artboard" && upgrade_from_before_returning_nested_click_targets {
|
||||||
let label = document.network_interface.frontend_display_name(node_id, network_path);
|
let label = document.network_interface.frontend_display_name(node_id, network_path);
|
||||||
|
|
|
||||||
|
|
@ -342,17 +342,21 @@ async fn mirror<I: 'n + Send>(
|
||||||
#[implementations(VectorDataTable, GraphicGroupTable)] instance: Instances<I>,
|
#[implementations(VectorDataTable, GraphicGroupTable)] instance: Instances<I>,
|
||||||
#[default(0., 0.)] center: DVec2,
|
#[default(0., 0.)] center: DVec2,
|
||||||
#[range((-90., 90.))] angle: Angle,
|
#[range((-90., 90.))] angle: Angle,
|
||||||
|
#[default(true)] keep_original: bool,
|
||||||
) -> GraphicGroupTable
|
) -> GraphicGroupTable
|
||||||
where
|
where
|
||||||
Instances<I>: GraphicElementRendered,
|
Instances<I>: GraphicElementRendered,
|
||||||
{
|
{
|
||||||
let mut result_table = GraphicGroupTable::default();
|
let mut result_table = GraphicGroupTable::default();
|
||||||
let Some(bounding_box) = instance.bounding_box(DAffine2::IDENTITY) else { return result_table };
|
|
||||||
// The mirror center is based on the bounding box for now
|
// The mirror center is based on the bounding box for now
|
||||||
|
let Some(bounding_box) = instance.bounding_box(DAffine2::IDENTITY) else { return result_table };
|
||||||
let mirror_center = (bounding_box[0] + bounding_box[1]) / 2. + center;
|
let mirror_center = (bounding_box[0] + bounding_box[1]) / 2. + center;
|
||||||
// Normalize direction vector
|
|
||||||
|
// Normalize the direction vector
|
||||||
let normal = DVec2::from_angle(angle.to_radians());
|
let normal = DVec2::from_angle(angle.to_radians());
|
||||||
// Create reflection matrix
|
|
||||||
|
// Create the reflection matrix
|
||||||
let reflection = DAffine2::from_mat2_translation(
|
let reflection = DAffine2::from_mat2_translation(
|
||||||
glam::DMat2::from_cols(
|
glam::DMat2::from_cols(
|
||||||
DVec2::new(1. - 2. * normal.x * normal.x, -2. * normal.y * normal.x),
|
DVec2::new(1. - 2. * normal.x * normal.x, -2. * normal.y * normal.x),
|
||||||
|
|
@ -360,15 +364,20 @@ where
|
||||||
),
|
),
|
||||||
DVec2::ZERO,
|
DVec2::ZERO,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Apply reflection around the center point
|
// Apply reflection around the center point
|
||||||
let modification = DAffine2::from_translation(mirror_center) * reflection * DAffine2::from_translation(-mirror_center);
|
let modification = DAffine2::from_translation(mirror_center) * reflection * DAffine2::from_translation(-mirror_center);
|
||||||
// Add original instance to result
|
|
||||||
let original_element = instance.to_graphic_element().clone();
|
// Add original instance depending on the keep_original flag
|
||||||
result_table.push(original_element);
|
if keep_original {
|
||||||
|
result_table.push(instance.to_graphic_element());
|
||||||
|
}
|
||||||
|
|
||||||
// Create and add mirrored instance
|
// Create and add mirrored instance
|
||||||
let mut mirrored_element = instance.to_graphic_element().clone();
|
let mut mirrored_element = instance.to_graphic_element();
|
||||||
mirrored_element.new_ids_from_hash(None);
|
mirrored_element.new_ids_from_hash(None);
|
||||||
// Finally, apply the transformation to the mirrored instance
|
|
||||||
|
// Apply the transformation to the mirrored instance
|
||||||
let mirrored_instance = result_table.push(mirrored_element);
|
let mirrored_instance = result_table.push(mirrored_element);
|
||||||
*mirrored_instance.transform = modification;
|
*mirrored_instance.transform = modification;
|
||||||
|
|
||||||
|
|
@ -393,6 +402,7 @@ async fn round_corners(
|
||||||
let source_transform = source.transform();
|
let source_transform = source.transform();
|
||||||
let source_transform_inverse = source_transform.inverse();
|
let source_transform_inverse = source_transform.inverse();
|
||||||
let source = source.one_instance().instance;
|
let source = source.one_instance().instance;
|
||||||
|
let upstream_graphics_group = source.upstream_graphic_group.clone();
|
||||||
|
|
||||||
// Flip the roundness to help with user intuition
|
// Flip the roundness to help with user intuition
|
||||||
let roundness = 1. - roundness;
|
let roundness = 1. - roundness;
|
||||||
|
|
@ -402,11 +412,14 @@ async fn round_corners(
|
||||||
let mut result = VectorData::empty();
|
let mut result = VectorData::empty();
|
||||||
result.style = source.style.clone();
|
result.style = source.style.clone();
|
||||||
|
|
||||||
|
// Grab the initial point ID as a stable starting point
|
||||||
|
let mut initial_point_id = source.point_domain.ids().first().copied().unwrap_or(PointId::generate());
|
||||||
|
|
||||||
for mut subpath in source.stroke_bezier_paths() {
|
for mut subpath in source.stroke_bezier_paths() {
|
||||||
subpath.apply_transform(source_transform);
|
subpath.apply_transform(source_transform);
|
||||||
|
|
||||||
|
// End if not enough points for corner rounding
|
||||||
if subpath.manipulator_groups().len() < 3 {
|
if subpath.manipulator_groups().len() < 3 {
|
||||||
// Not enough points for corner rounding
|
|
||||||
result.append_subpath(subpath, false);
|
result.append_subpath(subpath, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -450,28 +463,30 @@ async fn round_corners(
|
||||||
let p1 = curr - dir1 * distance_along_edge;
|
let p1 = curr - dir1 * distance_along_edge;
|
||||||
let p2 = curr + dir2 * distance_along_edge;
|
let p2 = curr + dir2 * distance_along_edge;
|
||||||
|
|
||||||
// Add first point with out handle
|
// Add first point (coming into the rounded corner)
|
||||||
new_groups.push(ManipulatorGroup {
|
new_groups.push(ManipulatorGroup {
|
||||||
anchor: p1,
|
anchor: p1,
|
||||||
in_handle: None,
|
in_handle: None,
|
||||||
out_handle: Some(curr - dir1 * distance_along_edge * roundness),
|
out_handle: Some(curr - dir1 * distance_along_edge * roundness),
|
||||||
id: PointId::generate(),
|
id: initial_point_id.next_id(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add second point with in handle
|
// Add second point (coming out of the rounded corner)
|
||||||
new_groups.push(ManipulatorGroup {
|
new_groups.push(ManipulatorGroup {
|
||||||
anchor: p2,
|
anchor: p2,
|
||||||
in_handle: Some(curr + dir2 * distance_along_edge * roundness),
|
in_handle: Some(curr + dir2 * distance_along_edge * roundness),
|
||||||
out_handle: None,
|
out_handle: None,
|
||||||
id: PointId::generate(),
|
id: initial_point_id.next_id(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// One subpath for each shape
|
||||||
let mut rounded_subpath = Subpath::new(new_groups, is_closed);
|
let mut rounded_subpath = Subpath::new(new_groups, is_closed);
|
||||||
rounded_subpath.apply_transform(source_transform_inverse);
|
rounded_subpath.apply_transform(source_transform_inverse);
|
||||||
result.append_subpath(rounded_subpath, false);
|
result.append_subpath(rounded_subpath, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.upstream_graphic_group = upstream_graphics_group;
|
||||||
let mut result_table = VectorDataTable::new(result);
|
let mut result_table = VectorDataTable::new(result);
|
||||||
*result_table.transform_mut() = source_transform;
|
*result_table.transform_mut() = source_transform;
|
||||||
result_table
|
result_table
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue