Cleaning up some assets and parsing logic

attempt/001
Elijah Voigt 1 year ago
parent 804021debf
commit 957ec64ee0

@ -1,6 +1,5 @@
uuid 739619d7-b8a1-42b4-8803-2b8cfedeebf1
name "Editor Camera" name "Editor Camera"
editor_tag editorTag
camera render_target window b90f31a2-34d9-42c2-9e53-646d9c9c6c70 camera target window "window.entity"
fly_camera flyCamera
transform transform 10.0 10.0 10.0 transform translation 10.0 10.0 10.0 rotation 0.0 0.0 0.0 1.0 scale 1.0 1.0 1.0

@ -1,4 +1,3 @@
uuid 08e1a4d9-6c76-471d-af02-1aa7db1b435a editorTag
editor_tag uiNode
ui_node targetCamera "camera.entity"
target_camera 739619d7-b8a1-42b4-8803-2b8cfedeebf1

@ -1,4 +1,3 @@
uuid 0088bc7d-851e-402b-9d20-fadfe5cab106 editorTag
editor_tag uiText "Welcome to the editor" color #ffffff size 12.0
ui_text text "Welcome to the editor" color 1.0 1.0 1.0 1.0 parent "ui_container.entity"
parent 08e1a4d9-6c76-471d-af02-1aa7db1b435a

@ -1,4 +1,3 @@
uuid b90f31a2-34d9-42c2-9e53-646d9c9c6c70 editorTag
editor_tag
name "Editor Window" name "Editor Window"
window title "Editor" visible false window "Editor" visible false

@ -1,4 +1,3 @@
name camera name camera
uuid 2e45b7e9-6722-4d50-8ea5-67f25b8b0f62
transform translation 2.0 2.0 0.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 camera

@ -1,4 +1,3 @@
name van name van
uuid 5c270e84-814c-4d51-9ccd-ab79d9e01f1d
transform translation 0.0 0.0 0.0 rotation 0.0 0.0 0.0 1.0 scale 1.0 1.0 1.0 transform translation 0.0 0.0 0.0 rotation 0.0 0.0 0.0 1.0 scale 1.0 1.0 1.0
model "models/van.glb" "Scene" model "models/van.glb" "Scene"

@ -53,8 +53,9 @@ impl std::convert::From<&EditorState> for bool {
} }
/// Tag component for editor entities /// Tag component for editor entities
#[derive(Component)] #[derive(Component, Reflect, Debug, Default)]
struct EditorTag; #[reflect(Component, Default)]
pub(crate) struct EditorTag;
fn toggle_editor_state( fn toggle_editor_state(
curr_state: Res<State<EditorState>>, curr_state: Res<State<EditorState>>,
@ -73,15 +74,11 @@ fn toggle_editor_state(
} }
} }
fn spawn_editor( fn spawn_editor(mut _commands: Commands) {
mut _commands: Commands,
) {
todo!("Spawn editor"); todo!("Spawn editor");
} }
fn despawn_editor( fn despawn_editor(mut _comands: Commands) {
mut _comands: Commands,
) {
todo!("Despawn editor"); todo!("Despawn editor");
} }
@ -123,4 +120,4 @@ fn plane_gizmos(mut gizmos: Gizmos) {
gizmos.arrow(Vec3::ZERO, Vec3::Y, DARK_GREEN); gizmos.arrow(Vec3::ZERO, Vec3::Y, DARK_GREEN);
gizmos.arrow(Vec3::ZERO, Vec3::Z, BLUE); gizmos.arrow(Vec3::ZERO, Vec3::Z, BLUE);
} }
} }

@ -32,4 +32,4 @@ fn main() {
.add_plugins(save::SavePlugin) .add_plugins(save::SavePlugin)
.add_plugins(window::WindowPlugin) .add_plugins(window::WindowPlugin)
.run(); .run();
} }

