1#![deny(missing_docs)]
2
3mod animation;
12mod convert;
13mod path;
14mod style;
15
16pub use animation::{Animation, AnimationFrame, AnimationState};
17pub use path::IndexedPath;
18pub use style::{FillStyle, StrokeStyle};
19
20use data_stream::{FromStream, ToStream, collections::SizeSettings, from_stream, to_stream};
21use femto_g::{Canvas, Renderer};
22use ga2::Vector;
23use inner_space::distance;
24use touch_selection::Selector;
25use vector_editor_core::{PointObject, SelectSettings};
26
27use std::io::{Read, Result, Write};
28
29#[derive(Clone, Default)]
31pub struct PathList {
32 paths: Vec<IndexedPath>,
33}
34
35impl PathList {
36 pub fn new() -> Self {
38 Self { paths: Vec::new() }
39 }
40}
41
42impl SelectSettings<Vector<f32>> for PathList {
43 #[inline]
44 fn grab_distance(&self) -> f32 {
45 1.0
46 }
47}
48
49impl<S: SizeSettings> ToStream<S> for PathList {
50 fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
51 to_stream::<S, _, _>(&self.paths, stream)
52 }
53}
54
55impl<S: SizeSettings> FromStream<S> for PathList {
56 fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
57 Ok(Self {
58 paths: from_stream::<S, _, _>(stream)?,
59 })
60 }
61}
62
63pub type VectorMesh = PointObject<Vector<f32>, PathList>;
67
68pub trait VectorMeshExtensions: Sized {
70 fn set_animation(&mut self, animation: &Animation, state: &AnimationState);
72
73 fn add_path(&mut self, path: IndexedPath);
75
76 fn render<R: Renderer>(&self, canvas: &mut Canvas<R>);
78}
79
80impl VectorMeshExtensions for VectorMesh {
81 fn set_animation(&mut self, animation: &Animation, state: &AnimationState) {
82 animation.set_shape(&mut self.points, state);
83 }
84
85 fn add_path(&mut self, path: IndexedPath) {
86 self.options.paths.push(path);
87 }
88
89 fn render<R: Renderer>(&self, canvas: &mut Canvas<R>) {
90 for indexed_path in &self.options.paths {
91 indexed_path.render(canvas, &self.points);
92 }
93 }
94}
95
96pub struct SelectionEditor {
98 move_distance: f32,
99 snapping: Option<i8>,
100}
101
102fn snap(pos: Vector<f32>, f: f32) -> Vector<f32> {
103 let Vector { x, y } = pos;
104 Vector::new((x / f).round(), (y / f).round()) * f
105}
106
107impl SelectionEditor {
108 pub fn new() -> Self {
110 Self {
111 move_distance: 0x10 as f32,
112 snapping: Some(0),
113 }
114 }
115}
116
117impl Default for SelectionEditor {
118 fn default() -> Self {
119 Self::new()
120 }
121}
122
123impl Selector for SelectionEditor {
124 type Selectable = VectorMesh;
125 type Position = Vector<f32>;
126
127 fn moved(&self, moved: Vector<f32>, cursor: Vector<f32>) -> bool {
128 distance(moved, cursor) >= self.move_distance
129 }
130
131 fn stop(&self, selectable: &mut Self::Selectable, index: usize) {
132 if let Some(snapping) = self.snapping {
133 let pos = &mut selectable.points[index];
134 *pos = snap(*pos, 2.0f32.powi(snapping as i32));
135 }
136 }
137}