shape_maker/src/ui.rs
2022-08-04 17:52:04 +03:00

266 lines
13 KiB
Rust

use bevy::math::{Vec3Swizzles, Mat2};
use bevy::prelude::*;
use bevy_egui::{egui, EguiContext};
use bevy_prototype_lyon::prelude::{Path, DrawMode, FillMode, StrokeMode};
use crate::*;
pub fn action_bar_sys(
mut coms: Commands,
assets: Res<AssetServer>,
mut egui_ctx: ResMut<EguiContext>,
mut state: ResMut<UiState>,
colors: Res<ButtonsColors>,
) {
egui::Window::new("buttons_float")
.default_pos((20.0, 20.0))
.title_bar(false)
.resizable(false)
.show(egui_ctx.ctx_mut(), |ui| {
ui.horizontal(|hui| {
let m = hui.button(egui::RichText::new("M").color(state.current_action_color(&colors, Action::Modify)))
.on_hover_text("Modify");
if m.clicked() {
state.current_action = Action::Modify;
}
let c = hui.button(egui::RichText::new("C").color(state.current_action_color(&colors, Action::Create)))
.on_hover_text("Create");
if c.clicked() {
state.current_action = Action::Create;
}
hui.label(" | ");
if hui.button(" I ").on_hover_text("Import Image").clicked() {
let file = rfd::FileDialog::new()
.add_filter("Pngs", &["png"])
.set_directory("./")
.set_title("Please dont try to pick a cat instead of an image(although you can pick a cat image)")
.pick_file();
if let Some(file) = file {
let name = String::from(file.file_name().unwrap().to_str().unwrap_or("Image"));
let image: Handle<Image> = assets.load(file);
coms.spawn_bundle(SpriteBundle {
texture: image,
..Default::default()
})
.insert(ImageName(name));
}
}
hui.label(": :");
});
if state.current_action == Action::Create {
ui.horizontal(|hui| {
let tri = hui.button(egui::RichText::new("Tri").color(state.create_shape_color(&colors, CreateShape::Triangle)))
.on_hover_text("Triangle - from 3 edges");
if tri.clicked() {
state.create_shape = CreateShape::Triangle;
}
let squ = hui.button(egui::RichText::new("Squ").color(state.create_shape_color(&colors, CreateShape::Square)))
.on_hover_text("Square - from 2 opposing edges");
if squ.clicked() {
state.create_shape = CreateShape::Square;
}
let cir = hui.button(egui::RichText::new("Cir").color(state.create_shape_color(&colors, CreateShape::Circle)))
.on_hover_text("Circle - center point and radius");
if cir.clicked() {
state.create_shape = CreateShape::Circle;
}
// let cap = hui.button(egui::RichText::new("Cap").color(state.create_shape_color(&colors, CreateShape::Capsule)))
// .on_hover_text("Capsule - from 2 center points and a radius");
// if cap.clicked() {
// state.create_shape = CreateShape::Capsule;
// }
});
}
});
}
pub fn grid_window_sys(
mut grid: ResMut<SnapGrid>,
mut egui_ctx: ResMut<EguiContext>,
) {
egui::Window::new("Snap Grid")
.default_pos((200.0, 20.0))
.title_bar(true)
.resizable(false)
.show(egui_ctx.ctx_mut(), |ui| {
ui.checkbox(&mut grid.snap, "Snap Enabled");
ui.label("Grid size:");
ui.horizontal(|hui| {
hui.label("Width:");
hui.add(egui::DragValue::new(&mut grid.width));
hui.label("Height:");
hui.add(egui::DragValue::new(&mut grid.height));
});
ui.horizontal(|hui| {
hui.label("Offset:");
hui.label("X:");
hui.add(egui::DragValue::new(&mut grid.offset.x));
hui.label("Y:");
hui.add(egui::DragValue::new(&mut grid.offset.y));
});
});
}
pub fn shape_tree_sys(
mut name_change: Local<Option<(Entity, String)>>,
mut coms: Commands,
mut egui_ctx: ResMut<EguiContext>,
mut shapes: Query<(Entity, &mut ShapeData)>,
mut transforms: Query<&mut Transform>,
global_transforms: Query<&GlobalTransform>,
mut paths: Query<&mut Path>,
mut draw_modes: Query<&mut DrawMode, With<Path>>,
mut visible: Query<&mut Visibility, Or<(With<Path>, With<Sprite>)>>,
mut images: Query<(Entity, &mut ImageName), With<Sprite>>,
) {
if !shapes.is_empty() {
egui::Window::new("Shape Tree")
.default_pos((10.0, 100.0))
.title_bar(true)
.resizable(false)
.show(egui_ctx.ctx_mut(), |ui| {
for (e, mut sd) in shapes.iter_mut () {
ui.push_id(e.id(), |ui| {
let mut ui_func = |ui: &mut egui::Ui| {
if let Ok(mut t) = transforms.get_mut(sd.main_shape) {
ui.horizontal(|hui| {
hui.label("Translation:");
hui.add(egui::DragValue::new(&mut t.translation.x));
hui.add(egui::DragValue::new(&mut t.translation.y));
});
ui.horizontal(|hui| {
hui.label("Rotation:");
let mut rot = t.rotation.to_euler(EulerRot::XYZ).2.to_degrees();
if hui.add(egui::DragValue::new(&mut rot).suffix("°")).changed() {
t.rotation = Quat::from_rotation_z(rot.to_radians());
}
});
}
for (i, edge) in sd.edges.iter().enumerate() {
ui.horizontal(|hui| {
hui.label(format!("Edge {}", i));
let gt = global_transforms.get(*edge).unwrap();
let mut gt_x = gt.translation().x;
let mut gt_y = gt.translation().y;
let c1 = hui.add(egui::DragValue::new(&mut gt_x)).changed();
let c2 = hui.add(egui::DragValue::new(&mut gt_y)).changed();
if c1 || c2 {
let rot = gt.to_scale_rotation_translation().1;
let ang = rot.to_euler(EulerRot::XYZ).2;
let delta = Mat2::from_angle(-ang) * (Vec2::new(gt_x, gt_y) - gt.translation().xy());
if let Ok(mut t) = transforms.get_mut(*edge) {
t.translation += delta.extend(0.0);
}
// We need to recalculate the center, and update the points to be the new relevant point from the center
let center_offset = modify::calc_shape_center_offset(&transforms, &*sd);
// Update each edge's offset, and then move the main shape's translation
for edge in sd.edges.iter() {
if let Ok(mut t) = transforms.get_mut(*edge) {
t.translation -= center_offset.extend(0.0);
}
}
if let Ok(mut t) = transforms.get_mut(sd.main_shape) {
t.translation += (Mat2::from_angle(ang) * center_offset).extend(0.0);
}
// Now we need to update the shape itself
modify::update_main_shape(&mut paths, &transforms, &*sd);
}
});
}
};
if let Some((sde, name)) = &mut *name_change && *sde == e {
// Changing the current shape's name
let te = egui::TextEdit::singleline(name).desired_width(100.0);
if ui.add(te).lost_focus() {
let (_, name) = name_change.take().unwrap();
sd.name = Some(name);
}
}
else {
let default_name = format!("{:?}", sd.shape);
ui.horizontal(|hui| {
let collapse = hui.collapsing(sd.name.as_ref().unwrap_or(&default_name), |ui| {
ui.horizontal(|hui| {
if hui.button("E").clicked() {
*name_change = Some((e, format!("{:?}", sd.shape)));
}
if hui.button("D").clicked() {
coms.entity(sd.main_shape).despawn_recursive();
coms.entity(e).despawn();
}
let mut v = visible.get_mut(sd.main_shape).unwrap();
let text = if v.is_visible { egui::RichText::new("V") } else { egui::RichText::new("V").strikethrough() };
if hui.button(text).clicked() {
v.is_visible ^= true;
}
});
ui_func(ui);
});
if collapse.fully_closed() {
if hui.button("E").clicked() {
*name_change = Some((e, default_name));
}
if hui.button("D").clicked() {
coms.entity(sd.main_shape).despawn_recursive();
coms.entity(e).despawn();
}
let mut v = visible.get_mut(sd.main_shape).unwrap();
let text = if v.is_visible { egui::RichText::new("V") } else { egui::RichText::new("V").strikethrough() };
if hui.button(text).clicked() {
v.is_visible ^= true;
}
}
let d_normal = DrawMode::Outlined {
fill_mode: FillMode::color(Color::rgba(0.0, 0.5, 0.5, 0.4)),
outline_mode: StrokeMode::new(Color::rgba(0.0, 0.5, 0.5, 0.6), 3.0),
};
let d_open = DrawMode::Outlined {
fill_mode: FillMode::color(Color::rgba(0.0, 0.5, 0.5, 0.4)),
outline_mode: StrokeMode::new(Color::GOLD, 3.0),
};
let wanted_dm = if collapse.fully_open() { d_open } else { d_normal };
if let Ok(mut dm) = draw_modes.get_mut(sd.main_shape) {
if *dm != wanted_dm {
*dm = wanted_dm
}
}
});
}
});
}
for (e, mut n) in images.iter_mut() {
if let Some((ne, name)) = &mut *name_change && *ne == e {
let te = egui::TextEdit::singleline(name);
if ui.add(te).lost_focus() {
let (_, name) = name_change.take().unwrap();
**n = name;
}
}
else {
ui.horizontal(|hui| {
hui.label(&**n);
if hui.button("E").clicked() {
*name_change = Some((e, n.clone()));
}
if hui.button("D").clicked() {
coms.entity(e).despawn();
}
let mut v = visible.get_mut(e).unwrap();
let text = if v.is_visible { egui::RichText::new("V") } else { egui::RichText::new("V").strikethrough() };
if hui.button(text).clicked() {
v.is_visible ^= true;
}
});
}
}
});
}
}