@ -2,8 +2,6 @@ use crate::prelude::*;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub(crate) enum SaveEntityParseError { pub(crate) enum SaveEntityParseError {
#[error("Failed to parse Uuid: {0}")]
Uuid(#[from] uuid::Error),
#[error("Failed to parse name")] #[error("Failed to parse name")]
Name, Name,
#[error("Failed to parse Transform")] #[error("Failed to parse Transform")]
@ -134,42 +132,21 @@ fn test_parse_name() {
} }
} }
#[derive(Component, Clone, Debug, Reflect, PartialEq)] #[derive(Debug, Default, Reflect, PartialEq)]
#[reflect(Component)]
pub(crate) struct EntityUuid {
id: String,
}
///
/// Returns a reflected `EntityUuid`
///
pub(crate) fn parse_save_uuid(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (remainder, _) = tag("uuid")(line)?;
let id = remainder.trim().into();
Ok(EntityUuid { id }.clone_value())
}
#[test]
fn test_parse_uuid() {
let line = "uuid 1c16ab9a-5f79-4340-8469-4086f69c64f2";
let parsed = parse_save_uuid(line).unwrap();
let expected = EntityUuid {
id: "1c16ab9a-5f79-4340-8469-4086f69c64f2".into(),
};
assert!(expected
.clone_value()
.reflect_partial_eq(parsed.as_reflect())
.unwrap());
}
#[derive(Component, Debug, Default, Reflect, PartialEq)]
#[reflect(Component, PartialEq)] #[reflect(Component, PartialEq)]
pub(crate) struct SaveModel { pub(crate) struct SaveModel {
gltf_file: PathBuf, gltf_file: PathBuf,
scene_name: String, scene_name: String,
} }
impl Component for SaveModel {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut ComponentHooks) {
todo!("Assign Scene Handle for SaveModel")
}
}
/// ///
/// Returns a reflected `SaveModel` /// Returns a reflected `SaveModel`
/// ///
@ -201,12 +178,20 @@ fn test_parse_model() {
.unwrap()); .unwrap());
} }
#[derive(Component, Debug, Default, PartialEq, Reflect, Clone)] #[derive(Debug, Default, PartialEq, Reflect, Clone)]
#[reflect_value(Component, Default, PartialEq)] #[reflect_value(Component, Default, PartialEq)]
pub(crate) enum SaveCameraRenderTarget { pub(crate) enum SaveCameraRenderTarget {
#[default] #[default]
Default, Default,
Window(Uuid), Window(PathBuf),
}
impl Component for SaveCameraRenderTarget {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut ComponentHooks) {
todo!("Assign Render Target")
}
} }
/// ///
@ -217,11 +202,12 @@ pub(crate) fn parse_save_camera(line: &str) -> Result<Box<dyn Reflect>, SaveEnti
if let Ok((rem, (_, _target))) = tuple((space1::<&str, ()>, tag("target")))(rem) { if let Ok((rem, (_, _target))) = tuple((space1::<&str, ()>, tag("target")))(rem) {
if let Ok((rem, (_, _window))) = tuple((space1::<&str, ()>, tag("window")))(rem) { if let Ok((rem, (_, _window))) = tuple((space1::<&str, ()>, tag("window")))(rem) {
// Camera + target + window + UUID // Camera + target + window + UUID
if let Ok((rem, (_, uuid))) = tuple((space1::<&str, ()>, take(36usize)))(rem) { if let Ok((rem, (_, path))) =
tuple((space1::<&str, nom::error::Error<&str>>, parse_string))(rem)
{
debug_assert!(rem == ""); debug_assert!(rem == "");
let parsed_uuid = Uuid::parse_str(uuid)?; Ok(SaveCameraRenderTarget::Window(path.into()).clone_value())
Ok(SaveCameraRenderTarget::Window(parsed_uuid).clone_value())
// Camera + target + widow // Camera + target + widow
} else { } else {
debug_assert!(rem == ""); debug_assert!(rem == "");
@ -272,10 +258,9 @@ fn test_parse_camera() {
assert!(parsed.is_err()); assert!(parsed.is_err());
} }
{ {
let line = "camera target window 9a1367e0-71e5-4c79-b4ad-02aa44b68af0"; let line = "camera target window \"some.entity\"";
let target_uuid = Uuid::parse_str("9a1367e0-71e5-4c79-b4ad-02aa44b68af0").unwrap();
let parsed = parse_save_camera(line).unwrap(); let parsed = parse_save_camera(line).unwrap();
let expected = SaveCameraRenderTarget::Window(target_uuid); let expected = SaveCameraRenderTarget::Window("some.entity".into());
assert!(expected assert!(expected
.clone_value() .clone_value()
.reflect_partial_eq(parsed.as_reflect()) .reflect_partial_eq(parsed.as_reflect())
@ -290,10 +275,18 @@ fn test_parse_camera() {
/// SaveParent entity which is a reference to which entity this is a child of /// SaveParent entity which is a reference to which entity this is a child of
/// A run-time system converts this to a bevy Parent component /// A run-time system converts this to a bevy Parent component
#[derive(Component, PartialEq, Debug, Reflect, Clone)] #[derive(PartialEq, Debug, Reflect, Clone)]
#[reflect_value(Component, PartialEq)] #[reflect_value(Component, PartialEq)]
pub(crate) struct SaveParent(String); pub(crate) struct SaveParent(String);
impl Component for SaveParent {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut ComponentHooks) {
todo!("Assign parent for entity")
}
}
/// ///
/// Parses a parent entity with this format: /// Parses a parent entity with this format:
/// ```text /// ```text
@ -360,13 +353,13 @@ fn test_parse_window() {
/// ///
/// The UI Text bundle specified as a sparse subset of a bundle /// The UI Text bundle specified as a sparse subset of a bundle
/// ```text /// ```text
/// text "This is the text" color #abc123 size 12.34 /// uiText "This is the text" color #abc123 size 12.34
/// ``` /// ```
/// ///
/// Returns a reflected `Text` /// Returns a reflected `Text`
/// ///
pub(crate) fn parse_save_ui_text(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_ui_text(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (rem, (_tag_text, _space1, text)) = tuple((tag("text"), space1, parse_string))(line)?; let (rem, (_tag_text, _space1, text)) = tuple((tag("uiText"), space1, parse_string))(line)?;
let (rem, (_space, _tag_color, _space1, _hash, hex_color)) = let (rem, (_space, _tag_color, _space1, _hash, hex_color)) =
tuple((space1, tag("color"), space1, char('#'), hex_digit1))(rem)?; tuple((space1, tag("color"), space1, char('#'), hex_digit1))(rem)?;
@ -386,7 +379,7 @@ pub(crate) fn parse_save_ui_text(line: &str) -> Result<Box<dyn Reflect>, SaveEnt
#[test] #[test]
fn test_save_ui_text() { fn test_save_ui_text() {
let line = "text \"This is the text\" color #caffee size 14.6"; let line = "uiText \"This is the text\" color #caffee size 14.6";
let parsed = parse_save_ui_text(line).unwrap(); let parsed = parse_save_ui_text(line).unwrap();
let expected = Text::from_section( let expected = Text::from_section(
"This is the text", "This is the text",
@ -408,8 +401,10 @@ fn test_save_ui_text() {
/// ///
pub(crate) fn parse_save_tag<T: Component + Reflect + Default>( pub(crate) fn parse_save_tag<T: Component + Reflect + Default>(
t: &str, t: &str,
) -> impl FnOnce(&str) -> Result<T, SaveEntityParseError> + '_ { ) -> impl FnOnce(&str) -> Result<Box<dyn Reflect>, SaveEntityParseError> + '_ {
move |line: &str| -> Result<T, SaveEntityParseError> { Ok(tag(t)(line).map(|_| T::default())?) } move |line: &str| -> Result<Box<dyn Reflect>, SaveEntityParseError> {
Ok(tag(t)(line).map(|_| T::default().clone_value())?)
}
} }
#[derive(Component, Reflect, PartialEq, Debug, Default)] #[derive(Component, Reflect, PartialEq, Debug, Default)]
@ -427,13 +422,21 @@ fn test_save_tag() {
.unwrap()); .unwrap());
} }
#[derive(Component, Clone, Debug, Reflect, PartialEq)] #[derive(Clone, Debug, Reflect, PartialEq)]
#[reflect(Component)] #[reflect(Component)]
pub(crate) struct SaveTargetCamera(String); pub(crate) struct SaveTargetCamera(String);
impl Component for SaveTargetCamera {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut ComponentHooks) {
todo!("Assign target camera")
}
}
/// Parses the a SaveTargetCamera which at runtime is converted to a TargetCamera /// Parses the a SaveTargetCamera which at runtime is converted to a TargetCamera
/// ```text /// ```text
/// target-camera "./level-camera.entity" /// targetCamera "./level-camera.entity"
/// ``` /// ```
/// ///
/// Returns reflected `SaveTargetCamera` /// Returns reflected `SaveTargetCamera`
@ -441,7 +444,7 @@ pub(crate) fn parse_save_target_camera(
line: &str, line: &str,
) -> Result<Box<dyn Reflect>, SaveEntityParseError> { ) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
Ok( Ok(
tuple((tag("target-camera"), space1, parse_string))(line).map( tuple((tag("targetCamera"), space1, parse_string))(line).map(
|(_, (_, _, target_camera_entity_file))| { |(_, (_, _, target_camera_entity_file))| {
SaveTargetCamera(target_camera_entity_file.into()).clone_value() SaveTargetCamera(target_camera_entity_file.into()).clone_value()
}, },
@ -451,7 +454,7 @@ pub(crate) fn parse_save_target_camera(
#[test] #[test]
fn test_target_camera() { fn test_target_camera() {
let line = "target-camera \"./level-camera.entity\""; let line = "targetCamera \"./level-camera.entity\"";
let parsed = parse_save_target_camera(line).unwrap(); let parsed = parse_save_target_camera(line).unwrap();
let expected = SaveTargetCamera("./level-camera.entity".into()); let expected = SaveTargetCamera("./level-camera.entity".into());

@ -9,7 +9,6 @@ pub(crate) use bevy::{
render::camera::RenderTarget, render::camera::RenderTarget,
window::{PrimaryWindow, WindowCloseRequested, WindowRef}, window::{PrimaryWindow, WindowCloseRequested, WindowRef},
}; };
pub(crate) use nom::bytes::complete::take;
pub(crate) use nom::character::complete::hex_digit1; pub(crate) use nom::character::complete::hex_digit1;
pub(crate) use nom::{ pub(crate) use nom::{
branch::alt, branch::alt,
@ -21,6 +20,7 @@ pub(crate) use nom::{
}; };
pub(crate) use std::path::PathBuf; pub(crate) use std::path::PathBuf;
pub(crate) use thiserror::Error; pub(crate) use thiserror::Error;
pub(crate) use uuid::Uuid;
pub(crate) use crate::{conditions::*, parser::*}; pub(crate) use crate::{conditions::*, parser::*};
pub(crate) use bevy::ecs::component::{ComponentHooks, StorageType};

@ -5,9 +5,9 @@ pub(crate) struct SavePlugin;
impl Plugin for SavePlugin { impl Plugin for SavePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.register_type::<EntityUuid>() app.register_type::<SaveCameraRenderTarget>()
.register_type::<SaveCameraRenderTarget>()
.register_type::<GltfScene>() .register_type::<GltfScene>()
.register_type::<SaveModel>()
.init_asset::<SaveEntity>() .init_asset::<SaveEntity>()
.init_asset_loader::<SaveEntityLoader>() .init_asset_loader::<SaveEntityLoader>()
.init_asset_loader::<SaveSceneLoader>() .init_asset_loader::<SaveSceneLoader>()
@ -32,36 +32,44 @@ pub(crate) struct SaveEntity {
impl SaveEntity { impl SaveEntity {
fn parse( fn parse(
text: &str, text: &str,
_load_context: &mut LoadContext, load_context: &mut LoadContext,
) -> Result<SaveEntity, SaveEntityParseError> { ) -> Result<SaveEntity, SaveEntityParseError> {
let lines = text.split('\n'); let lines = text.split('\n');
let mut entity = SaveEntity { ..default() }; let mut entity = SaveEntity { ..default() };
let fns = [ let fns = [
parse_save_name, parse_save_name,
parse_save_transform, parse_save_transform,
parse_save_uuid,
parse_save_model, parse_save_model,
parse_save_camera, parse_save_camera,
parse_save_parent, parse_save_parent,
parse_save_window, parse_save_window,
parse_save_target_camera, parse_save_target_camera,
parse_save_ui_text,
// parse_save_tag::<EditorTag>("editor_tag"),
]; ];
lines.into_iter().for_each(|line| { lines
// track if this line matched any components .into_iter()
let mut good = false; .filter(|line| !line.is_empty())
.for_each(|line| {
// Run line against all parsers // track if this line matched any components
for f in fns { let mut good = false;
if let Ok(v) = f(line) {
entity.components.push(v); // Run line against all parsers
good = true; for f in fns {
if let Ok(v) = f(line) {
entity.components.push(v);
good = true;
}
} }
}
if !good { if !good {
error!("failed to parse component from line {:?}", line); error!(
} file = load_context.path().to_str().unwrap(),
}); line = line,
"failed to parse component",
);
}
});
Ok(entity) Ok(entity)
} }
} }

Loading…
Cancel
Save