Skip to content

Commit 8a795a9

Browse files
authored
Iterator Implementations and fixes (#637)
* Refactoring: disentangle kurbo from apply_affine * Broke boolean operations, refactor in state which compiles * "fixed" boolean operation refactor related errors * fixed apply_affine, which would not have applied any type of affine * implemented transforms for VectorAnchors implemented Not for VectorControlPointType * started adding Vector Shape implementations of shape prototypes * added several useful implemtations to UniqueElements * added another implemnation for UniqueElements to make working with iterators easier, fixed vector-shape errors * package-lock.json * clean up rebase, added back Layer paths * added deref implementation for VectorShape * unnecesary variable * simplify code by removing levels of indirection * fixed errors
1 parent 1fd964c commit 8a795a9

File tree

10 files changed

+208
-108
lines changed

10 files changed

+208
-108
lines changed

editor/src/viewport_tools/tools/shape_tool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl Fsm for ShapeToolFsmState {
161161
path: shape_data.path.clone().unwrap(),
162162
insert_index: -1,
163163
transform: DAffine2::ZERO.to_cols_array(),
164-
sides: data.sides,
164+
sides: data.sides.into(),
165165
style: style::PathStyle::new(None, Some(style::Fill::new(tool_data.primary_color))),
166166
}
167167
.into(),

editor/src/viewport_tools/vector_editor/shape_editor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl ShapeEditor {
144144

145145
/// A mutable iterator of all the anchors, regardless of selection
146146
pub fn anchors_mut(&mut self) -> impl Iterator<Item = &mut VectorAnchor> {
147-
self.copy_of_shapes.iter_mut().flat_map(|shape| shape.anchors_mut())
147+
self.copy_of_shapes.iter_mut().flat_map(|shape| shape.iter_mut())
148148
}
149149

150150
/// Select the last anchor in this shape

graphene/src/layers/id_storage.rs

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::collections::HashMap;
1+
use std::{
2+
collections::HashMap,
3+
ops::{Deref, DerefMut},
4+
};
25

36
use crate::DocumentError;
47
use serde::{Deserialize, Serialize};
@@ -9,7 +12,7 @@ type ElementIndex = i64;
912
/// A layer that encapsulates other layers, including potentially more folders.
1013
/// The contained layers are rendered in the same order they are
1114
/// stored in the [layers](PathStorage::layers) field.
12-
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Default)]
15+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1316

1417
// TODO: Default is a bit weird because Layer does not implement Default. but we should not care because the empty vec is the default
1518
pub struct UniqueElements<T> {
@@ -62,17 +65,16 @@ impl<T> UniqueElements<T> {
6265
}
6366
}
6467

65-
let id = self.next_assignment_id;
6668
self.values.insert(insert_index as usize, element);
67-
self.keys.insert(insert_index as usize, id);
68-
self.id_to_index.insert(id, insert_index);
69+
self.keys.insert(insert_index as usize, self.next_assignment_id);
70+
self.id_to_index.insert(self.next_assignment_id, insert_index);
6971

7072
// Linear probing for collision avoidance
7173
while self.id_to_index.contains_key(&self.next_assignment_id) {
7274
self.next_assignment_id += 1;
7375
}
7476

75-
Some(id)
77+
Some(self.next_assignment_id)
7678
} else {
7779
None
7880
}
@@ -109,15 +111,16 @@ impl<T> UniqueElements<T> {
109111
self.keys.as_slice()
110112
}
111113

112-
/// Get references to all the [T]s in the within this container.
113-
pub fn values(&self) -> &[T] {
114-
self.values.as_slice()
115-
}
114+
/// These can be replaced by implementing Deref I think
115+
// /// Get references to all the [T]s in the within this container.
116+
// pub fn values(&self) -> &[T] {
117+
// self.values.as_slice()
118+
// }
116119

117-
/// Get mutable references to all the [T]s in the within this container.
118-
pub fn values_mut(&mut self) -> &mut [T] {
119-
self.values.as_mut_slice()
120-
}
120+
// /// Get mutable references to all the [T]s in the within this container.
121+
// pub fn values_mut(&mut self) -> &mut [T] {
122+
// self.values.as_mut_slice()
123+
// }
121124

