Skip to content

Commit

Permalink
Implement application log
Browse files Browse the repository at this point in the history
- Allows for undo/redo functionality
- Less mutations on our runtime state
- Middleware functionality via messages
  • Loading branch information
lbirkert committed Jul 31, 2023
1 parent 172ceea commit 4c38f28
Show file tree
Hide file tree
Showing 16 changed files with 500 additions and 386 deletions.
11 changes: 5 additions & 6 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ impl eframe::App for KeloApp {
if let Some(handle) = handle {
async {
if let Ok(mesh) = Mesh::from_stl(&mut Cursor::new(&handle.read().await)) {
self.editor.id_counter += 1;
self.editor.objects.push(Object::new(
mesh,
handle.file_name(),
self.editor.id_counter,
));
self.editor.state.push(
self.editor
.state
.insert_object(Object::new(mesh, handle.file_name())),
);
}
}
.block_on();
Expand Down
12 changes: 0 additions & 12 deletions src/core/machine.rs

This file was deleted.

3 changes: 0 additions & 3 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
pub mod machine;
pub mod tool;

pub mod primitives;
12 changes: 1 addition & 11 deletions src/core/primitives/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::io::Cursor;

use nalgebra::{Matrix4, UnitVector3, Vector2, Vector3};

use super::{Path2, Ray, Trans, Triangle};
use super::{Path2, Ray, Triangle};

#[derive(Clone)]
pub struct Mesh {
Expand Down Expand Up @@ -218,16 +218,6 @@ impl Mesh {
}
}

/// Apply a transformation.
pub fn apply(&mut self, trans: &Trans) {
match trans {
Trans::Scale(delta) => self.scale(*delta),
Trans::ScaleNonUniformly(delta) => self.scale_non_uniformly(delta),
Trans::Rotate(delta) => self.rotate(delta),
Trans::Translate(delta) => self.translate(delta),
}
}

/// Calculate the infinum (aka. componentwise min) and the suprenum (aka. componentwise max) of this mesh.
pub fn inf_sup(&self) -> (Vector3<f32>, Vector3<f32>) {
let mut inf = Vector3::from_element(std::f32::INFINITY);
Expand Down
2 changes: 0 additions & 2 deletions src/core/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub mod plane;
pub mod ray;
pub mod sphere;
pub mod square;
pub mod trans;
pub mod triangle;

pub use axis::Axis;
Expand All @@ -16,5 +15,4 @@ pub use plane::Plane;
pub use ray::Ray;
pub use sphere::Sphere;
pub use square::Square;
pub use trans::Trans;
pub use triangle::Triangle;
9 changes: 0 additions & 9 deletions src/core/primitives/trans.rs

This file was deleted.

10 changes: 0 additions & 10 deletions src/core/tool.rs

This file was deleted.

36 changes: 36 additions & 0 deletions src/editor/icons.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#[macro_export]
macro_rules! icon {
($name:tt) => {{
let image = image::load_from_memory(include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/icons/",
$name,
".png"
)))
.expect("Failed to load image");
let size = [image.width() as _, image.height() as _];
let image_buffer = image.to_rgba8();
let pixels = image_buffer.as_flat_samples();
egui::ColorImage::from_rgba_unmultiplied(size, pixels.as_slice())
}};
}

pub struct Icons {
pub group: egui::TextureHandle,
pub object: egui::TextureHandle,
pub toolpath: egui::TextureHandle,
}

impl Icons {
pub fn load(ctx: &egui::Context) -> Self {
let group = ctx.load_texture("group", icon!("group"), Default::default());
let object = ctx.load_texture("object", icon!("object"), Default::default());
let toolpath = ctx.load_texture("toolpath", icon!("toolpath"), Default::default());

Self {
group,
object,
toolpath,
}
}
}
97 changes: 97 additions & 0 deletions src/editor/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::collections::HashSet;

use crate::core::primitives::Mesh;

use super::{object::Object, tool::Tool};

/// An action is a message in the application log, the ActionTree.
/// Actions are re- and undoable.
pub enum Message {
Tool(Tool),
Selection(HashSet<u32>),
Object { id: u32, object: Option<Object> },
Mesh { id: u32, mesh: Mesh },
None,
}

impl Default for Message {
fn default() -> Self {
Self::None
}
}

pub const UNDO_CAPACITY: usize = 20;

/// The stack allocated application log. It stores the last n actions that occured for undoing
/// and redoing, where n is the number stored in the UNDO_CAPACITY constant.
pub struct Log {
pub actions: Vec<Message>,
pub cursor: usize,
before: usize,
after: usize,
}

impl Log {
pub fn new(capacity: usize) -> Self {
assert!(capacity > 0);

let mut actions = Vec::with_capacity(capacity);
for _ in 0..actions.capacity() {
actions.push(Message::None);
}

Self {
actions,
cursor: 0,
before: 0,
after: 0,
}
}

/// Pushes an action. This returns the action that was overwritten (if any).
pub fn push(&mut self, mut message: Message) -> Option<Message> {
if matches!(message, Message::None) {
return None;
}

self.cursor = (self.cursor + 1) % self.actions.len();
self.after = 0;

if self.before == self.actions.len() {
std::mem::swap(&mut message, &mut self.actions[self.cursor]);
Some(message)
} else {
self.before += 1;
self.actions[self.cursor] = message;
None
}
}

pub fn can_undo(&self) -> bool {
self.before > 0
}

/// Retracts the cursor
pub fn undo(&mut self) {
self.cursor = self.cursor.checked_sub(1).unwrap_or(self.actions.len() - 1);
self.after = (self.after + 1).min(self.actions.len());
self.before -= 1;
}

pub fn can_redo(&self) -> bool {
self.after > 0
}

/// Advances the cursor
pub fn redo(&mut self) {
self.cursor = (self.cursor + 1) % self.actions.len();
self.before = (self.before + 1).min(self.actions.len());
self.after -= 1;
}
}

impl Default for Log {
fn default() -> Self {
Self::new(UNDO_CAPACITY)
}
}
Loading

0 comments on commit 4c38f28

Please sign in to comment.