Skip to content

Commit 7aa0476

Browse files
committed
Adds a Toggle for Inner Radius in Polygon tool
1 parent 203910a commit 7aa0476

File tree

4 files changed

+80
-30
lines changed

4 files changed

+80
-30
lines changed

editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/number_of_points_dial.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::messages::tool::common_functionality::shapes::shape_utility::{extract
1313
use glam::{DAffine2, DVec2};
1414
use graph_craft::document::NodeInput;
1515
use graph_craft::document::value::TaggedValue;
16+
use graphene_std::vector::generator_nodes::calculate_effective_radius;
1617
use std::collections::VecDeque;
1718
use std::f64::consts::TAU;
1819

@@ -68,11 +69,12 @@ impl NumberOfPointsDial {
6869
}
6970

7071
// Polygon
71-
if let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) {
72+
if let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) {
7273
let viewport = document.metadata().transform_to_viewport(layer);
7374
let center = viewport.transform_point2(DVec2::ZERO);
7475

75-
let point_on_max_radius = polygon_vertex_position(viewport, 0, sides, radius);
76+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
77+
let point_on_max_radius = polygon_vertex_position(viewport, 0, sides, effective_radius);
7678

7779
if mouse_position.distance(center) < NUMBER_OF_POINTS_DIAL_SPOKE_LENGTH && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
7880
self.layer = Some(layer);
@@ -122,7 +124,7 @@ impl NumberOfPointsDial {
122124
}
123125

124126
// Polygon
125-
if let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) {
127+
if let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) {
126128
let viewport = document.metadata().transform_to_viewport(layer);
127129
let center = viewport.transform_point2(DVec2::ZERO);
128130

@@ -131,10 +133,11 @@ impl NumberOfPointsDial {
131133
{
132134
return;
133135
}
134-
let point_on_max_radius = polygon_vertex_position(viewport, 0, sides, radius);
136+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
137+
let point_on_max_radius = polygon_vertex_position(viewport, 0, sides, effective_radius);
135138

136-
if inside_polygon(viewport, sides, radius, mouse_position) && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
137-
self.draw_spokes(center, viewport, sides, radius, overlay_context);
139+
if inside_polygon(viewport, sides, effective_radius, mouse_position) && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
140+
self.draw_spokes(center, viewport, sides, effective_radius, overlay_context);
138141
}
139142
}
140143
}
@@ -144,10 +147,12 @@ impl NumberOfPointsDial {
144147
};
145148

146149
// Get the star's greater radius or polygon's radius, as well as the number of sides
147-
let Some((sides, radius)) = extract_star_parameters(Some(layer), document)
148-
.map(|(sides, r1, r2)| (sides, r1.max(r2)))
149-
.or_else(|| extract_polygon_parameters(Some(layer), document))
150-
else {
150+
let Some((sides, radius)) = extract_star_parameters(Some(layer), document).map(|(sides, r1, r2)| (sides, r1.max(r2))).or_else(|| {
151+
extract_polygon_parameters(Some(layer), document).map(|(sides, radius, is_inner_radius)| {
152+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
153+
(sides, effective_radius)
154+
})
155+
}) else {
151156
return;
152157
};
153158

editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/point_radius_handle.rs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ use crate::messages::prelude::FrontendMessage;
99
use crate::messages::prelude::Responses;
1010
use crate::messages::prelude::{DocumentMessageHandler, InputPreprocessorMessageHandler, NodeGraphMessage};
1111
use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer};
12-
use crate::messages::tool::common_functionality::shapes::shape_utility::{draw_snapping_ticks, extract_polygon_parameters, polygon_outline, polygon_vertex_position, star_outline};
13-
use crate::messages::tool::common_functionality::shapes::shape_utility::{extract_star_parameters, star_vertex_position};
12+
use crate::messages::tool::common_functionality::shapes::shape_utility::{
13+
draw_snapping_ticks, extract_polygon_parameters, extract_star_parameters, polygon_edge_midpoint, polygon_outline, polygon_vertex_position, star_outline, star_vertex_position,
14+
};
1415
use glam::DVec2;
1516
use graph_craft::document::NodeInput;
1617
use graph_craft::document::value::TaggedValue;
18+
use graphene_std::vector::calculate_effective_radius;
1719
use std::collections::VecDeque;
1820
use std::f64::consts::{FRAC_1_SQRT_2, FRAC_PI_4, PI, SQRT_2};
1921

