|
|
|
|
@ -1,33 +1,67 @@
|
|
|
|
|
use std::{fs::File, io::Write};
|
|
|
|
|
|
|
|
|
|
use bevy::{audio::PlaybackMode, prelude::*, tasks::IoTaskPool};
|
|
|
|
|
// TODO:
|
|
|
|
|
// * Determine where local assets folder needs to be created
|
|
|
|
|
// * Create local assets folder
|
|
|
|
|
// * Recusrively laod that folder and watch for changes
|
|
|
|
|
// * Copy assets into local folder in leue of importing them
|
|
|
|
|
// * Check portability by moving binary + folder to new location
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
|
fs::{DirBuilder, File},
|
|
|
|
|
io::Write,
|
|
|
|
|
time::Duration,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use bevy::{
|
|
|
|
|
asset::{Asset, ChangeWatcher},
|
|
|
|
|
audio::PlaybackMode,
|
|
|
|
|
gltf::Gltf,
|
|
|
|
|
prelude::*,
|
|
|
|
|
tasks::IoTaskPool,
|
|
|
|
|
};
|
|
|
|
|
use monologue_trees::{debug::*, ui};
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
App::new()
|
|
|
|
|
.init_resource::<AssetRegistry>()
|
|
|
|
|
.add_plugins((
|
|
|
|
|
DefaultPlugins.set(WindowPlugin {
|
|
|
|
|
primary_window: Some(Window {
|
|
|
|
|
title: "Serialization WTF".into(),
|
|
|
|
|
resolution: (640., 480.).into(),
|
|
|
|
|
DefaultPlugins
|
|
|
|
|
.set(WindowPlugin {
|
|
|
|
|
primary_window: Some(Window {
|
|
|
|
|
title: "Serialization WTF".into(),
|
|
|
|
|
resolution: (640., 480.).into(),
|
|
|
|
|
..default()
|
|
|
|
|
}),
|
|
|
|
|
..default()
|
|
|
|
|
})
|
|
|
|
|
.set(AssetPlugin {
|
|
|
|
|
asset_folder: "assets".into(),
|
|
|
|
|
// Tell the asset server to watch for asset changes on disk:
|
|
|
|
|
watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(0)),
|
|
|
|
|
..default()
|
|
|
|
|
}),
|
|
|
|
|
..default()
|
|
|
|
|
}),
|
|
|
|
|
DebugInfoPlugin,
|
|
|
|
|
ui::GameUiPlugin { ..default() },
|
|
|
|
|
))
|
|
|
|
|
.add_systems(Startup, init)
|
|
|
|
|
.add_systems(Startup, (init, init_assets_dir))
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
(
|
|
|
|
|
export.run_if(interaction_condition::<ExportAction>),
|
|
|
|
|
clear.run_if(interaction_condition::<ClearAction>),
|
|
|
|
|
import.run_if(interaction_condition::<ImportAction>),
|
|
|
|
|
inspect.run_if(interaction_condition::<InspectAction>),
|
|
|
|
|
load.run_if(interaction_condition::<LoadAssetsAction>),
|
|
|
|
|
unload.run_if(interaction_condition::<UnloadAssetsAction>),
|
|
|
|
|
spawn_level.run_if(interaction_condition::<SpawnLevelAction>),
|
|
|
|
|
asset_inspector::<AudioSource>,
|
|
|
|
|
asset_inspector::<Scene>,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.add_systems(
|
|
|
|
|
PostUpdate,
|
|
|
|
|
(
|
|
|
|
|
rehydrate::<Visibility, ComputedVisibility>,
|
|
|
|
|
rehydrate::<Handle<AudioSource>, PlaybackSettings>,
|
|
|
|
|
inspect.run_if(interaction_condition::<InspectAction>),
|
|
|
|
|
fallback_camera.run_if(fallback_camera_condition),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
@ -50,38 +84,37 @@ struct ImportAction;
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
struct InspectAction;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
struct LoadAssetsAction;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
struct UnloadAssetsAction;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
struct SpawnLevelAction;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Resource, Default)]
|
|
|
|
|
struct AssetRegistry {
|
|
|
|
|
handles: Vec<HandleUntyped>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init(server: Res<AssetServer>, mut commands: Commands, mut registry: ResMut<AssetRegistry>) {
|
|
|
|
|
fn init_assets_dir() {
|
|
|
|
|
IoTaskPool::get()
|
|
|
|
|
.spawn(async move {
|
|
|
|
|
match DirBuilder::new().create("assets") {
|
|
|
|
|
Ok(_) => info!("Created assets directory"),
|
|
|
|
|
Err(e) => warn!("Error creating assets directory", e),
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.detach();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init(mut commands: Commands) {
|
|
|
|
|
commands.spawn((
|
|
|
|
|
Camera2dBundle { ..default() },
|
|
|
|
|
UiCameraConfig { show_ui: true },
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
let audio_handle: Handle<AudioSource> = server.load("audio/Ambient/Lake Sound 1.ogg");
|
|
|
|
|
let scene_handle: Handle<Scene> = server.load("models/materials.glb#Scene0");
|
|
|
|
|
commands
|
|
|
|
|
.spawn((SpatialBundle { ..default() }, LevelRoot))
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
parent.spawn(AudioSourceBundle {
|
|
|
|
|
source: audio_handle.clone(),
|
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
|
mode: PlaybackMode::Loop,
|
|
|
|
|
paused: false,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
parent.spawn((SceneBundle {
|
|
|
|
|
scene: scene_handle.clone(),
|
|
|
|
|
..default()
|
|
|
|
|
},));
|
|
|
|
|
});
|
|
|
|
|
registry.handles.push(audio_handle.clone_untyped());
|
|
|
|
|
registry.handles.push(scene_handle.clone_untyped());
|
|
|
|
|
|
|
|
|
|
commands
|
|
|
|
|
.spawn((
|
|
|
|
|
NodeBundle {
|
|
|
|
|
@ -101,6 +134,57 @@ fn init(server: Res<AssetServer>, mut commands: Commands, mut registry: ResMut<A
|
|
|
|
|
ui::Select::Action,
|
|
|
|
|
))
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
parent.spawn((
|
|
|
|
|
ButtonBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
padding: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
ui::Title {
|
|
|
|
|
text: "Load Assets".into(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
LoadAssetsAction,
|
|
|
|
|
));
|
|
|
|
|
parent.spawn((
|
|
|
|
|
ButtonBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
padding: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
ui::Title {
|
|
|
|
|
text: "Dump Assets".into(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
UnloadAssetsAction,
|
|
|
|
|
));
|
|
|
|
|
parent.spawn((
|
|
|
|
|
ButtonBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
padding: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
ui::Title {
|
|
|
|
|
text: "Spawn Level".into(),
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
SpawnLevelAction,
|
|
|
|
|
));
|
|
|
|
|
parent.spawn((
|
|
|
|
|
ButtonBundle {
|
|
|
|
|
style: Style {
|
|
|
|
|
@ -269,6 +353,8 @@ fn clear(root: Query<Entity, With<LevelRoot>>, mut commands: Commands) {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Figure out how to import the same asset from a differnt source
|
|
|
|
|
// How do the plugins do it??
|
|
|
|
|
fn import(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
|
info!("Importing level");
|
|
|
|
|
|
|
|
|
|
@ -295,3 +381,47 @@ fn fallback_camera(
|
|
|
|
|
) {
|
|
|
|
|
ui_camera.single_mut().is_active = cameras.iter().len() <= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn asset_inspector<T: Asset>(mut events: EventReader<AssetEvent<T>>) {
|
|
|
|
|
events.iter().for_each(|event| match event {
|
|
|
|
|
AssetEvent::Created { handle } => info!("Asset Created {:?}", handle),
|
|
|
|
|
AssetEvent::Modified { handle } => info!("Asset Modified {:?}", handle),
|
|
|
|
|
AssetEvent::Removed { handle } => info!("Asset Removed {:?}", handle),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OK seems like `load_folder` does not automatically pick up added files
|
|
|
|
|
fn load(mut registry: ResMut<AssetRegistry>, server: Res<AssetServer>) {
|
|
|
|
|
info!("Loading assets");
|
|
|
|
|
|
|
|
|
|
registry.handles = server.load_folder("./dynamic").unwrap();
|
|
|
|
|
info!("Current files: {:?}", registry.handles);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn unload(mut registry: ResMut<AssetRegistry>, mut gltfs: ResMut<Assets<Gltf>>) {
|
|
|
|
|
info!("Unloading asstes");
|
|
|
|
|
|
|
|
|
|
registry.handles.clear();
|
|
|
|
|
|
|
|
|
|
// This is required to clear scenes from asset cache
|
|
|
|
|
gltfs.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn spawn_level(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
|
commands
|
|
|
|
|
.spawn((SpatialBundle { ..default() }, LevelRoot))
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
parent.spawn(AudioSourceBundle {
|
|
|
|
|
source: server.load::<AudioSource, &str>("dynamic/Lake Sound 1.ogg"),
|
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
|
mode: PlaybackMode::Loop,
|
|
|
|
|
paused: false,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
parent.spawn((SceneBundle {
|
|
|
|
|
scene: server.load("dynamic/materials.glb#Scene0"),
|
|
|
|
|
..default()
|
|
|
|
|
},));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|