Another change to Coord trait stuff

This commit is contained in:
Dane Johnson 2022-05-09 15:47:00 -05:00
parent 401560d35e
commit e97598b69f
7 changed files with 1745 additions and 75 deletions

1641
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -13,4 +13,4 @@ zip = "0.6.2"
image = "0.24.2" image = "0.24.2"
[workspace] [workspace]
members = ["board-builder-impl-fltk"] members = ["board-builder-impl-fltk", "board-builder-impl-egui"]

View File

@ -0,0 +1,12 @@
[package]
name = "board-builder-impl-egui"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
board-builder = { path = "../" }
eframe = "0.18.0"
rfd = "0.8.2"
image = "0.24.2"

View File

@ -0,0 +1,90 @@
use eframe::egui;
use egui::*;
use rfd::FileDialog;
use board_builder::Board;
use std::path::Path;
fn main() {
let native_options = eframe::NativeOptions::default();
eframe::run_native("Board Builder", native_options, Box::new(|_cc| Box::new(BoardBuilderApp::default())));
}
#[derive(Default)]
struct BoardBuilderApp {
board: Board,
texture: Option<TextureHandle>,
image: Option<image::DynamicImage>,
}
impl eframe::App for BoardBuilderApp {
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
TopBottomPanel::top("menubar").show(ctx, |ui| {
menu::bar(ui, |ui| {
fn choose_file() {
FileDialog::new().pick_file();
}
ui.menu_button("File", |ui| {
ui.button("New");
if ui.button("Open...").clicked() {
choose_file();
}
if ui.button("Save As...").clicked() {
choose_file();
}
if ui.button("Open Image...").clicked() {
let image_file = FileDialog::new()
.add_filter("Image", &["png", "jpg", "jpeg", "gif", "webp", "bmp", "tiff"])
.pick_file();
if let Some(image_file) = image_file {
self.load_image(ctx, &image_file);
}
}
});
ui.menu_button("Edit", |ui| {
ui.button("Edit Nodes");
ui.button("Edit Edges");
ui.button("Edit Labels...");
})
});
});
CentralPanel::default().show(ctx, |ui| {
if let Some(texture) = self.texture.as_ref() {
let size = ui.available_size();
ui.image(texture, size);
let (response, painter) = ui.allocate_painter(size, Sense::click());
let view = View(response.rect);
self.draw_board(&painter, view);
}
});
}
}
impl BoardBuilderApp {
fn load_image(&mut self, ctx: &Context, image_file: &Path) -> Result<(), image::ImageError> {
let image = image::io::Reader::open(image_file)?.decode()?;
let egui_image = egui::ColorImage::from_rgba_unmultiplied(
[image.width() as _, image.height() as _],
image.to_rgba8().as_flat_samples().as_slice(),
);
self.image = Some(image);
self.texture = Some(ctx.load_texture("board-image", egui_image));
Ok(())
}
fn draw_board(&mut self, painter: &Painter, view: View) {
for node in &self.board.nodes {
todo!();
}
}
}
struct View(Rect);
impl board_builder::CoordTransformer<Pos2> for View {
fn origin(&self) -> Pos2 { self.0.min }
fn extremes(&self) -> Pos2 { self.0.max }
}

View File

