basic stringtree movement
This commit is contained in:
parent
a9d346c411
commit
18a93e44df
|
@ -17,7 +17,7 @@ use bevy_egui::{
|
||||||
self, color_picker,
|
self, color_picker,
|
||||||
ecolor::{hsv_from_rgb, rgb_from_hsv},
|
ecolor::{hsv_from_rgb, rgb_from_hsv},
|
||||||
epaint::Hsva,
|
epaint::Hsva,
|
||||||
Id, Pos2, Rect, Response, ScrollArea,
|
Id, Pos2, Rect, ScrollArea,
|
||||||
},
|
},
|
||||||
EguiContexts, EguiPlugin, EguiSettings,
|
EguiContexts, EguiPlugin, EguiSettings,
|
||||||
};
|
};
|
||||||
|
@ -39,6 +39,9 @@ use super::{
|
||||||
orbit_camera::orbit_camera::{pan_orbit_camera, spawn_camera},
|
orbit_camera::orbit_camera::{pan_orbit_camera, spawn_camera},
|
||||||
ui_extensions::{StringTree, StringTreeElement},
|
ui_extensions::{StringTree, StringTreeElement},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
pub struct AssetEditData {
|
pub struct AssetEditData {
|
||||||
path: String,
|
path: String,
|
||||||
id: Handle<OctTreeAsset>,
|
id: Handle<OctTreeAsset>,
|
||||||
|
@ -51,6 +54,21 @@ pub struct EditWindowUIState {
|
||||||
meshes: Vec<AssetEditData>,
|
meshes: Vec<AssetEditData>,
|
||||||
structure: StringTree,
|
structure: StringTree,
|
||||||
egui: EditWindowEguiState,
|
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)]
|
#[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 {
|
app.insert_resource(EditWindowUIState {
|
||||||
brush_color: egui_color_from(Color::RED),
|
brush_color: egui_color_from(Color::RED),
|
||||||
meshes: Vec::new(),
|
meshes: Vec::new(),
|
||||||
|
@ -157,7 +178,11 @@ pub fn register_edit_ui(app: &mut bevy::prelude::App) -> &mut bevy::prelude::App
|
||||||
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);
|
spawn_camera(commands);
|
||||||
shared_ui_state
|
shared_ui_state
|
||||||
.structure
|
.structure
|
||||||
|
@ -215,10 +240,8 @@ pub fn edit_click_events(
|
||||||
|
|
||||||
octtree_ray_overlap(&eoct, &obb, ray.origin, ray.direction.normalize())
|
octtree_ray_overlap(&eoct, &obb, ray.origin, ray.direction.normalize())
|
||||||
};
|
};
|
||||||
dbg!(&shared_ui_state.egui.windows);
|
|
||||||
let scale = egui_settings.scale_factor;
|
let scale = egui_settings.scale_factor;
|
||||||
let mod_cursor_pos = Pos2::new(cursor_pos.x / scale, cursor_pos.y / scale);
|
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 {
|
for rect in &shared_ui_state.egui.windows {
|
||||||
if rect.contains(mod_cursor_pos) {
|
if rect.contains(mod_cursor_pos) {
|
||||||
return;
|
return;
|
||||||
|
@ -362,10 +385,11 @@ pub fn edit_window_ui(
|
||||||
for window_entity in &windows {
|
for window_entity in &windows {
|
||||||
let ctx = contexts.ctx_for_window_mut(window_entity);
|
let ctx = contexts.ctx_for_window_mut(window_entity);
|
||||||
let pos = ctx.memory(|memory| {
|
let pos = ctx.memory(|memory| {
|
||||||
if !memory.is_popup_open(shared_ui_state.egui.popup_identifier.unwrap()) {
|
if let PopupWindowData::StructureElement(_) = shared_ui_state.popup {
|
||||||
return None;
|
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 {
|
if let Some(pos) = pos {
|
||||||
shared_ui_state.egui.windows.push(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| {
|
response.show(contexts.ctx_mut(), |ui: &mut egui::Ui| {
|
||||||
|
ui.label("This tool is in early development.");
|
||||||
ScrollArea::vertical().show(ui, |ui| {
|
ScrollArea::vertical().show(ui, |ui| {
|
||||||
let mut label = String::from("Pre-Alpha");
|
ui.collapsing("Mesh Tools", |ui| {
|
||||||
use std::fmt::Write;
|
let mut label = String::from("Controls:");
|
||||||
writeln!(label, " Controls:").ok();
|
writeln!(label, "").ok();
|
||||||
writeln!(label, "click adds a voxel:").ok();
|
writeln!(label, "click adds a voxel:").ok();
|
||||||
writeln!(label, "R+click removes a voxel:").ok();
|
writeln!(label, "R+click removes a voxel:").ok();
|
||||||
writeln!(label, "E+click paints (edits) a voxel:").ok();
|
writeln!(label, "E+click paints (edits) a voxel:").ok();
|
||||||
color_picker::color_picker_hsva_2d(
|
color_picker::color_picker_hsva_2d(
|
||||||
ui,
|
ui,
|
||||||
&mut shared_ui_state.brush_color,
|
&mut shared_ui_state.brush_color,
|
||||||
color_picker::Alpha::Opaque,
|
color_picker::Alpha::Opaque,
|
||||||
);
|
);
|
||||||
ui.label(label);
|
ui.label(label);
|
||||||
let mut color_to_set: Option<Color> = None;
|
let mut color_to_set: Option<Color> = None;
|
||||||
for each in &shared_ui_state.meshes {
|
for each in &shared_ui_state.meshes {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
//color palette clickables.
|
//color palette clickables.
|
||||||
let handle = each.id.clone();
|
let handle = each.id.clone();
|
||||||
let asset = oct_assets.get(handle);
|
let asset = oct_assets.get(handle);
|
||||||
if asset.is_some() {
|
if asset.is_some() {
|
||||||
let list = {
|
let list = {
|
||||||
let eoct = asset.unwrap().model.read().unwrap();
|
let eoct = asset.unwrap().model.read().unwrap();
|
||||||
eoct.collect_voxels()
|
eoct.collect_voxels()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut count: Vec<(Color, usize)> = Vec::new();
|
let mut count: Vec<(Color, usize)> = Vec::new();
|
||||||
fn eq(c1: &Color, c2: &mut Color) -> bool {
|
fn eq(c1: &Color, c2: &mut Color) -> bool {
|
||||||
c1.r() == c2.r() && c1.g() == c2.g() && c1.b() == c2.b()
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !is_committed {
|
for (_, _, color) in &list {
|
||||||
count.push((color.clone(), 1));
|
let mut is_committed = false;
|
||||||
}
|
for (each_col, each_count) in &mut count {
|
||||||
}
|
if eq(color, each_col) {
|
||||||
count.sort_by(|a, b| b.1.cmp(&a.1));
|
*each_count += 1;
|
||||||
if !count.is_empty() {
|
is_committed = true;
|
||||||
ui.label(each.path.clone());
|
break;
|
||||||
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 !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 {
|
||||||
if let Some(color) = color_to_set {
|
shared_ui_state.brush_color = egui_color_from(color);
|
||||||
shared_ui_state.brush_color = egui_color_from(color);
|
}
|
||||||
}
|
if ui.button("Add Origin Voxel").clicked() {
|
||||||
if ui.button("Add Origin Voxel").clicked() {
|
//
|
||||||
//
|
for pair in &mut pairs.handles {
|
||||||
for pair in &mut pairs.handles {
|
let id = pair.oct_handle.clone();
|
||||||
let id = pair.oct_handle.clone();
|
let tree = oct_assets.get_mut(id);
|
||||||
let tree = oct_assets.get_mut(id);
|
if tree.is_some() {
|
||||||
if tree.is_some() {
|
let tree = tree.unwrap();
|
||||||
let tree = tree.unwrap();
|
{
|
||||||
{
|
let mut eoct = tree.model.write().unwrap();
|
||||||
let mut eoct = tree.model.write().unwrap();
|
eoct.set_voxel_at_location(
|
||||||
eoct.set_voxel_at_location(
|
Vec3::ZERO,
|
||||||
Vec3::ZERO,
|
color_from(shared_ui_state.brush_color),
|
||||||
color_from(shared_ui_state.brush_color),
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
let response = ui.button("Save Any Changes");
|
show_editable_stringtree(ui, &mut shared_ui_state);
|
||||||
if response.clicked() {
|
if ui.button("Save Any Changes").clicked() {
|
||||||
//save all files.
|
//save all files.
|
||||||
for each in &mut shared_ui_state.meshes {
|
for each in &mut shared_ui_state.meshes {
|
||||||
if each.has_changed_since_last_save {
|
if each.has_changed_since_last_save {
|
||||||
|
@ -477,40 +503,67 @@ pub fn edit_window_ui(
|
||||||
);
|
);
|
||||||
if result {
|
if result {
|
||||||
each.has_changed_since_last_save = false;
|
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(
|
pub fn show_popup(state: &mut EditWindowUIState, contexts: &mut EguiContexts) {
|
||||||
ui: &mut egui::Ui,
|
let mut change_state = None;
|
||||||
state: EditWindowEguiState,
|
let mut reparent = None;
|
||||||
tree: &mut StringTree,
|
match &state.popup {
|
||||||
response: &Response,
|
PopupWindowData::None => return,
|
||||||
) {
|
PopupWindowData::StructureElement(name) => {
|
||||||
egui::popup_below_widget(ui, state.popup_identifier.unwrap(), response, |ui| {
|
//formatting comment
|
||||||
ScrollArea::vertical().show(ui, |ui| {
|
let response = egui::Window::new("edit structure element ".to_owned() + &name.clone())
|
||||||
ui.vertical(|ui| {
|
.id(state.egui.popup_identifier.unwrap());
|
||||||
for _ in 0..100 {
|
response.show(contexts.ctx_mut(), |ui| {
|
||||||
ui.label("filler");
|
//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.collapsing("Model Structure", |ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
for each in &mut tree.root {
|
for each in &mut state.structure.root {
|
||||||
match each {
|
match each {
|
||||||
super::ui_extensions::StringTreeElement::None => {}
|
super::ui_extensions::StringTreeElement::None => {}
|
||||||
super::ui_extensions::StringTreeElement::Element(name, children) => {
|
super::ui_extensions::StringTreeElement::Element(name, children) => {
|
||||||
|
@ -518,14 +571,21 @@ pub fn show_editable_stringtree(
|
||||||
ui.label(">".to_owned());
|
ui.label(">".to_owned());
|
||||||
if ui.button(name.clone()).clicked() {
|
if ui.button(name.clone()).clicked() {
|
||||||
//
|
//
|
||||||
|
let mut should_close = false;
|
||||||
ui.memory_mut(|mem| {
|
if let PopupWindowData::StructureElement(val) = &state.popup {
|
||||||
mem.toggle_popup(state.popup_identifier.unwrap())
|
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() {
|
for each in children.as_ref() {
|
||||||
show_child(ui, each, 1);
|
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 {
|
match subject {
|
||||||
StringTreeElement::None => {}
|
StringTreeElement::None => {}
|
||||||
StringTreeElement::Element(name, children) => {
|
StringTreeElement::Element(name, children) => {
|
||||||
//
|
|
||||||
let mut prec = String::from("");
|
let mut prec = String::from("");
|
||||||
for i in 0..depth {
|
for i in 0..depth {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -550,10 +613,22 @@ pub fn show_child(ui: &mut egui::Ui, subject: &mut StringTreeElement, depth: usi
|
||||||
prec = prec + ">";
|
prec = prec + ">";
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label(prec);
|
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() {
|
for each in children.as_ref() {
|
||||||
show_child(ui, each, depth + 1);
|
show_child(ui, each, depth + 1, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,6 +263,28 @@ impl StringTree {
|
||||||
}
|
}
|
||||||
false
|
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]
|
#[test]
|
||||||
pub fn test_string_tree() {
|
pub fn test_string_tree() {
|
||||||
|
|
Loading…
Reference in a new issue