Start working on a transform editor

This commit is contained in:
Bradlee Speice 2025-02-23 18:02:35 -05:00
parent ceb772bbec
commit 38f383a0b2
7 changed files with 137 additions and 6 deletions

1
Cargo.lock generated
View File

@ -1299,6 +1299,7 @@ dependencies = [
"egui",
"egui-wgpu",
"env_logger",
"epaint",
"flare-shader",
"futures",
"futures-executor",

View File

@ -158,15 +158,24 @@ impl ThreadState {
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(C)]
pub struct Coefs {
a: f32,
b: f32,
c: f32,
d: f32,
e: f32,
f: f32,
pub a: f32,
pub b: f32,
pub c: f32,
pub d: f32,
pub e: f32,
pub f: f32,
}
impl Coefs {
pub const IDENTITY: Coefs = Coefs {
a: 1.0,
b: 0.0,
c: 0.0,
d: 0.0,
e: 1.0,
f: 0.0
};
pub fn new(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> Self {
Self { a, b, c, d, e, f }
}

View File

@ -12,6 +12,7 @@ eframe = { version = "0.31", features = ["wgpu"]}
egui = "0.31"
egui-wgpu = "0.31"
env_logger.workspace = true
epaint = "0.31"
flare-shader = { path = "../flare-shader" }
futures = "0.3"
futures-executor.workspace = true

View File

@ -0,0 +1,60 @@
use flare::transform_editor::TransformEditor;
use flare_shader::Coefs;
struct TransformEditorApp {
transform_editor: TransformEditor,
}
impl TransformEditorApp {
fn new() -> Self {
Self {
transform_editor: TransformEditor::new()
}
}
}
impl eframe::App for TransformEditorApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
ui.menu_button("File", |ui| {
if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
});
if ui.button("Add Transform").clicked() {
self.transform_editor.add_transform(Coefs::IDENTITY)
}
})
});
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
ui.label(format!("Transforms: {}", self.transform_editor.len()))
});
egui::CentralPanel::default().show(ctx, |ui| {
egui::Frame::canvas(ui.style()).show(ui, |ui| {
self.transform_editor.ui(ui)
})
});
}
}
fn main() -> eframe::Result {
env_logger::init();
let initial_dimensions = egui::vec2(800., 600.);
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size(initial_dimensions),
renderer: eframe::Renderer::Wgpu,
..Default::default()
};
eframe::run_native(
"transform_editor",
native_options,
Box::new(|cc| {
Ok(Box::new(TransformEditorApp::new()))
}),
)
}

1
crates/flare/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod transform_editor;

View File

@ -15,6 +15,8 @@ use std::fs::File;
use wgpu::util::DeviceExt;
use wgpu::{CommandBuffer, CommandEncoder, Device, Queue, RenderPass};
pub mod transform_editor;
struct RenderGroup {
device: wgpu::Device,
queue: wgpu::Queue,

View File

@ -0,0 +1,57 @@
use egui::{emath, Rect, Sense};
use epaint::{Color32, Shape, Stroke};
use flare_shader::Coefs;
pub struct TransformEditor {
transforms: Vec<Coefs>
}
fn coef_to_shapes(coef: &Coefs, to_screen: emath::RectTransform) -> Vec<Shape> {
let origin = to_screen.transform_pos(egui::pos2(coef.c, -coef.f));
let x = to_screen.transform_pos(egui::pos2(coef.c + coef.a, -(coef.f + coef.b)));
let y = to_screen.transform_pos(egui::pos2(coef.c + coef.d, -(coef.f + coef.e)));
let stroke = Stroke::new(2.0, Color32::BLUE);
let translucent = Color32::from_rgba_unmultiplied(0, 0, 255, 8);
let shapes = vec![
Shape::circle_stroke(origin, 5.0, stroke),
Shape::circle_stroke(x, 5.0, stroke),
Shape::circle_stroke(y, 5.0, stroke),
Shape::convex_polygon(vec![origin, x, y], translucent, stroke),
];
shapes
}
impl TransformEditor {
pub fn new() -> Self {
let mut editor = Self { transforms: vec![] };
editor.add_transform(Coefs::IDENTITY);
editor
}
pub fn add_transform(&mut self, coefs: Coefs) {
self.transforms.push(coefs);
}
pub fn len(&self) -> usize {
self.transforms.len()
}
pub fn ui(&mut self, ui: &mut egui::Ui) -> egui::Response {
let (response, painter) = ui.allocate_painter(ui.available_size(), Sense::hover());
let transform_area = Rect::from_min_max(egui::pos2(-2.0, -2.0), egui::pos2(2.0, 2.0));
let to_screen = emath::RectTransform::from_to(transform_area, response.interact_rect);
self.transforms.iter().map(|coef| {
coef_to_shapes(coef, to_screen)
}).flat_map(|x| x).for_each(|shape| {
let _ = painter.add(shape);
});
response
}
}