@ -133,13 +133,38 @@ mod dispatch {
} }
struct FrameView<'a>(&'a frame::Frame); struct FrameView<'a>(&'a frame::Frame);
struct Pos(i32, i32);
impl<'a> CoordTransformer<i32> for FrameView<'a> { impl<'a> FrameView<'a> {
fn origin(&self) -> (i32, i32) { (self.0.x(), self.0.y()) } fn origin(&self) -> Pos {
fn extremes(&self) -> (i32, i32) { (self.0.x()+self.0.w(), self.0.y()+self.0.h()) } Pos(self.0.x(), self.0.y())
}
fn extremes(&self) -> Pos {
Pos(self.0.x() + self.0.w(), self.0.y() + self.0.h())
}
} }
impl<'a> CoordTransformer<Pos> for FrameView<'a> {
fn origin(&self) -> Pos { self.origin() }
fn extremes(&self) -> Pos { self.extremes() }
}
impl From<(f32, f32)> for Pos {
fn from((x, y): (f32, f32)) -> Self {
Pos(x as i32, y as i32)
}
}
impl From<Pos> for (f32, f32) {
fn from(Pos(x, y): Pos) -> Self {
(x as f32, y as f32)
}
}
//////////////////// App State //////////////////// //////////////////// App State ////////////////////
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum EditMode { enum EditMode {
Node, Node,
@ -253,7 +278,7 @@ fn main() {
let f = FrameView(f); let f = FrameView(f);
for (&id, node) in &board.nodes { for (&id, node) in &board.nodes {
// Draw the node // Draw the node
let (x, y) = f.from_coords(node.x, node.y); let Pos(x, y) = f.from_coords(node.x, node.y);
if state.selected_node == Some(id) { if state.selected_node == Some(id) {
set_draw_color(Color::Red); set_draw_color(Color::Red);
draw_text(&node.name, x, y); draw_text(&node.name, x, y);
@ -264,7 +289,7 @@ fn main() {
// Draw edges // Draw edges
for other_id in &node.edges { for other_id in &node.edges {
let other = board.nodes.get(other_id).unwrap(); let other = board.nodes.get(other_id).unwrap();
let (x1, y1) = f.from_coords(other.x, other.y); let Pos(x1, y1) = f.from_coords(other.x, other.y);
draw_line(x, y, x1, y1); draw_line(x, y, x1, y1);
} }
} }
@ -274,7 +299,7 @@ fn main() {
Event::Push => { Event::Push => {
let f = FrameView(f); let f = FrameView(f);
let edit_mode = STATE.get().lock().unwrap().edit_mode; let edit_mode = STATE.get().lock().unwrap().edit_mode;
let coords = f.to_coords(app::event_x(), app::event_y()); let coords = f.to_coords(Pos(app::event_x(), app::event_y()));
match edit_mode { match edit_mode {
EditMode::Node => dispatch::node_press(coords), EditMode::Node => dispatch::node_press(coords),

BIN
board.zip

Binary file not shown.

View File

@ -139,33 +139,21 @@ fn inv_lerp(v0: f32, v1: f32, a: f32) -> f32 {
(a - v0) / (v1 - v0) (a - v0) / (v1 - v0)
} }
pub trait CoordTransformer<I: CoordtypeConvertible> { pub trait CoordTransformer<I: Into<(f32, f32)> + From<(f32, f32)>> {
fn origin(&self) -> (I, I); fn origin(&self) -> I;
fn extremes(&self) -> (I, I); fn extremes(&self) -> I;
fn to_coords(&self, x: I, y: I) -> (f32, f32) { fn to_coords(&self, pos: I) -> (f32, f32) {
let (sx, sy) = self.origin(); let (sx, sy) = self.origin().into();
let (ex, ey) = self.extremes(); let (ex, ey) = self.extremes().into();
let (x, y) = pos.into();
( (
inv_lerp(sx.to_coordtype(), ex.to_coordtype(), x.to_coordtype()), inv_lerp(sx, ex, x),
inv_lerp(sy.to_coordtype(), ey.to_coordtype(), y.to_coordtype()), inv_lerp(sy, ey, y),
) )
} }
fn from_coords(&self, x: f32, y: f32) -> (I, I) { fn from_coords(&self, x: f32, y: f32) -> I {
let (sx, sy) = self.origin(); let (sx, sy) = self.origin().into();
let (ex, ey) = self.extremes(); let (ex, ey) = self.extremes().into();
( (lerp(sx, ex, x), lerp(sy, ey, y)).into()
CoordtypeConvertible::from_coordtype(lerp(sx.to_coordtype(), ex.to_coordtype(), x)),
CoordtypeConvertible::from_coordtype(lerp(sy.to_coordtype(), ey.to_coordtype(), y)),
)
} }
} }
pub trait CoordtypeConvertible {
fn to_coordtype(self) -> f32;
fn from_coordtype(coordtype: f32) -> Self;
}
impl CoordtypeConvertible for i32 {
fn to_coordtype(self) -> f32 { self as f32 }
fn from_coordtype(coordtype: f32) -> i32 { coordtype as i32 }
}