122125
/// Get a single element with a given element ID from the within this container.
123126
pub fn by_id(&self, id: ElementId) -> Option<&T> {
@@ -216,3 +219,49 @@ impl<T> UniqueElements<T> {
216219
Err(DocumentError::LayerNotFound([element_id].into()))
217220
}
218221
}
222+
223+
impl<T> Default for UniqueElements<T> {
224+
fn default() -> Self {
225+
UniqueElements {
226+
keys: vec![],
227+
values: vec![],
228+
next_assignment_id: 0,
229+
id_to_index: HashMap::new(),
230+
}
231+
}
232+
}
233+
234+
impl<T> Deref for UniqueElements<T> {
235+
type Target = [T];
236+
fn deref(&self) -> &Self::Target {
237+
&self.values
238+
}
239+
}
240+
241+
impl<T> DerefMut for UniqueElements<T> {
242+
fn deref_mut(&mut self) -> &mut Self::Target {
243+
&mut self.values
244+
}
245+
}
246+
247+
/// allows use with iterators
248+
/// also allows constructing UniqueElements with collect
249+
impl<A> FromIterator<A> for UniqueElements<A> {
250+
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
251+
let mut new = UniqueElements::default();
252+
iter.into_iter().for_each(|element| match new.add(element, None, -1) {
253+
_ => (), // attempt to add all elements, even if one fails
254+
});
255+
new
256+
}
257+
}
258+
259+
impl<'b, 'a: 'b, A: 'a + Clone> FromIterator<&'b A> for UniqueElements<A> {
260+
fn from_iter<T: IntoIterator<Item = &'b A>>(iter: T) -> Self {
261+
let mut new = UniqueElements::default();
262+
iter.into_iter().for_each(|element| match new.add(element.clone(), None, -1) {
263+
_ => (), // attempt to add all elements, even if one fails
264+
});
265+
new
266+
}
267+
}

graphene/src/layers/shape_layer.rs

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -78,33 +78,10 @@ impl ShapeLayer {
7878
}
7979
}
8080

