mirror of https://codeberg.org/topola/topola.git
cargo: rename topola-gui to topola-egui, minor refactoring
This commit is contained in:
parent
0cb7a015d4
commit
f10f7b7ab4
|
|
@ -2,21 +2,21 @@
|
|||
name = "topola"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
default-run = "topola-gui"
|
||||
default-run = "topola-egui"
|
||||
|
||||
[lib]
|
||||
name = "topola"
|
||||
|
||||
[[bin]]
|
||||
name = "topola-gui"
|
||||
required-features = ["gui"]
|
||||
name = "topola-egui"
|
||||
required-features = ["egui"]
|
||||
|
||||
[[bin]]
|
||||
name = "topola-sdl2-demo"
|
||||
required-features = ["sdl2"]
|
||||
|
||||
[features]
|
||||
gui = ["dep:egui", "dep:eframe"]
|
||||
egui = ["dep:egui", "dep:eframe"]
|
||||
sdl2 = ["dep:sdl2"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/// Deserialize/Serialize is needed to persist app state between restarts.
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct TemplateApp {
|
||||
pub struct App {
|
||||
// Example stuff:
|
||||
label: String,
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ pub struct TemplateApp {
|
|||
value: f32,
|
||||
}
|
||||
|
||||
impl Default for TemplateApp {
|
||||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
// Example stuff:
|
||||
|
|
@ -19,7 +19,7 @@ impl Default for TemplateApp {
|
|||
}
|
||||
}
|
||||
|
||||
impl TemplateApp {
|
||||
impl App {
|
||||
/// Called once on start.
|
||||
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||
// Load previous app state if one exists.
|
||||
|
|
@ -31,7 +31,7 @@ impl TemplateApp {
|
|||
}
|
||||
}
|
||||
|
||||
impl eframe::App for TemplateApp {
|
||||
impl eframe::App for App {
|
||||
/// Called to save state before shutdown.
|
||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
||||
eframe::set_value(storage, eframe::APP_KEY, self);
|
||||
|
|
@ -55,6 +55,14 @@ impl eframe::App for TemplateApp {
|
|||
});
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {});
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::Frame::canvas(ui.style()).show(ui, |ui| {
|
||||
let (rect, response) =
|
||||
ui.allocate_exact_size(egui::Vec2::splat(300.0), egui::Sense::drag());
|
||||
let stroke = egui::Stroke::new(10.0, egui::Color32::from_white_alpha(255));
|
||||
ui.painter()
|
||||
.line_segment([[10.0, 10.0].into(), [30.0, 30.0].into()], stroke);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
|
||||
mod app;
|
||||
use app::TemplateApp;
|
||||
mod painter;
|
||||
use app::App;
|
||||
|
||||
// Build to native.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
|
@ -15,9 +16,9 @@ fn main() -> eframe::Result<()> {
|
|||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"eframe template",
|
||||
"topola-egui",
|
||||
native_options,
|
||||
Box::new(|cc| Box::new(TemplateApp::new(cc))),
|
||||
Box::new(|cc| Box::new(App::new(cc))),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
extern crate sdl2;
|
||||
|
||||
mod painter;
|
||||
|
||||
macro_rules! dbg_dot {
|
||||
($graph:expr) => {
|
||||
use petgraph::dot::Dot;
|
||||
|
|
@ -8,6 +10,7 @@ macro_rules! dbg_dot {
|
|||
}
|
||||
|
||||
use geo::point;
|
||||
use painter::Painter;
|
||||
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
||||
use topola::draw::DrawException;
|
||||
use topola::layout::connectivity::BandIndex;
|
||||
|
|
@ -665,6 +668,7 @@ fn render_times(
|
|||
let window_size = window.size();
|
||||
let mut canvas = Canvas::new(vec2f(window_size.0 as f32, window_size.1 as f32))
|
||||
.get_context_2d(font_context.clone());
|
||||
let mut painter = Painter::new(&mut canvas);
|
||||
|
||||
let layout = match router_or_layout {
|
||||
RouterOrLayout::Router(ref mut router) => {
|
||||
|
|
@ -701,17 +705,17 @@ fn render_times(
|
|||
};
|
||||
|
||||
let shape = node.primitive(layout).shape();
|
||||
render_shape(&mut canvas, &shape, color);
|
||||
painter.paint_shape(&shape, color);
|
||||
}
|
||||
|
||||
for ghost in ghosts {
|
||||
render_shape(&mut canvas, &ghost, ColorU::new(75, 75, 150, 255));
|
||||
painter.paint_shape(&ghost, ColorU::new(75, 75, 150, 255));
|
||||
}
|
||||
|
||||
if let Some(ref mesh) = maybe_mesh {
|
||||
for edge in mesh.edge_references() {
|
||||
let start_point = edge.source().primitive(layout).shape().center();
|
||||
let end_point = edge.target().primitive(layout).shape().center();
|
||||
let to = edge.source().primitive(layout).shape().center();
|
||||
let from = edge.target().primitive(layout).shape().center();
|
||||
|
||||
let color = 'blk: {
|
||||
if let (Some(source_pos), Some(target_pos)) = (
|
||||
|
|
@ -726,12 +730,7 @@ fn render_times(
|
|||
ColorU::new(125, 125, 125, 255)
|
||||
};
|
||||
|
||||
let mut path = Path2D::new();
|
||||
path.move_to(vec2f(start_point.x() as f32, start_point.y() as f32));
|
||||
path.line_to(vec2f(end_point.x() as f32, end_point.y() as f32));
|
||||
canvas.set_stroke_style(color);
|
||||
canvas.set_line_width(1.0);
|
||||
canvas.stroke_path(path);
|
||||
painter.paint_edge(from, to, color);
|
||||
}
|
||||
}
|
||||
//});
|
||||
|
|
@ -752,54 +751,3 @@ fn render_times(
|
|||
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
|
||||
}
|
||||
}
|
||||
|
||||
fn render_shape(canvas: &mut CanvasRenderingContext2D, shape: &Shape, color: ColorU) {
|
||||
canvas.set_stroke_style(color);
|
||||
canvas.set_fill_style(color);
|
||||
|
||||
match shape {
|
||||
Shape::Dot(dot) => {
|
||||
let mut path = Path2D::new();
|
||||
path.ellipse(
|
||||
vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
|
||||
dot.c.r as f32,
|
||||
0.0,
|
||||
0.0,
|
||||
std::f32::consts::TAU,
|
||||
);
|
||||
canvas.fill_path(path, FillRule::Winding);
|
||||
}
|
||||
Shape::Seg(seg) => {
|
||||
let mut path = Path2D::new();
|
||||
path.move_to(vec2f(seg.from.x() as f32, seg.from.y() as f32));
|
||||
path.line_to(vec2f(seg.to.x() as f32, seg.to.y() as f32));
|
||||
canvas.set_line_width(seg.width as f32);
|
||||
canvas.stroke_path(path);
|
||||
}
|
||||
Shape::Bend(bend) => {
|
||||
let delta1 = bend.from - bend.c.pos;
|
||||
let delta2 = bend.to - bend.c.pos;
|
||||
|
||||
let angle1 = delta1.y().atan2(delta1.x());
|
||||
let angle2 = delta2.y().atan2(delta2.x());
|
||||
|
||||
let mut path = Path2D::new();
|
||||
path.arc(
|
||||
vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
|
||||
bend.circle().r as f32,
|
||||
angle1 as f32,
|
||||
angle2 as f32,
|
||||
ArcDirection::CW,
|
||||
);
|
||||
canvas.set_line_width(bend.width as f32);
|
||||
canvas.stroke_path(path);
|
||||
}
|
||||
}
|
||||
let envelope = ShapeTrait::envelope(shape, 0.0);
|
||||
// XXX: points represented as arrays can't be conveniently converted to vector types
|
||||
let topleft = vec2f(envelope.lower()[0] as f32, envelope.lower()[1] as f32);
|
||||
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
|
||||
canvas.set_line_width(1.0);
|
||||
canvas.set_stroke_style(ColorU::new(100, 100, 100, 255));
|
||||
canvas.stroke_rect(RectF::new(topleft, bottomright - topleft));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
use geo::Point;
|
||||
use pathfinder_canvas::{
|
||||
vec2f, ArcDirection, Canvas, CanvasRenderingContext2D, ColorU, FillRule, Path2D, RectF,
|
||||
};
|
||||
use topola::layout::geometry::shape::{Shape, ShapeTrait};
|
||||
|
||||
pub struct Painter<'a> {
|
||||
canvas: &'a mut CanvasRenderingContext2D,
|
||||
}
|
||||
|
||||
impl<'a> Painter<'a> {
|
||||
pub fn new(canvas: &'a mut CanvasRenderingContext2D) -> Self {
|
||||
Self { canvas }
|
||||
}
|
||||
|
||||
pub fn paint_shape(&mut self, shape: &Shape, color: ColorU) {
|
||||
self.canvas.set_stroke_style(color);
|
||||
self.canvas.set_fill_style(color);
|
||||
|
||||
match shape {
|
||||
Shape::Dot(dot) => {
|
||||
let mut path = Path2D::new();
|
||||
path.ellipse(
|
||||
vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
|
||||
dot.c.r as f32,
|
||||
0.0,
|
||||
0.0,
|
||||
std::f32::consts::TAU,
|
||||
);
|
||||
self.canvas.fill_path(path, FillRule::Winding);
|
||||
}
|
||||
Shape::Seg(seg) => {
|
||||
let mut path = Path2D::new();
|
||||
path.move_to(vec2f(seg.from.x() as f32, seg.from.y() as f32));
|
||||
path.line_to(vec2f(seg.to.x() as f32, seg.to.y() as f32));
|
||||
self.canvas.set_line_width(seg.width as f32);
|
||||
self.canvas.stroke_path(path);
|
||||
}
|
||||
Shape::Bend(bend) => {
|
||||
let delta1 = bend.from - bend.c.pos;
|
||||
let delta2 = bend.to - bend.c.pos;
|
||||
|
||||
let angle1 = delta1.y().atan2(delta1.x());
|
||||
let angle2 = delta2.y().atan2(delta2.x());
|
||||
|
||||
let mut path = Path2D::new();
|
||||
path.arc(
|
||||
vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
|
||||
bend.circle().r as f32,
|
||||
angle1 as f32,
|
||||
angle2 as f32,
|
||||
ArcDirection::CW,
|
||||
);
|
||||
self.canvas.set_line_width(bend.width as f32);
|
||||
self.canvas.stroke_path(path);
|
||||
}
|
||||
}
|
||||
|
||||
let envelope = ShapeTrait::envelope(shape, 0.0);
|
||||
// XXX: points represented as arrays can't be conveniently converted to vector types
|
||||
let topleft = vec2f(envelope.lower()[0] as f32, envelope.lower()[1] as f32);
|
||||
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
|
||||
self.canvas.set_line_width(1.0);
|
||||
self.canvas
|
||||
.set_stroke_style(ColorU::new(100, 100, 100, 255));
|
||||
self.canvas
|
||||
.stroke_rect(RectF::new(topleft, bottomright - topleft));
|
||||
}
|
||||
|
||||
pub fn paint_edge(&mut self, from: Point, to: Point, color: ColorU) {
|
||||
let mut path = Path2D::new();
|
||||
path.move_to(vec2f(from.x() as f32, from.y() as f32));
|
||||
path.line_to(vec2f(to.x() as f32, to.y() as f32));
|
||||
self.canvas.set_stroke_style(color);
|
||||
self.canvas.set_line_width(1.0);
|
||||
self.canvas.stroke_path(path);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue