track untrackeds
This commit is contained in:
parent
25f5ea3971
commit
7d2ff0408b
16
assets/test.vvs
Normal file
16
assets/test.vvs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
version 1
|
||||||
|
|
||||||
|
torso|head|waist|frontleftpaw|frontrightpaw
|
||||||
|
head|leftear|rightear
|
||||||
|
waist|tail|backleftpaw|backrightpaw
|
||||||
|
||
|
||||||
|
element|torso
|
||||||
|
position|0|0|0
|
||||||
|
scale|0.25|0.25|0.25
|
||||||
|
rotation|0|0|0|1
|
||||||
|
element|head
|
||||||
|
position|0|0|0
|
||||||
|
scale|1|1|1
|
||||||
|
rotation|0|0|0|1
|
||||||
|
||
|
||||||
|
head|grid|test.vvg
|
594
src/vvedit/s_ui_helpers_and_popup.rs
Normal file
594
src/vvedit/s_ui_helpers_and_popup.rs
Normal file
|
@ -0,0 +1,594 @@
|
||||||
|
use std::{fs, io, path::Path};
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
asset::{AssetServer, Assets},
|
||||||
|
ecs::{
|
||||||
|
entity::Entity,
|
||||||
|
event::EventWriter,
|
||||||
|
system::{Commands, ResMut},
|
||||||
|
},
|
||||||
|
math::{Quat, Vec3},
|
||||||
|
render::color::Color,
|
||||||
|
utils::hashbrown::hash_map::Entry,
|
||||||
|
};
|
||||||
|
use bevy_egui::{
|
||||||
|
egui::{
|
||||||
|
self,
|
||||||
|
ecolor::{hsv_from_rgb, rgb_from_hsv},
|
||||||
|
epaint::Hsva,
|
||||||
|
},
|
||||||
|
EguiContexts,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
vvedit::s_editor_ui::{GridEditData, Selection, StructureEditData},
|
||||||
|
vvlib::{
|
||||||
|
s_identifier_validation::{self, is_valid},
|
||||||
|
s_oct_asset::OctTreeAsset,
|
||||||
|
s_structure_asset::{StructureAsset, StructureUpdateMessage, StructureUpdateType},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
s_editor_ui::{EditWindowUIState, PopupWindowMode},
|
||||||
|
s_string_tree::{StringTree, StringTreeElement},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn color_from(egui_color: Hsva) -> Color {
|
||||||
|
let rgb = rgb_from_hsv((egui_color.h, egui_color.s, egui_color.v));
|
||||||
|
return Color::rgb_from_array(rgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn egui_color_from(color: Color) -> Hsva {
|
||||||
|
let x = hsv_from_rgb([color.r(), color.g(), color.b()]);
|
||||||
|
|
||||||
|
return Hsva::new(x.0, x.1, x.2, 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn round_trip_color() {
|
||||||
|
use rand::Rng;
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let min = 0.;
|
||||||
|
let max = 1.;
|
||||||
|
for _ in 0..10000 {
|
||||||
|
let r = rng.gen_range(min..max);
|
||||||
|
let g = rng.gen_range(min..max);
|
||||||
|
let b = rng.gen_range(min..max);
|
||||||
|
let mut color = Color::rgb(r, g, b);
|
||||||
|
let mut egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
egui_color = egui_color_from(color);
|
||||||
|
color = color_from(egui_color);
|
||||||
|
assert_eq!((color.r() * 255.).floor(), (r * 255.).floor());
|
||||||
|
assert_eq!((color.g() * 255.).floor(), (g * 255.).floor());
|
||||||
|
assert_eq!((color.b() * 255.).floor(), (b * 255.).floor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show_popup(
|
||||||
|
state: &mut EditWindowUIState,
|
||||||
|
contexts: &mut EguiContexts,
|
||||||
|
asset_server: &mut ResMut<AssetServer>,
|
||||||
|
structure_assets: &mut ResMut<Assets<StructureAsset>>,
|
||||||
|
event_writer: &mut EventWriter<StructureUpdateMessage>,
|
||||||
|
mut commands: &mut Commands,
|
||||||
|
) {
|
||||||
|
enum PopupStateChange {
|
||||||
|
None,
|
||||||
|
RemoveStructureElement(String, String, bool), //structure subject, name of element, keep children(reparenting upward) or drop
|
||||||
|
RenameComplete,
|
||||||
|
Reparent(String, String, String), //structure subject, name of element to reparent, new parent
|
||||||
|
Addition(String, String, String), //structure subject, new element name, new parent
|
||||||
|
Cancel,
|
||||||
|
}
|
||||||
|
let mut state_change = PopupStateChange::None;
|
||||||
|
//let mut added_valid_name = false;
|
||||||
|
match &mut state.popup {
|
||||||
|
PopupWindowMode::None => return,
|
||||||
|
PopupWindowMode::EditStructureElement(structure_selection, name, rename) => {
|
||||||
|
//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 + "?");
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
//.
|
||||||
|
ui.label("rename element: ");
|
||||||
|
let mut rename_string = rename.clone();
|
||||||
|
ui.text_edit_singleline(&mut rename_string);
|
||||||
|
if s_identifier_validation::is_valid(rename_string.clone()) {
|
||||||
|
*rename = rename_string;
|
||||||
|
}
|
||||||
|
if ui.button("Confirm and change name").clicked() {
|
||||||
|
//.
|
||||||
|
state_change = PopupStateChange::RenameComplete;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("remove and reparent to parent").clicked() {
|
||||||
|
state_change = PopupStateChange::RemoveStructureElement(
|
||||||
|
structure_selection.clone(),
|
||||||
|
name.clone(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ui.button("remove and drop children").clicked() {
|
||||||
|
state_change = PopupStateChange::RemoveStructureElement(
|
||||||
|
structure_selection.clone(),
|
||||||
|
name.clone(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
enum Tasks {
|
||||||
|
MoveElement,
|
||||||
|
RemoveElement,
|
||||||
|
DeleteElementWithChildren,
|
||||||
|
DeleteElementAndReparent,
|
||||||
|
}
|
||||||
|
ui.collapsing("Reparent to child of", |ui| {
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
let mut selected_structure = false;
|
||||||
|
let mut selection = None;
|
||||||
|
if structure_selection != "" {
|
||||||
|
for structure in &state.structures {
|
||||||
|
if structure.path == structure_selection.clone() {
|
||||||
|
let asset = structure_assets.get_mut(structure.id.clone());
|
||||||
|
if asset.is_some() {
|
||||||
|
selection = Some(&mut asset.unwrap().layout);
|
||||||
|
selected_structure = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if selected_structure {
|
||||||
|
let selection = selection.unwrap();
|
||||||
|
for each in selection.list_of_elements() {
|
||||||
|
if each != cur
|
||||||
|
&& Some(&each) != selection.parent_of(&cur.clone())
|
||||||
|
&& !selection.is_upstream_of(&cur, &each)
|
||||||
|
{
|
||||||
|
if ui.button(&each).clicked() {
|
||||||
|
state_change = PopupStateChange::Reparent(
|
||||||
|
structure_selection.clone(),
|
||||||
|
cur.clone(),
|
||||||
|
each,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if selection.parent_of(&cur).is_some() {
|
||||||
|
if ui.button("None").clicked() {
|
||||||
|
state_change = PopupStateChange::Reparent(
|
||||||
|
structure_selection.clone(),
|
||||||
|
cur.clone(),
|
||||||
|
"".into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// todo: rename action. edit subject action (mesh, light), remove action (with, without reparenting)
|
||||||
|
if ui.button("Cancel").clicked() {
|
||||||
|
state_change = PopupStateChange::Cancel;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
PopupWindowMode::CreateStructureElement(structure_selection, name, parent) => {
|
||||||
|
let response = egui::Window::new("new structure element ".to_owned() + &name.clone())
|
||||||
|
.id(state.egui.popup_identifier.unwrap());
|
||||||
|
response.show(contexts.ctx_mut(), |ui| {
|
||||||
|
let mut selected_structure = false;
|
||||||
|
let mut selection = None;
|
||||||
|
if structure_selection != "" {
|
||||||
|
for structure in &state.structures {
|
||||||
|
if structure.path == structure_selection.clone() {
|
||||||
|
let asset = structure_assets.get_mut(structure.id.clone());
|
||||||
|
if asset.is_some() {
|
||||||
|
selection = Some(&mut asset.unwrap().layout);
|
||||||
|
selected_structure = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if selected_structure {
|
||||||
|
let selection = selection.unwrap();
|
||||||
|
ui.label("please name the new structure node.");
|
||||||
|
let mut newname = name.clone();
|
||||||
|
ui.text_edit_singleline(&mut newname);
|
||||||
|
if is_valid(newname.clone()) && !selection.is_present(&newname) {
|
||||||
|
*name = newname;
|
||||||
|
}
|
||||||
|
if ui.button("Confirm and add.").clicked() {
|
||||||
|
//added_valid_name = true;
|
||||||
|
state_change = PopupStateChange::Addition(
|
||||||
|
structure_selection.clone(),
|
||||||
|
name.clone(),
|
||||||
|
parent.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ui.collapsing(
|
||||||
|
"parent status: ".to_owned() + parent.clone().as_str(),
|
||||||
|
|ui| {
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.radio_value(parent, "".into(), "Root level - no parent");
|
||||||
|
for each in selection.list_of_elements() {
|
||||||
|
ui.radio_value(parent, each.clone(), each.clone());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
PopupWindowMode::LoadFile(current_selection, counter, files) => {
|
||||||
|
// immediate mode means we run every frame
|
||||||
|
if *counter == i32::MIN {
|
||||||
|
// do nothing. disk inaccessible
|
||||||
|
} else if (*counter > (30 * 64)) | files.is_empty() {
|
||||||
|
//rescan disk
|
||||||
|
let x = fs::read_dir("assets");
|
||||||
|
if let Ok(x) = x {
|
||||||
|
let x: Result<Vec<String>, io::Error> = x
|
||||||
|
.into_iter()
|
||||||
|
.map(
|
||||||
|
//
|
||||||
|
|x| {
|
||||||
|
x.map(
|
||||||
|
//
|
||||||
|
|entry| entry.path().to_string_lossy().into_owned(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
if let Ok(x) = x {
|
||||||
|
*files = x;
|
||||||
|
*counter = 0;
|
||||||
|
} else {
|
||||||
|
*counter = i32::MIN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*counter = i32::MIN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*counter += 1;
|
||||||
|
}
|
||||||
|
let response =
|
||||||
|
egui::Window::new("load file".to_owned()).id(state.egui.popup_identifier.unwrap());
|
||||||
|
response.show(contexts.ctx_mut(), |ui| {
|
||||||
|
let mut selection_updated = current_selection.clone();
|
||||||
|
ui.text_edit_singleline(&mut selection_updated);
|
||||||
|
*current_selection = selection_updated.clone();
|
||||||
|
*current_selection = current_selection.replace("assets/", "");
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum Extension {
|
||||||
|
Invalid,
|
||||||
|
Structure,
|
||||||
|
Grid,
|
||||||
|
}
|
||||||
|
let mut extension = Extension::Invalid;
|
||||||
|
if current_selection.ends_with(".vvg") {
|
||||||
|
extension = Extension::Grid;
|
||||||
|
}
|
||||||
|
if current_selection.ends_with(".vvs") {
|
||||||
|
extension = Extension::Structure;
|
||||||
|
}
|
||||||
|
if Path::new(("assets/".to_owned() + current_selection.as_str()).as_str()).exists()
|
||||||
|
& (current_selection.as_str() != "")
|
||||||
|
& !(extension == Extension::Invalid)
|
||||||
|
{
|
||||||
|
if ui.button("Load file").clicked() {
|
||||||
|
*current_selection = current_selection.replace("assets/", "");
|
||||||
|
let path_pre = current_selection.clone();
|
||||||
|
match extension {
|
||||||
|
Extension::Invalid => {}
|
||||||
|
Extension::Structure => {
|
||||||
|
let handle = asset_server.load::<StructureAsset>(path_pre.clone());
|
||||||
|
let data = StructureEditData {
|
||||||
|
path: path_pre,
|
||||||
|
id: handle,
|
||||||
|
has_changed_since_last_save: false,
|
||||||
|
edit_entity: Entity::PLACEHOLDER, //BAD BAD BAD
|
||||||
|
};
|
||||||
|
let mut loaded_already = false;
|
||||||
|
for each in &state.structures {
|
||||||
|
if each.id == data.id {
|
||||||
|
loaded_already = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !loaded_already {
|
||||||
|
state.structures.push(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Extension::Grid => {
|
||||||
|
let handle = asset_server.load::<OctTreeAsset>(path_pre.clone());
|
||||||
|
let data = GridEditData {
|
||||||
|
path: path_pre,
|
||||||
|
id: handle,
|
||||||
|
has_changed_since_last_save: false,
|
||||||
|
};
|
||||||
|
let mut loaded_already = false;
|
||||||
|
for each in &state.grids {
|
||||||
|
if each.id == data.id {
|
||||||
|
loaded_already = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !loaded_already {
|
||||||
|
state.grids.push(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui.label("✔");
|
||||||
|
} else {
|
||||||
|
ui.label("✘ not a valid file to load");
|
||||||
|
}
|
||||||
|
if ui.button("close").clicked() {
|
||||||
|
state_change = PopupStateChange::Cancel;
|
||||||
|
}
|
||||||
|
ui.separator();
|
||||||
|
for each in files {
|
||||||
|
if ui.button(each.as_str()).clicked() {
|
||||||
|
*current_selection = each.clone();
|
||||||
|
*current_selection = current_selection.replace("assets/", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match state_change {
|
||||||
|
PopupStateChange::None => {} // nothing to do if state does not change
|
||||||
|
PopupStateChange::RemoveStructureElement(subject, element, keep_children) => {
|
||||||
|
let mut selected_structure = false;
|
||||||
|
let mut selection = None;
|
||||||
|
if subject != "" {
|
||||||
|
for structure in &mut state.structures {
|
||||||
|
if structure.path == subject {
|
||||||
|
let asset = structure_assets.get_mut(structure.id.clone());
|
||||||
|
if asset.is_some() {
|
||||||
|
structure.has_changed_since_last_save = true;
|
||||||
|
selection = Some(&mut asset.unwrap().layout);
|
||||||
|
selected_structure = true;
|
||||||
|
event_writer.send(StructureUpdateMessage {
|
||||||
|
update_type: StructureUpdateType::Rebuild,
|
||||||
|
entity: structure.edit_entity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if selected_structure {
|
||||||
|
let selection = selection.unwrap();
|
||||||
|
if keep_children {
|
||||||
|
selection.remove_element_preserve_branch(&element);
|
||||||
|
} else {
|
||||||
|
selection.remove_branch(&element);
|
||||||
|
}
|
||||||
|
state.popup = PopupWindowMode::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PopupStateChange::Cancel => {
|
||||||
|
state.popup = PopupWindowMode::None;
|
||||||
|
}
|
||||||
|
PopupStateChange::RenameComplete => {
|
||||||
|
if let PopupWindowMode::EditStructureElement(subject, old, new) = &state.popup {
|
||||||
|
let mut selected_structure = false;
|
||||||
|
let mut selection = None;
|
||||||
|
if subject != "" {
|
||||||
|
for structure in &mut state.structures {
|
||||||
|
if &structure.path == subject {
|
||||||
|
let asset = structure_assets.get_mut(structure.id.clone());
|
||||||
|
if asset.is_some() {
|
||||||
|
selection = Some(&mut asset.unwrap().layout);
|
||||||
|
selected_structure = true;
|
||||||
|
event_writer.send(StructureUpdateMessage {
|
||||||
|
update_type: StructureUpdateType::Rebuild,
|
||||||
|
entity: structure.edit_entity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if selected_structure {
|
||||||
|
let selection = selection.unwrap();
|
||||||
|
if selection.rename(old, new) {
|
||||||
|
structure.has_changed_since_last_save = true;
|
||||||
|
}
|
||||||
|
if let Selection::Structure(structure_name) =
|
||||||
|
state.selection.clone()
|
||||||
|
{
|
||||||
|
if let Entry::Occupied(element_select) = state
|
||||||
|
.struct_element_selections
|
||||||
|
.clone()
|
||||||
|
.entry(structure_name.clone())
|
||||||
|
{
|
||||||
|
let element_select = element_select.get();
|
||||||
|
if element_select == old {
|
||||||
|
state
|
||||||
|
.struct_element_selections
|
||||||
|
.insert(structure_name, new.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.popup = PopupWindowMode::None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PopupStateChange::Reparent(subject, cur, next) => {
|
||||||
|
if subject != "" {
|
||||||
|
for structure in &mut state.structures {
|
||||||
|
if structure.path == subject {
|
||||||
|
let asset = structure_assets.get_mut(structure.id.clone());
|
||||||
|
if asset.is_some() {
|
||||||
|
let selection = &mut asset.unwrap().layout;
|
||||||
|
if next != "" {
|
||||||
|
if selection.move_branch(&cur, &next) {
|
||||||
|
event_writer.send(StructureUpdateMessage {
|
||||||
|
update_type: StructureUpdateType::Rebuild,
|
||||||
|
entity: structure.edit_entity,
|
||||||
|
});
|
||||||
|
structure.has_changed_since_last_save = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if selection.deparent(&cur) {
|
||||||
|
event_writer.send(StructureUpdateMessage {
|
||||||
|
update_type: StructureUpdateType::Rebuild,
|
||||||
|
entity: structure.edit_entity,
|
||||||
|
});
|
||||||
|
structure.has_changed_since_last_save = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.popup = PopupWindowMode::None;
|
||||||
|
}
|
||||||
|
PopupStateChange::Addition(subject, name, parent) => {
|
||||||
|
if subject != "" {
|
||||||
|
for structure in &mut state.structures {
|
||||||
|
if structure.path == subject {
|
||||||
|
let asset = structure_assets.get_mut(structure.id.clone());
|
||||||
|
if asset.is_some() {
|
||||||
|
let selection = &mut asset.unwrap().layout;
|
||||||
|
let par = if parent == "" { None } else { Some(&parent) };
|
||||||
|
if selection.add(&name, par) {
|
||||||
|
structure.has_changed_since_last_save = true;
|
||||||
|
event_writer.send(StructureUpdateMessage {
|
||||||
|
update_type: StructureUpdateType::Rebuild,
|
||||||
|
entity: structure.edit_entity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
state.popup = PopupWindowMode::None;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show_stringtree_selector(ui: &mut egui::Ui, tree: &StringTree, selection: &mut String) {
|
||||||
|
for each in &tree.root {
|
||||||
|
match each {
|
||||||
|
super::s_string_tree::StringTreeElement::None => {}
|
||||||
|
super::s_string_tree::StringTreeElement::Element(name, children) => {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(">".to_owned());
|
||||||
|
//ui.label(name.clone());
|
||||||
|
ui.radio_value(selection, name.clone(), name.clone());
|
||||||
|
});
|
||||||
|
for each in children.as_ref() {
|
||||||
|
show_child(ui, each, 1, selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn show_child(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
subject: &StringTreeElement,
|
||||||
|
depth: usize,
|
||||||
|
selection: &mut String,
|
||||||
|
) {
|
||||||
|
match subject {
|
||||||
|
StringTreeElement::None => {}
|
||||||
|
StringTreeElement::Element(name, children) => {
|
||||||
|
let mut prec = String::from("");
|
||||||
|
for i in 0..depth {
|
||||||
|
if i == 0 {
|
||||||
|
prec = prec + "+";
|
||||||
|
} else {
|
||||||
|
prec = prec + "+";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prec = prec + ">";
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(prec);
|
||||||
|
ui.radio_value(selection, name.clone(), name.clone());
|
||||||
|
});
|
||||||
|
for each in children.as_ref() {
|
||||||
|
show_child(ui, each, depth + 1, selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn editable_vec3(ui: &mut egui::Ui, value: &mut Vec3, should_reshape: &mut bool) {
|
||||||
|
let copy = value.clone();
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("X:");
|
||||||
|
ui.add(egui::Slider::new(&mut value.x, -100f32..=100f32));
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Y:");
|
||||||
|
ui.add(egui::Slider::new(&mut value.y, -100f32..=100f32));
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Z:");
|
||||||
|
ui.add(egui::Slider::new(&mut value.z, -100f32..=100f32));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if copy != *value {
|
||||||
|
*should_reshape = true;
|
||||||
|
println!("code reached.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn editable_quat(ui: &mut egui::Ui, value: &mut Quat, should_reshape: &mut bool) {
|
||||||
|
let copy = value.clone();
|
||||||
|
let (mut x, mut y, mut z) = value.to_euler(bevy::math::EulerRot::XYZ);
|
||||||
|
x = x.to_degrees();
|
||||||
|
y = y.to_degrees();
|
||||||
|
z = z.to_degrees();
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("X:");
|
||||||
|
ui.add(egui::Slider::new(&mut x, -180f32..=180f32));
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Y:");
|
||||||
|
ui.add(egui::Slider::new(&mut y, -180f32..=180f32));
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Z:");
|
||||||
|
ui.add(egui::Slider::new(&mut z, -180f32..=180f32));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
*value = Quat::from_euler(
|
||||||
|
bevy::math::EulerRot::XYZ,
|
||||||
|
x.to_radians(),
|
||||||
|
y.to_radians(),
|
||||||
|
z.to_radians(),
|
||||||
|
);
|
||||||
|
if copy != *value {
|
||||||
|
*should_reshape = true;
|
||||||
|
println!("code reached.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pub fn set_visibility
|
8
src/vvedit/what its like to load a file.md
Normal file
8
src/vvedit/what its like to load a file.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
what its like to load a file
|
||||||
|
default structure is empty
|
||||||
|
no meshes loaded
|
||||||
|
load a structure: structure is updated. load all meshes in the structure.
|
||||||
|
load a mesh: add a mesh node in the structure at root with name of mesh
|
||||||
|
|
||||||
|
~~BONUS: want a discovery-list-display of all known assets - scan assets folder~~
|
||||||
|
~~BONUS: Keep track of if structure or meshes have changed, when they changed offer to save if loading a new structure or closing program (meshes will stay loaded unchanged until close, loading a new structure erases current structure (temp?))~~
|
4
src/vvlib/s_identifier_validation.rs
Normal file
4
src/vvlib/s_identifier_validation.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub fn is_valid<S: Into<String>>(text: S) -> bool {
|
||||||
|
let text: String = text.into();
|
||||||
|
!(text.contains("|") & text.contains(char::is_whitespace) & text.contains(","))
|
||||||
|
}
|
Loading…
Reference in a new issue