working load-from-file. fixed struct-asset issue with childless root nodes. selection swapper functional (for structures, grids not working(??))

REMAINING FOR MVP: edit-node-data (REQUIRED), gizmos (arguable)
This commit is contained in:
Lillian Vixe 2024-06-17 13:00:35 -07:00
parent 41b673753e
commit 6c289f30f9
6 changed files with 109 additions and 68 deletions

View file

@ -1,5 +1,5 @@
version 1
test
head|none
||
element|torso
position|0|0|0

View file

@ -1,7 +1,7 @@
use bevy::{
app::{Startup, Update}, asset::{AssetServer, Assets, Handle}, ecs::{
entity::Entity, event::EventWriter, query::With, system::{Commands, Query, Res, ResMut, Resource}
}, hierarchy::BuildChildren, math::Vec3, pbr::{PointLight, PointLightBundle}, prelude::{default, SpatialBundle}, render::{camera::Camera, color::Color, view::Visibility}, transform::{components::{GlobalTransform, Transform}, TransformBundle}, utils::{hashbrown::hash_map::Entry, HashMap}, window::{PrimaryWindow, Window, WindowResolution}
entity::Entity, event::EventWriter, query::With, system::{Commands, Query, Res, ResMut}
}, math::Vec3, pbr::{PointLight, PointLightBundle}, prelude::{default, Resource, SpatialBundle}, render::{camera::Camera, color::Color, view::Visibility}, transform::components::{GlobalTransform, Transform}, utils::{hashbrown::hash_map::Entry, HashMap}, window::{PrimaryWindow, Window, WindowResolution}
};
use bevy_egui::{
egui::{self, color_picker, epaint::Hsva, Id, Pos2, Rect, ScrollArea},
@ -12,7 +12,7 @@ use crate::{
vvedit::s_editor_bevy_input_shim::keybind_codes::REMOVE_VOXEL,
vvlib::{
s_inputs::InputRegister, s_intersections::octtree_ray_overlap, s_obb::OBB,
s_oct_asset::OctAssetMarker, s_structure_asset::{StructureAsset, StructureComponent, StructureUpdateMessage, StructureUpdateType},
s_oct_asset::OctAssetMarker, s_structure_asset::{StructureAsset, StructureUpdateMessage, StructureUpdateType},
},
};
use crate::{
@ -29,11 +29,15 @@ use super::{
use std::fmt::Write;
#[derive(Clone)]
pub struct GridEditData {
pub path: String,
pub id: Handle<OctTreeAsset>,
pub edit_entity: Entity, //which instance of this structure is representing the one we can edit in the structure editor. other instances will exist which will be tricky (seperate store?)
pub has_changed_since_last_save: bool,
}
#[derive(Clone)]
pub struct StructureEditData {
pub path: String,
pub id: Handle<StructureAsset>,
@ -48,16 +52,13 @@ pub struct EditWindowUIState {
pub structures: Vec<StructureEditData>,
pub egui: EditWindowEguiState,
pub popup: PopupWindowMode,
//pub selected_structure_element: String,
//pub selected_structure: String,
//pub selected_grid: String,
pub display_state: DisplayState,
pub display_root: Entity,
pub selection: Selection,
pub struct_element_selections: HashMap<String, String>,
}
#[derive(Default, Clone, PartialEq)]
#[derive(Default, Clone, PartialEq, Debug)]
pub enum Selection {
#[default]
None,
@ -212,6 +213,7 @@ impl EditWindowUIState {
self.grids.push(GridEditData {
path: path.clone(),
id,
edit_entity: Entity::PLACEHOLDER, // BAD BAD BAD TODO: Finish this
has_changed_since_last_save: has_changed,
});
return true;
@ -242,14 +244,8 @@ pub fn register_edit_ui(
pub fn startup_system_edit_ui(
mut commands: Commands,
mut shared_ui_state: ResMut<EditWindowUIState>,
asset_server: ResMut<AssetServer>,
mut event_writer: EventWriter<StructureUpdateMessage>,
) {
spawn_camera(&mut commands);
/*
let str = "test.vvs";
let handle = asset_server.load::<StructureAsset>(str);
*/
let display_parent = commands
.spawn(SpatialBundle {
visibility: Visibility::Visible,
@ -258,27 +254,6 @@ pub fn startup_system_edit_ui(
})
.id();
shared_ui_state.display_root = display_parent;
/*
let id = commands.spawn((SpatialBundle {
visibility: Visibility::Visible,
..Default::default()
}, StructureComponent {
asset: handle.clone(),
nodes: Default::default(),
})).id();
let data = StructureEditData {
path: str.into(),
id: handle.clone(),
has_changed_since_last_save: false,
edit_entity: id.clone(),
};
shared_ui_state.structures.push(data);
commands.entity(display_parent).add_child(id.clone());
event_writer.send(StructureUpdateMessage {
update_type: StructureUpdateType::Rebuild,
entity: id,
});
*/
let light_transform = Transform::from_xyz(4f32, 4f32, 4f32).looking_at(Vec3::ZERO, Vec3::Y);
commands.spawn(PointLightBundle {
@ -449,6 +424,7 @@ pub fn edit_window_ui(
mut pairs: ResMut<MeshingOctTreePairs>,
windows: Query<Entity, With<Window>>,
window: Query<&Window>,
mut visibility: Query<&mut Visibility>,
mut asset_server: ResMut<AssetServer>,
mut event_writer: EventWriter<StructureUpdateMessage>,
mut commands: Commands,
@ -606,11 +582,6 @@ pub fn edit_window_ui(
}
let mut selection: Selection = shared_ui_state.selection.clone();
ui.collapsing("grid assets", |ui| {
if !shared_ui_state.selection.is_none() {
if ui.button("Deselect Asset").clicked() {
shared_ui_state.selection = Selection::None;
}
}
for grid in &shared_ui_state.grids {
ui.radio_value(
&mut selection,
@ -620,21 +591,17 @@ pub fn edit_window_ui(
}
});
ui.collapsing("structure assets", |ui| {
if !shared_ui_state.selection.is_none() {
if ui.button("Deselect Asset").clicked() {
shared_ui_state.selection = Selection::None;
}
}
for structure in &shared_ui_state.structures {
ui.radio_value(
&mut selection,
Selection::Grid(structure.path.to_string()),
Selection::Structure(structure.path.to_string()),
structure.path.to_string().as_str(),
);
}
});
if selection != shared_ui_state.selection {
shared_ui_state.selection = selection;
update_selection(&mut shared_ui_state, &mut visibility);
}
let mut selected_structure = false;
let mut selection = Option::<StringTree>::None;

View file

@ -9,7 +9,7 @@ use bevy::{
ecs::{entity::Entity, event::EventWriter, system::ResMut},
hierarchy::BuildChildren,
math::{Quat, Vec3},
prelude::{Commands, SpatialBundle},
prelude::{Commands, Query, SpatialBundle},
render::{color::Color, view::Visibility},
utils::hashbrown::hash_map::Entry,
};
@ -27,7 +27,7 @@ use crate::{
vvedit::s_editor_ui::{GridEditData, Selection, StructureEditData},
vvlib::{
s_identifier_validation::{self, is_valid},
s_oct_asset::OctTreeAsset,
s_oct_asset::{OctAssetMarker, OctTreeAsset},
s_octtree::OctTree,
s_structure_asset::{
StructureAsset, StructureComponent, StructureUpdateMessage, StructureUpdateType,
@ -338,9 +338,9 @@ pub fn show_popup(
edit_entity: id.clone(),
};
state.structures.push(data);
commands.entity(state.display_root).add_child(id);
commands.entity(state.display_root).add_child(id.clone());
event_writer.send(StructureUpdateMessage {
update_type: StructureUpdateType::Rebuild,
update_type: StructureUpdateType::Build,
entity: id,
});
}
@ -348,9 +348,22 @@ pub fn show_popup(
}
Extension::Grid => {
let handle = asset_server.load::<OctTreeAsset>(path_pre.clone());
let id = commands
.spawn((
SpatialBundle {
visibility: Visibility::Visible,
..Default::default()
},
OctAssetMarker {
oct_handle: handle.clone(),
},
))
.id();
commands.entity(state.display_root).add_child(id.clone());
let data = GridEditData {
path: path_pre,
id: handle,
edit_entity: id.clone(),
has_changed_since_last_save: false,
};
let mut loaded_already = false;
@ -451,13 +464,12 @@ pub fn show_popup(
// add structure
let handle = asset_server.add::<StructureAsset>(Default::default());
let handleclone = handle.clone();
let data = StructureEditData {
let mut data = StructureEditData {
path: final_path,
id: handle,
has_changed_since_last_save: false,
edit_entity: Entity::PLACEHOLDER, //BAD BAD BAD
};
state.structures.push(data);
state_change = PopupStateChange::Close;
let id = commands
@ -472,11 +484,13 @@ pub fn show_popup(
},
))
.id();
commands.entity(state.display_root).add_child(id);
commands.entity(state.display_root).add_child(id.clone());
event_writer.send(StructureUpdateMessage {
update_type: StructureUpdateType::Rebuild,
entity: id,
update_type: StructureUpdateType::Build,
entity: id.clone(),
});
data.edit_entity = id;
state.structures.push(data);
} else {
// add grid
let handle = asset_server.add::<OctTreeAsset>(OctTreeAsset {
@ -487,14 +501,26 @@ pub fn show_popup(
handle: None,
task: None,
});
let id = commands
.spawn((
SpatialBundle {
visibility: Visibility::Visible,
..Default::default()
},
OctAssetMarker {
oct_handle: handle.clone(),
},
))
.id();
commands.entity(state.display_root).add_child(id.clone());
let data = GridEditData {
path: final_path,
id: handle,
edit_entity: id,
has_changed_since_last_save: true,
};
state.grids.push(data);
state_change = PopupStateChange::Close;
// SPAWN ENTITY?
}
}
});
@ -737,4 +763,54 @@ pub fn editable_quat(ui: &mut egui::Ui, value: &mut Quat, should_reshape: &mut b
}
}
//pub fn set_visibility
pub fn update_selection(
shared_ui_state: &mut ResMut<EditWindowUIState>,
visibility: &mut Query<&mut Visibility>,
) {
let mut set_visible = Option::<Entity>::None;
if let Selection::Grid(some) = &shared_ui_state.selection {
for grid in &shared_ui_state.grids {
if &grid.path == some {
set_visible = Some(grid.edit_entity);
break;
}
}
} else if let Selection::Structure(some) = &shared_ui_state.selection {
for structure in &shared_ui_state.structures {
if &structure.path == some {
set_visible = Some(structure.edit_entity);
break;
}
}
}
for each_grid in &shared_ui_state.grids.clone() {
let ent = each_grid.edit_entity;
let each = visibility.get_mut(ent);
if let Ok(mut each) = each {
if let Some(set_visible) = set_visible.clone() {
if ent == set_visible {
*each = Visibility::Visible;
} else {
*each = Visibility::Hidden;
}
} else {
*each = Visibility::Hidden;
}
}
}
for each_structure in &shared_ui_state.structures.clone() {
let ent = each_structure.edit_entity;
let each = visibility.get_mut(ent);
if let Ok(mut each) = each {
if let Some(set_visible) = set_visible.clone() {
if ent == set_visible {
*each = Visibility::Visible;
} else {
*each = Visibility::Hidden;
}
} else {
*each = Visibility::Hidden;
}
}
}
}

View file

@ -1,9 +0,0 @@
what its like to load a file
default structure is empty
no meshes loaded
load a structure: display 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
DONE:
want a discovery-list-display of all known assets - scan assets folder
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?))

View file

@ -1,4 +1,7 @@
pub fn is_valid<S: Into<String>>(text: S) -> bool {
let text: String = text.into();
!(text.contains("|") & text.contains(char::is_whitespace) & text.contains(","))
!(text.contains("|")
& text.contains(char::is_whitespace)
& text.contains(",")
& (text.to_lowercase() != "none"))
}

View file

@ -430,7 +430,9 @@ pub mod serialization {
}
while let Some(each) = tokens.next() {
let each = each.trim().to_string();
result.layout.add_child(&each, &parent);
if each.to_lowercase() != "none" {
result.layout.add_child(&each, &parent);
}
}
}
}
@ -685,6 +687,8 @@ pub mod serialization {
if children.is_empty() {
*data += NEWLINE;
*data += element.as_str();
*data += "|";
*data += "none";
return;
}
*data += NEWLINE;