basic stringtree movement

This commit is contained in:
adia redmoon 2024-04-25 03:54:37 -07:00
parent a9d346c411
commit 18a93e44df
2 changed files with 209 additions and 112 deletions

View File

@ -17,7 +17,7 @@ use bevy_egui::{
self, color_picker,
ecolor::{hsv_from_rgb, rgb_from_hsv},
epaint::Hsva,
Id, Pos2, Rect, Response, ScrollArea,
Id, Pos2, Rect, ScrollArea,
},
EguiContexts, EguiPlugin, EguiSettings,
};
@ -39,6 +39,9 @@ use super::{
orbit_camera::orbit_camera::{pan_orbit_camera, spawn_camera},
ui_extensions::{StringTree, StringTreeElement},
};
use std::fmt::Write;
pub struct AssetEditData {
path: String,
id: Handle<OctTreeAsset>,
@ -51,6 +54,21 @@ pub struct EditWindowUIState {
meshes: Vec<AssetEditData>,
structure: StringTree,
egui: EditWindowEguiState,
popup: PopupWindowData,
}
#[derive(Default)]
pub enum PopupWindowData {
#[default]
None,
StructureElement(String),
}
impl PopupWindowData {
pub fn is_none(&self) -> bool {
match self {
PopupWindowData::None => true,
_ => false,
}
}
}
#[derive(Clone)]
@ -140,7 +158,10 @@ impl EditWindowUIState {
}
}
pub fn register_edit_ui(app: &mut bevy::prelude::App) -> &mut bevy::prelude::App {
pub fn register_edit_ui(
//formatting comment
app: &mut bevy::prelude::App,
) -> &mut bevy::prelude::App {
app.insert_resource(EditWindowUIState {
brush_color: egui_color_from(Color::RED),
meshes: Vec::new(),
@ -157,7 +178,11 @@ pub fn register_edit_ui(app: &mut bevy::prelude::App) -> &mut bevy::prelude::App
app
}
pub fn startup_system_edit_ui(commands: Commands, mut shared_ui_state: ResMut<EditWindowUIState>) {
pub fn startup_system_edit_ui(
// formatting comment
commands: Commands,
mut shared_ui_state: ResMut<EditWindowUIState>,
) {
spawn_camera(commands);
shared_ui_state
.structure
@ -215,10 +240,8 @@ pub fn edit_click_events(
octtree_ray_overlap(&eoct, &obb, ray.origin, ray.direction.normalize())
};
dbg!(&shared_ui_state.egui.windows);
let scale = egui_settings.scale_factor;
let mod_cursor_pos = Pos2::new(cursor_pos.x / scale, cursor_pos.y / scale);
dbg!(&mod_cursor_pos);
for rect in &shared_ui_state.egui.windows {
if rect.contains(mod_cursor_pos) {
return;
@ -362,10 +385,11 @@ pub fn edit_window_ui(
for window_entity in &windows {
let ctx = contexts.ctx_for_window_mut(window_entity);
let pos = ctx.memory(|memory| {
if !memory.is_popup_open(shared_ui_state.egui.popup_identifier.unwrap()) {
return None;
if let PopupWindowData::StructureElement(_) = shared_ui_state.popup {
memory.area_rect(shared_ui_state.egui.popup_identifier.unwrap())
} else {
None
}
memory.area_rect(shared_ui_state.egui.popup_identifier.unwrap())
});
if let Some(pos) = pos {
shared_ui_state.egui.windows.push(pos);
@ -383,86 +407,88 @@ pub fn edit_window_ui(
}
response.show(contexts.ctx_mut(), |ui: &mut egui::Ui| {
ui.label("This tool is in early development.");
ScrollArea::vertical().show(ui, |ui| {
let mut label = String::from("Pre-Alpha");
use std::fmt::Write;
writeln!(label, " Controls:").ok();
writeln!(label, "click adds a voxel:").ok();
writeln!(label, "R+click removes a voxel:").ok();
writeln!(label, "E+click paints (edits) a voxel:").ok();
color_picker::color_picker_hsva_2d(
ui,
&mut shared_ui_state.brush_color,
color_picker::Alpha::Opaque,
);
ui.label(label);
let mut color_to_set: Option<Color> = None;
for each in &shared_ui_state.meshes {
ui.vertical(|ui| {
//color palette clickables.
let handle = each.id.clone();
let asset = oct_assets.get(handle);
if asset.is_some() {
let list = {
let eoct = asset.unwrap().model.read().unwrap();
eoct.collect_voxels()
};
ui.collapsing("Mesh Tools", |ui| {
let mut label = String::from("Controls:");
writeln!(label, "").ok();
writeln!(label, "click adds a voxel:").ok();
writeln!(label, "R+click removes a voxel:").ok();
writeln!(label, "E+click paints (edits) a voxel:").ok();
color_picker::color_picker_hsva_2d(
ui,
&mut shared_ui_state.brush_color,
color_picker::Alpha::Opaque,
);
ui.label(label);
let mut color_to_set: Option<Color> = None;
for each in &shared_ui_state.meshes {
ui.vertical(|ui| {
//color palette clickables.
let handle = each.id.clone();
let asset = oct_assets.get(handle);
if asset.is_some() {
let list = {
let eoct = asset.unwrap().model.read().unwrap();
eoct.collect_voxels()
};
let mut count: Vec<(Color, usize)> = Vec::new();
fn eq(c1: &Color, c2: &mut Color) -> bool {
c1.r() == c2.r() && c1.g() == c2.g() && c1.b() == c2.b()
}
for (_, _, color) in &list {
let mut is_committed = false;
for (each_col, each_count) in &mut count {
if eq(color, each_col) {
*each_count += 1;
is_committed = true;
break;
}
let mut count: Vec<(Color, usize)> = Vec::new();
fn eq(c1: &Color, c2: &mut Color) -> bool {
c1.r() == c2.r() && c1.g() == c2.g() && c1.b() == c2.b()
}
if !is_committed {
count.push((color.clone(), 1));
}
}
count.sort_by(|a, b| b.1.cmp(&a.1));
if !count.is_empty() {
ui.label(each.path.clone());
ui.horizontal_wrapped(|ui| {
for (color, count) in count {
let button = egui::Button::new(count.to_string())
.fill(egui_color_from(color));
if ui.add(button).clicked() {
color_to_set = Some(color);
for (_, _, color) in &list {
let mut is_committed = false;
for (each_col, each_count) in &mut count {
if eq(color, each_col) {
*each_count += 1;
is_committed = true;
break;
}
}
});
if !is_committed {
count.push((color.clone(), 1));
}
}
count.sort_by(|a, b| b.1.cmp(&a.1));
if !count.is_empty() {
ui.label(each.path.clone());
ui.horizontal_wrapped(|ui| {
for (color, count) in count {
let button = egui::Button::new(count.to_string())
.fill(egui_color_from(color));
if ui.add(button).clicked() {
color_to_set = Some(color);
}
}
});
}
}
}
});
}
if let Some(color) = color_to_set {
shared_ui_state.brush_color = egui_color_from(color);
}
if ui.button("Add Origin Voxel").clicked() {
//
for pair in &mut pairs.handles {
let id = pair.oct_handle.clone();
let tree = oct_assets.get_mut(id);
if tree.is_some() {
let tree = tree.unwrap();
{
let mut eoct = tree.model.write().unwrap();
eoct.set_voxel_at_location(
Vec3::ZERO,
color_from(shared_ui_state.brush_color),
);
});
}
if let Some(color) = color_to_set {
shared_ui_state.brush_color = egui_color_from(color);
}
if ui.button("Add Origin Voxel").clicked() {
//
for pair in &mut pairs.handles {
let id = pair.oct_handle.clone();
let tree = oct_assets.get_mut(id);
if tree.is_some() {
let tree = tree.unwrap();
{
let mut eoct = tree.model.write().unwrap();
eoct.set_voxel_at_location(
Vec3::ZERO,
color_from(shared_ui_state.brush_color),
);
}
}
}
}
}
let response = ui.button("Save Any Changes");
if response.clicked() {
});
show_editable_stringtree(ui, &mut shared_ui_state);
if ui.button("Save Any Changes").clicked() {
//save all files.
for each in &mut shared_ui_state.meshes {
if each.has_changed_since_last_save {
@ -477,40 +503,67 @@ pub fn edit_window_ui(
);
if result {
each.has_changed_since_last_save = false;
println!("{} saved to disk.", &path);
}
}
}
}
}
show_editable_stringtree(
ui,
shared_ui_state.egui.clone(),
&mut shared_ui_state.structure,
&response,
);
});
});
show_popup(&mut shared_ui_state, &mut contexts);
}
pub fn show_editable_stringtree(
ui: &mut egui::Ui,
state: EditWindowEguiState,
tree: &mut StringTree,
response: &Response,
) {
egui::popup_below_widget(ui, state.popup_identifier.unwrap(), response, |ui| {
ScrollArea::vertical().show(ui, |ui| {
ui.vertical(|ui| {
for _ in 0..100 {
ui.label("filler");
pub fn show_popup(state: &mut EditWindowUIState, contexts: &mut EguiContexts) {
let mut change_state = None;
let mut reparent = None;
match &state.popup {
PopupWindowData::None => return,
PopupWindowData::StructureElement(name) => {
//formatting comment
let response = egui::Window::new("edit structure element ".to_owned() + &name.clone())
.id(state.egui.popup_identifier.unwrap());
response.show(contexts.ctx_mut(), |ui| {
//formatting comment
let cur = name.clone();
ui.label("what do you want to do with ".to_owned() + &name + "?");
enum Tasks {
MoveElement,
RemoveElement,
DeleteElementWithChildren,
DeleteElementAndReparent,
}
ui.collapsing("Reparent to child of", |ui| {
ui.vertical(|ui| {
for each in state.structure.list_of_elements() {
if each != cur && Some(&each) != state.structure.parent_of(&cur.clone())
{
if ui.button(&each).clicked() {
reparent = Some((cur.clone(), each));
change_state = Some(PopupWindowData::None);
}
}
}
});
});
// todo: rename action. edit subject action (mesh, light), remove action (with, without reparenting)
if ui.button("Cancel").clicked() {
change_state = Some(PopupWindowData::None);
}
});
});
});
}
}
if change_state.is_some() {
state.popup = change_state.unwrap();
}
if let Some((cur, next)) = reparent {
state.structure.move_branch(&cur, &next);
}
}
pub fn show_editable_stringtree(ui: &mut egui::Ui, state: &mut EditWindowUIState) {
ui.collapsing("Model Structure", |ui| {
ui.vertical(|ui| {
for each in &mut tree.root {
for each in &mut state.structure.root {
match each {
super::ui_extensions::StringTreeElement::None => {}
super::ui_extensions::StringTreeElement::Element(name, children) => {
@ -518,14 +571,21 @@ pub fn show_editable_stringtree(
ui.label(">".to_owned());
if ui.button(name.clone()).clicked() {
//
ui.memory_mut(|mem| {
mem.toggle_popup(state.popup_identifier.unwrap())
});
let mut should_close = false;
if let PopupWindowData::StructureElement(val) = &state.popup {
if val == name {
should_close = true;
}
}
if should_close {
state.popup = PopupWindowData::None;
} else {
state.popup = PopupWindowData::StructureElement(name.clone())
}
}
});
for each in children.as_mut() {
show_child(ui, each, 1);
for each in children.as_ref() {
show_child(ui, each, 1, &mut state.popup);
}
}
}
@ -533,12 +593,15 @@ pub fn show_editable_stringtree(
});
});
}
pub fn show_child(ui: &mut egui::Ui, subject: &mut StringTreeElement, depth: usize) {
//
pub fn show_child(
ui: &mut egui::Ui,
subject: &StringTreeElement,
depth: usize,
state: &mut PopupWindowData,
) {
match subject {
StringTreeElement::None => {}
StringTreeElement::Element(name, children) => {
//
let mut prec = String::from("");
for i in 0..depth {
if i == 0 {
@ -550,10 +613,22 @@ pub fn show_child(ui: &mut egui::Ui, subject: &mut StringTreeElement, depth: usi
prec = prec + ">";
ui.horizontal(|ui| {
ui.label(prec);
ui.button(name.clone()).clicked();
if ui.button(name.clone()).clicked() {
let mut should_close = false;
if let PopupWindowData::StructureElement(val) = state {
if val == name {
should_close = true;
}
}
if should_close {
*state = PopupWindowData::None;
} else {
*state = PopupWindowData::StructureElement(name.clone())
}
}
});
for each in children.as_mut() {
show_child(ui, each, depth + 1);
for each in children.as_ref() {
show_child(ui, each, depth + 1, state);
}
}
}

View File

@ -263,6 +263,28 @@ impl StringTree {
}
false
} */
pub fn list_of_elements(&self) -> Vec<String> {
let mut list: Vec<String> = Vec::new();
let mut to_search = Vec::new();
for each in &self.root {
to_search.push(each);
}
while !to_search.is_empty() {
let next = to_search.pop();
if let Some(next) = next {
if let Some(name) = next.name_of() {
list.push(name.clone());
}
if let StringTreeElement::Element(_, children) = next {
for each in children.as_ref() {
to_search.push(each);
}
}
}
}
return list;
}
}
#[test]
pub fn test_string_tree() {