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"
editor_tag
camera render_target window b90f31a2-34d9-42c2-9e53-646d9c9c6c70
fly_camera
transform transform 10.0 10.0 10.0
editorTag
camera target window "window.entity"
flyCamera
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
editor_tag
ui_node
target_camera 739619d7-b8a1-42b4-8803-2b8cfedeebf1
editorTag
uiNode
targetCamera "camera.entity"

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

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

@ -1,4 +1,3 @@
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
camera
camera

@ -1,4 +1,3 @@
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
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
#[derive(Component)]
struct EditorTag;
#[derive(Component, Reflect, Debug, Default)]
#[reflect(Component, Default)]
pub(crate) struct EditorTag;
fn toggle_editor_state(
curr_state: Res<State<EditorState>>,
@ -73,15 +74,11 @@ fn toggle_editor_state(
}
}
fn spawn_editor(
mut _commands: Commands,
) {
fn spawn_editor(mut _commands: Commands) {
todo!("Spawn editor");
}
fn despawn_editor(
mut _comands: Commands,
) {
fn despawn_editor(mut _comands: Commands) {
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::Z, BLUE);
}
}
}

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

@ -2,8 +2,6 @@ use crate::prelude::*;
#[derive(Error, Debug)]
pub(crate) enum SaveEntityParseError {
#[error("Failed to parse Uuid: {0}")]
Uuid(#[from] uuid::Error),
#[error("Failed to parse name")]
Name,
#[error("Failed to parse Transform")]
@ -134,42 +132,21 @@ fn test_parse_name() {
}
}
#[derive(Component, Clone, Debug, 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)]
#[derive(Debug, Default, Reflect, PartialEq)]
#[reflect(Component, PartialEq)]
pub(crate) struct SaveModel {
gltf_file: PathBuf,
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`
///
@ -201,12 +178,20 @@ fn test_parse_model() {
.unwrap());
}
#[derive(Component, Debug, Default, PartialEq, Reflect, Clone)]
#[derive(Debug, Default, PartialEq, Reflect, Clone)]
#[reflect_value(Component, Default, PartialEq)]
pub(crate) enum SaveCameraRenderTarget {
#[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, (_, _window))) = tuple((space1::<&str, ()>, tag("window")))(rem) {
// 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 == "");
let parsed_uuid = Uuid::parse_str(uuid)?;
Ok(SaveCameraRenderTarget::Window(parsed_uuid).clone_value())
Ok(SaveCameraRenderTarget::Window(path.into()).clone_value())
// Camera + target + widow
} else {
debug_assert!(rem == "");
@ -272,10 +258,9 @@ fn test_parse_camera() {
assert!(parsed.is_err());
}
{
let line = "camera target window 9a1367e0-71e5-4c79-b4ad-02aa44b68af0";
let target_uuid = Uuid::parse_str("9a1367e0-71e5-4c79-b4ad-02aa44b68af0").unwrap();
let line = "camera target window \"some.entity\"";
let parsed = parse_save_camera(line).unwrap();
let expected = SaveCameraRenderTarget::Window(target_uuid);
let expected = SaveCameraRenderTarget::Window("some.entity".into());
assert!(expected
.clone_value()
.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
/// 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)]
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:
/// ```text
@ -360,13 +353,13 @@ fn test_parse_window() {
///
/// The UI Text bundle specified as a sparse subset of a bundle
/// ```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`
///
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)) =
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]
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 expected = Text::from_section(
"This is the text",
@ -408,8 +401,10 @@ fn test_save_ui_text() {
///
pub(crate) fn parse_save_tag<T: Component + Reflect + Default>(
t: &str,
) -> impl FnOnce(&str) -> Result<T, SaveEntityParseError> + '_ {
move |line: &str| -> Result<T, SaveEntityParseError> { Ok(tag(t)(line).map(|_| T::default())?) }
) -> impl FnOnce(&str) -> Result<Box<dyn Reflect>, SaveEntityParseError> + '_ {
move |line: &str| -> Result<Box<dyn Reflect>, SaveEntityParseError> {
Ok(tag(t)(line).map(|_| T::default().clone_value())?)
}
}
#[derive(Component, Reflect, PartialEq, Debug, Default)]
@ -427,13 +422,21 @@ fn test_save_tag() {
.unwrap());
}
#[derive(Component, Clone, Debug, Reflect, PartialEq)]
#[derive(Clone, Debug, Reflect, PartialEq)]
#[reflect(Component)]
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
/// ```text
/// target-camera "./level-camera.entity"
/// targetCamera "./level-camera.entity"
/// ```
///
/// Returns reflected `SaveTargetCamera`
@ -441,7 +444,7 @@ pub(crate) fn parse_save_target_camera(
line: &str,
) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
Ok(
tuple((tag("target-camera"), space1, parse_string))(line).map(
tuple((tag("targetCamera"), space1, parse_string))(line).map(
|(_, (_, _, target_camera_entity_file))| {
SaveTargetCamera(target_camera_entity_file.into()).clone_value()
},
@ -451,7 +454,7 @@ pub(crate) fn parse_save_target_camera(
#[test]
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 expected = SaveTargetCamera("./level-camera.entity".into());

@ -9,7 +9,6 @@ pub(crate) use bevy::{
render::camera::RenderTarget,
window::{PrimaryWindow, WindowCloseRequested, WindowRef},
};
pub(crate) use nom::bytes::complete::take;
pub(crate) use nom::character::complete::hex_digit1;
pub(crate) use nom::{
branch::alt,
@ -21,6 +20,7 @@ pub(crate) use nom::{
};
pub(crate) use std::path::PathBuf;
pub(crate) use thiserror::Error;
pub(crate) use uuid::Uuid;
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 {
fn build(&self, app: &mut App) {
app.register_type::<EntityUuid>()
.register_type::<SaveCameraRenderTarget>()
app.register_type::<SaveCameraRenderTarget>()
.register_type::<GltfScene>()
.register_type::<SaveModel>()
.init_asset::<SaveEntity>()
.init_asset_loader::<SaveEntityLoader>()
.init_asset_loader::<SaveSceneLoader>()
@ -32,36 +32,44 @@ pub(crate) struct SaveEntity {
impl SaveEntity {
fn parse(
text: &str,
_load_context: &mut LoadContext,
load_context: &mut LoadContext,
) -> Result<SaveEntity, SaveEntityParseError> {
let lines = text.split('\n');
let mut entity = SaveEntity { ..default() };
let fns = [
parse_save_name,
parse_save_transform,
parse_save_uuid,
parse_save_model,
parse_save_camera,
parse_save_parent,
parse_save_window,
parse_save_target_camera,
parse_save_ui_text,
// parse_save_tag::<EditorTag>("editor_tag"),
];
lines.into_iter().for_each(|line| {
// track if this line matched any components
let mut good = false;
// Run line against all parsers
for f in fns {
if let Ok(v) = f(line) {
entity.components.push(v);
good = true;
lines
.into_iter()
.filter(|line| !line.is_empty())
.for_each(|line| {
// track if this line matched any components
let mut good = false;
// Run line against all parsers
for f in fns {
if let Ok(v) = f(line) {
entity.components.push(v);
good = true;
}
}
}
if !good {
error!("failed to parse component from line {:?}", line);
}
});
if !good {
error!(
file = load_context.path().to_str().unwrap(),
line = line,
"failed to parse component",
);
}
});
Ok(entity)
}
}

Loading…
Cancel
Save