Saving my place

main
Elijah Voigt 2 years ago
parent 8aaa53742f
commit a40958f0bb

1
Cargo.lock generated

@ -2147,6 +2147,7 @@ name = "monologue-trees"
version = "0.1.0"
dependencies = [
"bevy",
"ron",
"serde",
]

@ -47,7 +47,8 @@ path = "bin/serialize-wtf.rs"
[dependencies]
bevy = "0.11"
# bevy_rapier3d = "*"
serde = "1"
serde = { version = "1", features = ["derive"] }
ron = "0.8"
# From rapier docs
[profile.dev.package.bevy_rapier3d]

@ -1,5 +1,41 @@
///
/// General levevel structure is this:
/// Level: Vec<Epoch>
/// Epoch: Id, Handle<DynamicScene>
///
/// You can index a Level by it's Epoch like
/// `/path/to/level.file#epoch-id`
///
/// !!!TODO!!!
/// * read .trees.level files, loading Levels
/// * Similar to GLTFs, this contains nested assets
/// * Handle<Level> -> Vec<Handle<Epochs>> => Handle<DynamicScene>
/// * Review how GLTF loading works for this, very similar goal.
///
/// Ex:
/// foo.trees.level:
/// [
/// Epoch {
/// id: 1,
/// scene: [
/// entities: [...]
/// resources: [...]
/// ],
/// },
/// Epoch {
/// id: 2,
/// scene: [...]
/// }, etc
/// ]
///
use crate::editor::prelude::*;
use bevy::tasks::IoTaskPool;
use bevy::{
asset::{AssetLoader, LoadContext, LoadedAsset},
reflect::{TypePath, TypeUuid},
scene::SceneLoader,
tasks::IoTaskPool,
utils::BoxedFuture,
};
#[derive(Debug, Default)]
pub struct EditorLevelPlugin;
@ -7,8 +43,10 @@ pub struct EditorLevelPlugin;
impl Plugin for EditorLevelPlugin {
fn build(&self, app: &mut App) {
app.register_type::<LevelRoot>()
.add_asset::<Level>()
.init_asset_loader::<LevelAssetLoader>()
.add_systems(Update, level_ui)
.add_systems(Update, load_level)
.add_systems(Update, set_level)
.add_systems(Update, export_level.run_if(ui::activated::<ExportLevel>))
.add_systems(Update, rehydrate_level::<Visibility, ComputedVisibility>)
.add_systems(
@ -24,7 +62,16 @@ impl Plugin for EditorLevelPlugin {
#[reflect(Component)]
pub struct LevelRoot;
pub type Level = DynamicScene;
#[derive(Debug, TypeUuid, TypePath, Default, Deserialize)]
#[uuid = "eb5c5f73-076e-4476-83f2-d97cf077ec90"]
struct Level {
epochs: Vec<Epoch>,
}
#[derive(Reflect)]
struct RawLevel {
epochs: Vec<Epoch>,
}
#[derive(Debug, Component, Default)]
pub struct LevelWidget;
@ -84,7 +131,7 @@ fn level_ui(
});
}
fn load_level(
fn set_level(
events: Query<
&ui::TargetAsset<DynamicScene>,
(Added<ui::Active>, With<ui::TargetAsset<DynamicScene>>),
@ -224,3 +271,40 @@ fn clear_level(
});
})
}
#[derive(Default)]
pub struct LevelAssetLoader;
impl AssetLoader for LevelAssetLoader {
fn load<'a>(
&'a self,
bytes: &'a [u8],
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), bevy::asset::Error>> {
Box::pin(async move { Ok(load_level(bytes, load_context).await?) })
}
fn extensions(&self) -> &[&str] {
&["trees.level"]
}
}
// ref: https://github.com/bevyengine/bevy/blob/12c6fa7e591545afe8c7101b0f021121eea7272f/crates/bevy_gltf/src/loader.rs#L92
pub async fn load_level<'a, 'b>(
bytes: &'a [u8],
load_context: &'a mut LoadContext<'b>,
) -> Handle<Level> {
let level: Level = ron::de::from_bytes(bytes).expect("Deserialize level");
info!("Level: {:?}", level);
let scene = SceneLoader::from_world(&mut World::new())
.load(bytes, load_context)
.await;
info!("Scene result: {:?}", scene);
let epochs: Vec<Epoch> = {
todo!("Load epochs");
let id = todo!("get epoch ID");
let scene = todo!("get dynamic scene");
vec![]
};
load_context.set_default_asset(LoadedAsset::new(Level { epochs }));
}

@ -6,3 +6,4 @@ pub use crate::{
ui,
};
pub use bevy::{gltf::Gltf, prelude::*};
pub use serde::{Deserialize, Serialize};

@ -1,3 +1,5 @@
use bevy::reflect::TypeUuid;
use crate::editor::prelude::*;
#[derive(Debug, Default)]
@ -10,44 +12,27 @@ impl Plugin for EditorTimelinePlugin {
}
}
#[derive(Debug, Component, Resource, Clone, Default, Reflect, TypeUuid, Deserialize)]
#[uuid = "959f5f02-7c80-4b3d-ad02-9dc2e5d1b963"]
pub struct Epoch {
id: usize,
// scene: Handle<DynamicScene>,
}
/// Timeline widget marker
#[derive(Debug, Component)]
pub struct TimelineWidget;
#[derive(Debug, Resource)]
struct ActiveEpoch {
id: EpochId,
entity: Entity,
}
/// Add Epoch component, used on a button to trigger a new epoch addition
#[derive(Debug, Component)]
pub struct AddEpoch;
/// Epoch ID Component
#[derive(Debug, Reflect, Component, Clone)]
struct EpochId {
id: usize,
}
#[derive(Component)]
struct EpochScene(DynamicScene);
fn control_active_epoch(
events: Query<(Entity, &EpochId), Added<ui::Active>>,
events: Query<(Entity, &Epoch), Added<ui::Active>>,
mut commands: Commands,
level_root: Query<Entity, With<LevelRoot>>,
audio_root: Query<Entity, With<AudioRoot>>,
children: Query<&Children>,
world: &World,
) {
events.iter().for_each(|(entity, &ref id)| {
let scene = export_level_state(&level_root, &audio_root, &children, world);
commands.entity(entity).insert(EpochScene(scene));
commands.insert_resource(ActiveEpoch {
id: id.clone(),
entity,
});
events.iter().for_each(|(entity, epoch)| {
commands.insert_resource(epoch.clone());
});
}
@ -78,7 +63,7 @@ fn add_timeline_epoch(
text: name,
..default()
},
EpochId { id },
Epoch { id, ..default() },
));
});
});

Loading…
Cancel
Save