Skip to content

Commit b004f03

Browse files
committedMar 19, 2025
init
1 parent 08a4b69 commit b004f03

File tree

4 files changed

+46
-0
lines changed

4 files changed

+46
-0
lines changed
 

‎editor/src/messages/portfolio/document/node_graph/node_properties.rs

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ pub(crate) fn property_from_type(
125125
Some("Percentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(0.)).max(max(100.)), true).into(),
126126
Some("SignedPercentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(-100.)).max(max(100.)), true).into(),
127127
Some("Angle") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(-180.)).max(max(180.)).unit("°"), true).into(),
128+
Some("AngularDistance") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(0.)).max(max(360.)).unit("°"), true).into(),
128129
Some("PixelLength") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).unit(" px"), true).into(),
129130
Some("Length") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)), true).into(),
130131
Some("Fraction") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).max(max(1.)), true).into(),

‎libraries/bezier-rs/src/subpath/core.rs

+33
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,39 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
293293
Self::new(manipulator_groups, true)
294294
}
295295

296+
/// Constructs an arc by a `radius`, `angle_start` and `angle_size`. Angles must be in radians.
297+
pub fn new_arc(radius: f64, angle_start: f64, angle_size: f64) -> Self {
298+
let center = DVec2::new(0., 0.);
299+
let segments = (angle_size.abs() / (std::f64::consts::PI / 4.)).ceil() as usize;
300+
let step = angle_size / segments as f64;
301+
let half_step = step / 2.;
302+
let factor = 4. / 3. * half_step.sin() / (1. + half_step.cos());
303+
304+
let mut manipulator_groups = Vec::with_capacity(segments);
305+
let mut prev_in_handle = None;
306+
let mut prev_end = DVec2::new(0., 0.);
307+
308+
for i in 0..segments {
309+
let start_angle = angle_start + step * i as f64;
310+
let end_angle = start_angle + step;
311+
let start_vec = DVec2::from_angle(start_angle);
312+
let end_vec = DVec2::from_angle(end_angle);
313+
314+
let start = center + radius * start_vec;
315+
let end = center + radius * end_vec;
316+
317+
let handle_start = start + start_vec.perp() * radius * factor;
318+
let handle_end = end - end_vec.perp() * radius * factor;
319+
320+
manipulator_groups.push(ManipulatorGroup::new(start, prev_in_handle, Some(handle_start)));
321+
prev_in_handle = Some(handle_end);
322+
prev_end = end;
323+
}
324+
manipulator_groups.push(ManipulatorGroup::new(prev_end, prev_in_handle, None));
325+
326+
Self::new(manipulator_groups, false)
327+
}
328+
296329
/// Constructs a regular polygon (ngon). Based on `sides` and `radius`, which is the distance from the center to any vertex.
297330
pub fn new_regular_polygon(center: DVec2, sides: u64, radius: f64) -> Self {
298331
let sides = sides.max(3);

‎node-graph/gcore/src/registry.rs

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ pub mod types {
1414
pub type SignedPercentage = f64;
1515
/// -180° - 180°
1616
pub type Angle = f64;
17+
/// 0° - 360°
18+
pub type AngularDistance = f64;
1719
/// Non-negative integer with px unit
1820
pub type PixelLength = f64;
1921
/// Non-negative

‎node-graph/gcore/src/vector/generator_nodes.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::Ctx;
2+
use crate::registry::types::{Angle, AngularDistance};
23
use crate::vector::{HandleId, VectorData, VectorDataTable};
34
use bezier_rs::Subpath;
45
use glam::DVec2;
@@ -40,6 +41,15 @@ fn circle(_: impl Ctx, _primary: (), #[default(50.)] radius: f64) -> VectorDataT
4041
VectorDataTable::new(VectorData::from_subpath(Subpath::new_ellipse(DVec2::splat(-radius), DVec2::splat(radius))))
4142
}
4243

44+
#[node_macro::node(category("Vector: Shape"))]
45+
fn arc(_: impl Ctx, _primary: (), #[default(50.)] radius: f64, start_angle: Angle, #[default(90.)] angle_size: AngularDistance) -> VectorDataTable {
46+
VectorDataTable::new(VectorData::from_subpath(Subpath::new_arc(
47+
radius,
48+
start_angle / 360. * std::f64::consts::TAU,
49+
angle_size / 360. * std::f64::consts::TAU,
50+
)))
51+
}
52+
4353
#[node_macro::node(category("Vector: Shape"))]
4454
fn ellipse(_: impl Ctx, _primary: (), #[default(50)] radius_x: f64, #[default(25)] radius_y: f64) -> VectorDataTable {
4555
let radius = DVec2::new(radius_x, radius_y);

0 commit comments

Comments
 (0)
Failed to load comments.