Another change to Coord trait stuff
This commit is contained in:
parent
401560d35e
commit
e97598b69f
1641
Cargo.lock
generated
1641
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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"]
|
12
board-builder-impl-egui/Cargo.toml
Normal file
12
board-builder-impl-egui/Cargo.toml
Normal 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"
|
90
board-builder-impl-egui/src/main.rs
Normal file
90
board-builder-impl-egui/src/main.rs
Normal 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 }
|
||||||
|
}
|
@ -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),
|
||||||
|
38
src/lib.rs
38
src/lib.rs
@ -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 }
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user