@@ -87,11 +89,16 @@ impl PointRadiusHandle {
8789
}
8890

8991
// Draw the point handle gizmo for the polygon shape
90-
if let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) {
92+
if let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) {
9193
let viewport = document.metadata().transform_to_viewport(layer);
94+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
9295

9396
for i in 0..sides {
94-
let point = polygon_vertex_position(viewport, i as i32, sides, radius);
97+
let point = if is_inner_radius {
98+
polygon_edge_midpoint(viewport, i as i32, sides, radius)
99+
} else {
100+
polygon_vertex_position(viewport, i as i32, sides, effective_radius)
101+
};
95102
let center = viewport.transform_point2(DVec2::ZERO);
96103

97104
// If the user zooms out such that shape is very small hide the gizmo
@@ -130,8 +137,13 @@ impl PointRadiusHandle {
130137
}
131138

132139
// Polygon
133-
if let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) {
134-
let point = polygon_vertex_position(viewport, self.point as i32, sides, radius);
140+
if let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) {
141+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
142+
let point = if is_inner_radius {
143+
polygon_edge_midpoint(viewport, self.point as i32, sides, radius)
144+
} else {
145+
polygon_vertex_position(viewport, self.point as i32, sides, effective_radius)
146+
};
135147

136148
if matches!(&self.handle_state, PointRadiusHandleState::Hover) && (mouse_position - point).length() > 5. {
137149
self.update_state(PointRadiusHandleState::Inactive);
@@ -166,11 +178,16 @@ impl PointRadiusHandle {
166178
}
167179

168180
// Draw the point handle gizmo for the Polygon shape
169-
if let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) {
181+
if let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) {
170182
let viewport = document.metadata().transform_to_viewport(layer);
183+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
171184

172185
for i in 0..sides {
173-
let point = polygon_vertex_position(viewport, i as i32, sides, radius);
186+
let point = if is_inner_radius {
187+
polygon_edge_midpoint(viewport, i as i32, sides, radius)
188+
} else {
189+
polygon_vertex_position(viewport, i as i32, sides, effective_radius)
190+
};
174191
let center = viewport.transform_point2(DVec2::ZERO);
175192

176193
// If the user zooms out such that shape is very small hide the gizmo
@@ -211,8 +228,13 @@ impl PointRadiusHandle {
211228
}
212229

213230
// Polygon
214-
if let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) {
215-
let point = polygon_vertex_position(viewport, self.point as i32, sides, radius);
231+
if let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) {
232+
let effective_radius = calculate_effective_radius(radius, sides, is_inner_radius);
233+
let point = if is_inner_radius {
234+
polygon_edge_midpoint(viewport, self.point as i32, sides, radius)
235+
} else {
236+
polygon_vertex_position(viewport, self.point as i32, sides, effective_radius)
237+
};
216238

217239
let Some(direction) = (point - center).try_normalize() else { return };
218240

@@ -421,13 +443,14 @@ impl PointRadiusHandle {
421443
};
422444

423445
let viewport_transform = document.network_interface.document_metadata().transform_to_viewport(layer);
424-
let center = viewport_transform.transform_point2(DVec2::ZERO);
446+
425447
let radius_index = self.radius_index;
426448

427449
let original_radius = self.initial_radius;
428450

429-
let delta = viewport_transform.inverse().transform_point2(input.mouse.position) - viewport_transform.inverse().transform_point2(drag_start);
430-
let radius = drag_start - center;
451+
let drag_start = viewport_transform.inverse().transform_point2(drag_start);
452+
let delta = viewport_transform.inverse().transform_point2(input.mouse.position) - drag_start;
453+
let radius = drag_start;
431454
let projection = delta.project_onto(radius);
432455
let sign = radius.dot(delta).signum();
433456

editor/src/messages/tool/common_functionality/shapes/shape_utility.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use graph_craft::document::NodeInput;
1818
use graph_craft::document::value::TaggedValue;
1919
use graphene_std::NodeInputDecleration;
2020
use graphene_std::subpath::{self, Subpath};
21+
use graphene_std::vector::calculate_effective_radius;
2122
use graphene_std::vector::click_target::ClickTargetType;
2223
use graphene_std::vector::misc::{ArcType, GridType, SpiralType, dvec2_to_point};
2324
use kurbo::{BezPath, PathEl, Shape};
@@ -300,15 +301,26 @@ pub fn extract_star_parameters(layer: Option<LayerNodeIdentifier>, document: &Do
300301

301302
/// Extract the node input values of Polygon.
302303
/// Returns an option of (sides, radius).
303-
pub fn extract_polygon_parameters(layer: Option<LayerNodeIdentifier>, document: &DocumentMessageHandler) -> Option<(u32, f64)> {
304+
pub fn extract_polygon_parameters(layer: Option<LayerNodeIdentifier>, document: &DocumentMessageHandler) -> Option<(u32, f64, bool)> {
304305
let node_inputs =
305306
NodeGraphLayer::new(layer?, &document.network_interface).find_node_inputs(&DefinitionIdentifier::ProtoNode(graphene_std::vector::generator_nodes::regular_polygon::IDENTIFIER))?;
306307

307-
let (Some(&TaggedValue::U32(n)), Some(&TaggedValue::F64(radius))) = (node_inputs.get(1)?.as_value(), node_inputs.get(2)?.as_value()) else {
308+
let (Some(&TaggedValue::U32(n)), Some(&TaggedValue::F64(radius)), Some(&TaggedValue::Bool(is_inner_radius))) =
309+
(node_inputs.get(1)?.as_value(), node_inputs.get(2)?.as_value(), node_inputs.get(3)?.as_value())
310+
else {
308311
return None;
309312
};
310313

311-
Some((n, radius))
314+
Some((n, radius, is_inner_radius))
315+
}
316+
317+
pub fn polygon_edge_midpoint(viewport: DAffine2, edge_index: i32, n: u32, radius: f64) -> DVec2 {
318+
let angle = ((edge_index as f64 + 0.5) * TAU) / (n as f64);
319+
320+
viewport.transform_point2(DVec2 {
321+
x: radius * angle.sin(),
322+
y: -radius * angle.cos(),
323+
})
312324
}
313325

314326
/// Extract the node input values of an arc.
@@ -434,14 +446,14 @@ pub fn star_outline(layer: Option<LayerNodeIdentifier>, document: &DocumentMessa
434446
/// Outlines the geometric shape made by polygon-node
435447
pub fn polygon_outline(layer: Option<LayerNodeIdentifier>, document: &DocumentMessageHandler, overlay_context: &mut OverlayContext) {
436448
let Some(layer) = layer else { return };
437-
let Some((sides, radius)) = extract_polygon_parameters(Some(layer), document) else {
449+
let Some((sides, radius, is_inner_radius)) = extract_polygon_parameters(Some(layer), document) else {
438450
return;
439451
};
440452

441453
let viewport = document.metadata().transform_to_viewport(layer);
442454

443455
let points = sides as u64;
444-
let radius: f64 = radius * 2.;
456+
let radius: f64 = calculate_effective_radius(radius, sides, is_inner_radius) * 2.;
445457

446458
let subpath: Vec<ClickTargetType> = vec![ClickTargetType::Subpath(Subpath::new_regular_polygon(DVec2::splat(-radius), points, radius))];
447459

node-graph/nodes/vector/src/generator_nodes.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,20 @@ fn regular_polygon<T: AsU64>(
158158
#[unit(" px")]
159159
#[default(50)]
160160
radius: f64,
161+
#[default(false)] is_inner_radius: bool,
161162
) -> Table<Vector> {
162163
let points = sides.as_u64();
163-
let radius: f64 = radius * 2.;
164-
Table::new_from_element(Vector::from_subpath(subpath::Subpath::new_regular_polygon(DVec2::splat(-radius), points, radius)))
164+
let effective_radius = calculate_effective_radius(radius, sides.as_u64() as u32, is_inner_radius) * 2.;
165+
Table::new_from_element(Vector::from_subpath(subpath::Subpath::new_regular_polygon(DVec2::splat(-effective_radius), points, effective_radius)))
166+
}
167+
168+
pub fn calculate_effective_radius(radius: f64, sides: u32, is_inner: bool) -> f64 {
169+
if is_inner {
170+
let cosine = (std::f64::consts::PI / sides as f64).cos();
171+
if cosine.abs() > 1e-6 { radius / cosine } else { radius }
172+
} else {
173+
radius
174+
}
165175
}
166176

167177
/// Generates an n-pointed star shape with inner and outer points at chosen radii from the center.

0 commit comments

Comments
 (0)