81-
pub fn ngon(sides: u8, style: PathStyle) -> Self {
82-
use std::f64::consts::{FRAC_PI_2, TAU};
83-
84-
fn unit_rotation(theta: f64) -> DVec2 {
85-
DVec2::new(theta.sin(), theta.cos())
86-
}
87-
88-
let mut path = kurbo::BezPath::new();
89-
90-
let apothem_offset_angle = TAU / (sides as f64);
91-
// Rotate odd sided shapes by 90 degrees
92-
let offset = ((sides + 1) % 2) as f64 * FRAC_PI_2;
93-
94-
let relative_points = (0..sides).map(|i| apothem_offset_angle * i as f64 + offset).map(unit_rotation);
95-
96-
let min = relative_points.clone().reduce(|a, b| a.min(b)).unwrap_or_default();
97-
let transform = DAffine2::from_scale_angle_translation(DVec2::ONE / 2., 0., -min / 2.);
98-
let point = |vec: DVec2| kurbo::Point::new(vec.x, vec.y);
99-
100-
let mut relative_points = relative_points.map(|p| point(transform.transform_point2(p)));
101-
path.move_to(relative_points.next().expect("Tried to create an ngon with 0 sides"));
102-
relative_points.for_each(|p| path.line_to(p));
103-
104-
path.close_path();
105-
81+
/// TODO The behavior of ngon changed from the previous iteration slightly
82+
pub fn ngon(sides: u64, style: PathStyle) -> Self {
10683
Self {
107-
shape: path.iter().into(),
84+
shape: VectorShape::new_ngon(DVec2::new(0., 0.), sides, 1.),
10885
style,
10986
render_index: 1,
11087
closed: true,
@@ -113,7 +90,7 @@ impl ShapeLayer {
11390

11491
pub fn rectangle(style: PathStyle) -> Self {
11592
Self {
116-
shape: VectorShape::from_kurbo_shape(&kurbo::Rect::new(0., 0., 1., 1.).to_path(0.01)),
93+
shape: VectorShape::new_rect(DVec2::new(0., 0.), DVec2::new(1., 1.)),
11794
style,
11895
render_index: 1,
11996
closed: true,
@@ -131,24 +108,16 @@ impl ShapeLayer {
131108

132109
pub fn line(style: PathStyle) -> Self {
133110
Self {
134-
shape: VectorShape::from_kurbo_shape(&kurbo::Line::new((0., 0.), (1., 0.)).to_path(0.01)),
111+
shape: VectorShape::new_line(DVec2::new(0., 0.), DVec2::new(1., 0.)),
135112
style,
136113
render_index: 1,
137114
closed: false,
138115
}
139116
}
140117

141118
pub fn poly_line(points: Vec<impl Into<glam::DVec2>>, style: PathStyle) -> Self {
142-
let mut path = kurbo::BezPath::new();
143-
points
144-
.into_iter()
145-
.map(|v| v.into())
146-
.map(|v: DVec2| kurbo::Point { x: v.x, y: v.y })
147-
.enumerate()
148-
.for_each(|(i, p)| if i == 0 { path.move_to(p) } else { path.line_to(p) });
149-
150119
Self {
151-
shape: path.iter().into(),
120+
shape: VectorShape::new_poly_line(points),
152121
style,
153122
render_index: 0,
154123
closed: false,

graphene/src/layers/vector/constants.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::ops::{Index, IndexMut};
1+
use std::{
2+
ops::{Index, IndexMut, Not},
3+
thread::JoinHandle,
4+
};
25

36
use serde::{Deserialize, Serialize};
47

@@ -10,7 +13,18 @@ pub enum ControlPointType {
1013
Handle2 = 2,
1114
}
1215

13-
// Allows us to use ControlPointType for indexing
16+
impl Not for ControlPointType {
17+
type Output = Self;
18+
fn not(self) -> Self::Output {
19+
match self {
20+
ControlPointType::Handle1 => ControlPointType::Handle2,
21+
ControlPointType::Handle2 => ControlPointType::Handle1,
22+
_ => ControlPointType::Anchor,
23+
}
24+
}
25+
}
26+
27+
// Allows us to use ManipulatorType for indexing
1428
impl<T> Index<ControlPointType> for [T; 3] {
1529
type Output = T;
1630
fn index(&self, mt: ControlPointType) -> &T {

graphene/src/layers/vector/vector_anchor.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,17 @@ impl VectorAnchor {
6868
closest_index
6969
}
7070

71-
// TODO change relative to an enum (relative, absolute)
72-
/// Move the selected points by the provided delta
73-
pub fn move_selected_points(&mut self, translation: DVec2, relative: bool, transform: &DAffine2) {
74-
// TODO This needs to be rebuilt without usage of kurbo
75-
// Move associated handles
71+
/// Move the selected points by the provided transform
72+
/// if relative is false the point is transformed and its original position is subtracted
73+
pub fn move_selected_points(&mut self, relative: bool, transform: &DAffine2) {
74+
for point in self.selected_points_mut() {
75+
if !relative {
76+
let copy = point.clone().position;
77+
point.transform(transform);
78+
point.move_by(&(-copy));
79+
}
80+
point.transform(transform);
81+
}
7682
}
7783

7884
/// Returns true if any points in this anchor are selected
@@ -104,12 +110,12 @@ impl VectorAnchor {
104110
}
105111
}
106112

107-
/// Provides the selected points in this anchor
113+
/// Provides the points in this anchor
108114
pub fn points(&self) -> impl Iterator<Item = &VectorControlPoint> {
109115
self.points.iter().flatten()
110116
}
111117

112-
/// Returns
118+
/// Provides the selected points in this anchor
113119
pub fn selected_points(&self) -> impl Iterator<Item = &VectorControlPoint> {
114120
self.points.iter().flatten().filter(|pnt| pnt.is_selected)
115121
}
@@ -128,19 +134,9 @@ impl VectorAnchor {
128134
}
129135

130136
/// Returns the opposing handle to the handle provided
137+
/// Returns the anchor handle if the anchor is provided
131138
pub fn opposing_handle(&self, handle: &VectorControlPoint) -> &Option<VectorControlPoint> {
132-
if let Some(point) = &self.points[ControlPointType::Handle1] {
133-
if point == handle {
134-
return &self.points[ControlPointType::Handle2];
135-
}
136-
};
137-
138-
if let Some(point) = &self.points[ControlPointType::Handle2] {
139-
if point == handle {
140-
return &self.points[ControlPointType::Handle1];
141-
}
142-
};
143-
&None
139+
&self.points[!handle.manipulator_type]
144140
}
145141

146142
/// Set the mirroring state

graphene/src/layers/vector/vector_control_point.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::constants::ControlPointType;
2-
use glam::DVec2;
2+
use glam::{DAffine2, DVec2};
33
use serde::{Deserialize, Serialize};
44

55
/// VectorControlPoint represents any grabbable point, anchor or handle
@@ -44,8 +44,13 @@ impl VectorControlPoint {
4444
self.is_selected = selected;
4545
}
4646

47+
/// apply given transform
48+
pub fn transform(&mut self, delta: &DAffine2) {
49+
self.position = delta.transform_point2(self.position);
50+
}
51+
4752
/// Move by a delta amount
48-
pub fn move_by(&mut self, delta: DVec2) {
49-
self.position += delta;
53+
pub fn move_by(&mut self, delta: &DVec2) {
54+
self.position += *delta;
5055
}
5156
}

0 commit comments

Comments
 (0)