From 07bbbfa25b43b9d43e2862d6f9a81ffa0f7e9a81 Mon Sep 17 00:00:00 2001 From: "Elijah C. Voigt" Date: Tue, 9 Jul 2024 19:19:37 -0700 Subject: [PATCH] Successfully parsing camera component Now need to get the game to actually use the camera... --- assets/levels/00/entities/camera.entity | 2 +- src/editor.rs | 50 +++++++++++++++++++++++-- src/menu.rs | 2 +- src/prelude.rs | 6 ++- src/save.rs | 49 +++++++++++------------- 5 files changed, 75 insertions(+), 34 deletions(-) diff --git a/assets/levels/00/entities/camera.entity b/assets/levels/00/entities/camera.entity index cd17ac8..bc5622c 100644 --- a/assets/levels/00/entities/camera.entity +++ b/assets/levels/00/entities/camera.entity @@ -1,4 +1,4 @@ name camera uuid 2e45b7e9-6722-4d50-8ea5-67f25b8b0f62 -transform translation -5.0 5.0 5.0 rotation 0.0 0.0 0.0 1.0 scale 1.0 1.0 1.0 +transform translation 2.0 2.0 0.0 rotation 0.0 0.0 0.0 1.0 scale 1.0 1.0 1.0 camera \ No newline at end of file diff --git a/src/editor.rs b/src/editor.rs index 752f815..6e6472c 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -1,3 +1,5 @@ +use bevy::render::primitives::Aabb; + use crate::prelude::*; pub(crate) struct EditorPlugin; @@ -12,14 +14,16 @@ impl Plugin for EditorPlugin { ) .add_systems( Update, - toggle_editor_window.run_if(state_changed::), + ( + toggle_editor_window, + toggle_entity_aabb, + ).run_if(state_changed::), ) .add_systems( Update, ( handle_window_close.run_if(on_event::()), plane_gizmos, - // fly_camera, ) .run_if(in_state(EditorState::Open)), ); @@ -28,7 +32,7 @@ impl Plugin for EditorPlugin { /// Tracking the open/closed state of the editor #[derive(States, Debug, Clone, PartialEq, Eq, Hash, Default, Component)] -enum EditorState { +pub(crate) enum EditorState { /// The editor is closed => the editor window is disabled #[default] Closed, @@ -181,3 +185,43 @@ fn plane_gizmos(mut gizmos: Gizmos) { gizmos.arrow(Vec3::ZERO, Vec3::Z, Color::BLUE); } } + +fn toggle_entity_aabb( + state: Res>, + query: Query>>, + children: Query<&Children>, + aabbs: Query<(Entity, &Aabb)>, + mut commands: Commands, +) { + let add_component = match state.get() { + EditorState::Open => true, + EditorState::Closed => false, + }; + query.iter().for_each(|root| { + if add_component { + commands.entity(root).insert(ShowAabbGizmo { ..default() }); + } else { + commands.entity(root).remove::(); + } + + let mut child_has_bounding_box = false; + for child in children.iter_descendants(root) { + if add_component { + commands.entity(child).insert(ShowAabbGizmo { ..default() }); + } else { + commands.entity(child).remove::(); + } + if aabbs.contains(child) { + commands.entity(child).insert(Aabb { center: Vec3A::ZERO, half_extents: Vec3A::ONE }); + } else { + child_has_bounding_box = true; + } + } + + if !aabbs.contains(root) && !child_has_bounding_box { + commands.entity(root).insert(Aabb { center: Vec3A::ZERO, half_extents: Vec3A::ONE }); + } else { + commands.entity(root).remove::(); + } + }) +} \ No newline at end of file diff --git a/src/menu.rs b/src/menu.rs index 8c3b11d..6eaecbb 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -4,7 +4,7 @@ pub(crate) struct MenuPlugin; impl Plugin for MenuPlugin { fn build(&self, app: &mut App) { - app.add_systems(Startup, init_menu); + // app.add_systems(Startup, init_menu); } } diff --git a/src/prelude.rs b/src/prelude.rs index 649297d..03c1d1b 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,10 +10,14 @@ pub(crate) use bevy::window::PrimaryWindow; pub(crate) use bevy::window::WindowCloseRequested; pub(crate) use bevy::window::WindowRef; pub(crate) use nom::bytes::complete::tag; -pub(crate) use nom::bytes::complete::take; +pub(crate) use nom::character::complete::space1; pub(crate) use nom::bytes::complete::take_until1; pub(crate) use nom::number::complete::float; pub(crate) use nom::sequence::tuple; +pub(crate) use bevy::{gltf::Gltf, math::Vec3A}; +pub(crate) use nom::IResult; + pub(crate) use crate::camera::*; pub(crate) use crate::conditions::*; +pub(crate) use crate::save::*; diff --git a/src/save.rs b/src/save.rs index 167e7ff..707b1bd 100644 --- a/src/save.rs +++ b/src/save.rs @@ -1,6 +1,3 @@ -use bevy::{gltf::Gltf, math::Vec3A, render::primitives::Aabb}; -use nom::IResult; - use crate::prelude::*; /// Menu Plugin; empty struct for Plugin impl @@ -19,11 +16,13 @@ impl Plugin for SavePlugin { } #[derive(Asset, TypePath, Debug, Default)] -struct SaveEntity { +pub(crate) struct SaveEntity { transform: Option, name: Option, uuid: Option, model: Option<(Handle, String)>, + // TODO: Option feels like an antipattern as this is either Some(true) or None and never Some(false). + // Either encode more Camera data in this or replace it with Option<()> or just bool. camera: Option, } @@ -44,8 +43,8 @@ impl SaveEntity { } else if let Ok((gltf_path, scene_name)) = parse::parse_save_model(line) { let handle = load_context.load(gltf_path); entity.model = Some((handle, scene_name)); - } else if let Ok(is_camera) = parse::parse_save_camera(line) { - entity.camera = Some(is_camera); + } else if let Ok(true) = parse::parse_save_camera(line) { + entity.camera = Some(true); } }); Ok(entity) @@ -78,23 +77,25 @@ mod parse { } } - fn parse_thing<'a>(s: &'a str, l: &'a str) -> IResult<&'a str, &'a str> { - tag(l)(s) + fn parse_word<'a>(w: &'a str) -> impl Fn(&'a str) -> IResult<&'a str, &'a str> { + move |i: &'a str| { + tag(w)(i) + } } fn parse_xyz(i: &str) -> IResult<&str, (f32, f32, f32)> { - tuple((float, take(1usize), float, take(1usize), float))(i) + tuple((float, space1, float, space1, float))(i) .map(|(s, (x, _, y, _, z))| (s, (x, y, z))) } fn parse_wxyz(i: &str) -> IResult<&str, (f32, f32, f32, f32)> { tuple(( float, - take(1usize), + space1, float, - take(1usize), + space1, float, - take(1usize), + space1, float, ))(i) .map(|(s, (w, _, x, _, y, _, z))| (s, (w, x, y, z))) @@ -120,16 +121,14 @@ mod parse { let mut curr = rem.trim_start(); for _ in 0..3 { - if let Ok((input, _)) = parse_thing(curr, "translation") { - let (rem, (x, y, z)) = parse_xyz(input.trim_start())?; + println!("Curr: {:?}", curr); + if let Ok((rem, (_, _, (x, y, z)))) = tuple((parse_word("translation"), space1, parse_xyz))(curr.trim_start()) { transform.translation = Vec3::new(x, y, z); curr = rem.trim_start(); - } else if let Ok((input, _)) = parse_thing(curr.trim_start(), "rotation") { - let (rem, (x, y, z, w)) = parse_wxyz(input.trim_start())?; + } else if let Ok((rem, (_, _, (x, y, z, w)))) = tuple((parse_word("rotation"), space1, parse_wxyz))(curr.trim_start()) { transform.rotation = Quat::from_xyzw(x, y, z, w); curr = rem.trim_start(); - } else if let Ok((input, _)) = parse_thing(curr.trim_start(), "scale") { - let (rem, (x, y, z)) = parse_xyz(input.trim_start())?; + } else if let Ok((rem, (_, _, (x, y, z)))) = tuple((parse_word("scale"), space1, parse_xyz))(curr.trim_start()) { transform.scale = Vec3::new(x, y, z); curr = rem.trim_start(); } else { @@ -219,9 +218,9 @@ mod parse { pub(crate) fn parse_save_model(line: &str) -> Result<(String, String), SaveEntityParseError> { let (rem, (_, _, gltf_name, _, scene_name)) = tuple(( tag("model"), - take(1usize), + space1, parse_string, - take(1usize), + space1, parse_string, ))(line)?; @@ -254,9 +253,8 @@ mod parse { } { let line = "notcamera"; - let parsed = parse_save_camera(line).unwrap(); - let expected = false; - assert_eq!(parsed, expected); + let parsed = parse_save_camera(line); + assert!(parsed.is_err()); } } } @@ -302,11 +300,6 @@ fn test_save_entity(loader: Res, mut commands: Commands) { commands.spawn(( SpatialBundle { ..default() }, handle, - ShowAabbGizmo { ..default() }, - Aabb { - center: Vec3A::ZERO, - half_extents: Vec3A::ONE, - }, )); }