Skip to content

Commit

Permalink
Refactor away unnecessary generics
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom committed Nov 6, 2023
1 parent e204917 commit 3c19238
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 276 deletions.
11 changes: 3 additions & 8 deletions detailer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@ pub struct State {

pub struct Widget<'a> {
state: &'a mut State,
drawing: &'a mut Data<Feature>,
drawing: &'a mut Data,
handler: &'a mut Handler,
}

impl<'a> Widget<'a> {
pub fn new(
state: &'a mut State,
drawing: &'a mut Data<Feature>,
handler: &'a mut Handler,
) -> Self {
pub fn new(state: &'a mut State, drawing: &'a mut Data, handler: &'a mut Handler) -> Self {
Widget {
state,
drawing,
Expand All @@ -33,7 +29,7 @@ impl<'a> Widget<'a> {
}

pub fn show(mut self, ctx: &egui::Context) {
let mut window = egui::Window::new("Liquid CAD")
let window = egui::Window::new("Liquid CAD")
.id(egui::Id::new("detailer_window"))
.resizable(false)
.constrain(true)
Expand Down Expand Up @@ -86,7 +82,6 @@ impl<'a> Widget<'a> {
}
}

use drawing::CommandHandler;
for c in commands.drain(..) {
self.handler.handle(self.drawing, c);
}
Expand Down
174 changes: 174 additions & 0 deletions drawing/src/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use crate::Feature;
use slotmap::HopSlotMap;
use std::collections::HashMap;

const MAX_HOVER_DISTANCE: f32 = 160.0;

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct Viewport {
pub x: f32,
pub y: f32,
pub zoom: f32,
}

impl Viewport {
pub fn screen_to_point(&self, p: egui::Pos2) -> egui::Pos2 {
egui::Pos2 {
x: self.zoom * p.x + self.x,
y: self.zoom * p.y + self.y,
}
}
pub fn translate_point(&self, p: egui::Pos2) -> egui::Pos2 {
egui::Pos2 {
x: (p.x - self.x) / self.zoom,
y: (p.y - self.y) / self.zoom,
}
}
pub fn translate_rect(&self, r: egui::Rect) -> egui::Rect {
egui::Rect {
min: self.translate_point(r.min),
max: self.translate_point(r.max),
}
}
}

impl Default for Viewport {
fn default() -> Self {
Self {
x: 0.,
y: 0.,
zoom: 1.,
}
}
}

/// Data stores state about the drawing and what it is composed of.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct Data {
pub features: HopSlotMap<slotmap::DefaultKey, Feature>,
pub vp: Viewport,

pub selected_map: HashMap<slotmap::DefaultKey, usize>,
}

impl Default for Data {
fn default() -> Self {
Self {
features: HopSlotMap::default(),
vp: Viewport::default(),
selected_map: HashMap::default(),
}
}
}

impl Data {
pub fn find_point_at(&self, p: egui::Pos2) -> Option<slotmap::DefaultKey> {
for (k, v) in self.features.iter() {
if v.bb(self).center().distance_sq(p) < 0.0001 {
return Some(k);
}
}
None
}

pub fn find_screen_feature(&self, hp: egui::Pos2) -> Option<(slotmap::DefaultKey, Feature)> {
let mut closest: Option<(slotmap::DefaultKey, f32, bool)> = None;
for (k, v) in self.features.iter() {
let is_point = v.is_point();

// Points get a head-start in terms of being considered closer, so
// they are chosen over a line segment when hovering near the end of
// a line segment.
let dist = if is_point {
v.screen_dist(self, hp, &self.vp) - (MAX_HOVER_DISTANCE / 2.)
} else {
v.screen_dist(self, hp, &self.vp)
};

if dist < MAX_HOVER_DISTANCE {
closest = Some(
closest
.map(|c| if dist < c.1 { (k, dist, is_point) } else { c })
.unwrap_or((k, dist, is_point)),
);
}
}

match closest {
Some((k, _dist, _is_point)) => Some((k, self.features.get(k).unwrap().clone())),
None => None,
}
}

pub fn delete_feature(&mut self, k: slotmap::DefaultKey) -> bool {
self.selected_map.remove(&k);

match self.features.remove(k) {
Some(_v) => {
// Find and also remove any features dependent on what we just removed.
let to_delete: std::collections::HashSet<slotmap::DefaultKey> = self
.features
.iter()
.map(|(k2, v2)| {
let dependent_deleted = v2
.depends_on()
.into_iter()
.filter_map(|d| d.map(|d| d == k))
.reduce(|p, f| p || f);

match dependent_deleted {
Some(true) => Some(k2),
_ => None,
}
})
.filter_map(|d| d)
.collect();

for k in to_delete {
self.delete_feature(k);
}

true
}
None => false,
}
}

pub fn selection_delete(&mut self) {
let elements: Vec<_> = self.selected_map.drain().map(|(k, _)| k).collect();
for k in elements {
self.delete_feature(k);
}
}

pub fn select_feature(&mut self, feature: &slotmap::DefaultKey, select: bool) {
let currently_selected = self.selected_map.contains_key(feature);
if currently_selected && !select {
self.selected_map.remove(feature);
} else if !currently_selected && select {
let next_idx = self.selected_map.values().fold(0, |acc, x| acc.max(*x)) + 1;
self.selected_map.insert(feature.clone(), next_idx);
}
}

pub fn select_features_in_rect(&mut self, rect: egui::Rect, select: bool) {
let keys: Vec<_> = self
.features
.iter()
.filter(|(_, v)| rect.contains_rect(v.bb(self)))
.map(|(k, _)| k)
.collect();

for k in keys.into_iter() {
self.select_feature(&k, select);
}
}

pub fn selection_clear(&mut self) {
self.selected_map.clear();
}

pub fn feature_selected(&self, feature: &slotmap::DefaultKey) -> bool {
self.selected_map.get(feature).is_some()
}
}
14 changes: 7 additions & 7 deletions drawing/src/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ impl Default for Feature {
}
}

impl super::DrawingFeature for Feature {
fn is_point(&self) -> bool {
impl Feature {
pub fn is_point(&self) -> bool {
matches!(self, Feature::Point(_, _))
}

fn depends_on(&self) -> [Option<K>; 2] {
pub fn depends_on(&self) -> [Option<K>; 2] {
match self {
Feature::Point(_, _) => [None, None],
Feature::LineSegment(p1, p2) => [Some(*p1), Some(*p2)],
}
}

fn bb(&self, drawing: &Data<Self>) -> egui::Rect {
pub fn bb(&self, drawing: &Data) -> egui::Rect {
match self {
Feature::Point(x, y) => egui::Rect {
min: egui::Pos2 { x: *x, y: *y },
Expand All @@ -80,7 +80,7 @@ impl super::DrawingFeature for Feature {
}
}

fn screen_dist(&self, drawing: &Data<Self>, hp: egui::Pos2, vp: &Viewport) -> f32 {
pub fn screen_dist(&self, drawing: &Data, hp: egui::Pos2, vp: &Viewport) -> f32 {
match self {
Feature::Point(x, y) => vp
.translate_point(egui::Pos2 { x: *x, y: *y })
Expand All @@ -104,9 +104,9 @@ impl super::DrawingFeature for Feature {
}
}

fn paint(
pub fn paint(
&self,
drawing: &Data<Self>,
drawing: &Data,
_k: slotmap::DefaultKey,
params: &PaintParams,
painter: &egui::Painter,
Expand Down
4 changes: 2 additions & 2 deletions drawing/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::tools::ToolResponse;
#[derive(Debug, Default)]
pub struct Handler {}

impl super::CommandHandler<Feature, ToolResponse> for Handler {
fn handle(&mut self, drawing: &mut Data<Feature>, c: ToolResponse) {
impl Handler {
pub fn handle(&mut self, drawing: &mut Data, c: ToolResponse) {
match c {
ToolResponse::Handled => {}
ToolResponse::NewPoint(pos) => {
Expand Down
Loading

0 comments on commit 3c19238

Please sign in to comment.