|
|
|
|
@ -17,15 +17,23 @@ fn main() {
|
|
|
|
|
.init_state::<Debugger>()
|
|
|
|
|
.init_state::<GameState>()
|
|
|
|
|
.init_resource::<AllAssets>()
|
|
|
|
|
.add_systems(Update, load)
|
|
|
|
|
.init_resource::<SetupChecklist>()
|
|
|
|
|
// Check if assets were added to loading queue
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
loading_check
|
|
|
|
|
.run_if(in_state(Loading::Active))
|
|
|
|
|
.run_if(resource_changed::<AllAssets>),
|
|
|
|
|
)
|
|
|
|
|
// Wait for pending assets to be loaded
|
|
|
|
|
.add_systems(Update, loading_wait.run_if(in_state(Loading::Active)))
|
|
|
|
|
// Once done loading, move to the setup state
|
|
|
|
|
.add_systems(OnEnter(Loading::Idle), setup_game)
|
|
|
|
|
// Check if the game is ready to progress
|
|
|
|
|
.add_systems(Update, setup_wait.run_if(in_state(GameState::Setup)))
|
|
|
|
|
.run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Default, Resource, Debug)]
|
|
|
|
|
struct AllAssets {
|
|
|
|
|
handles: Vec<UntypedHandle>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Reports if the game is loading assets
|
|
|
|
|
#[derive(States, Default, Clone, Eq, Debug, PartialEq, Hash)]
|
|
|
|
|
enum Loading {
|
|
|
|
|
@ -46,16 +54,67 @@ enum Debugger {
|
|
|
|
|
#[derive(States, Default, Clone, Eq, Debug, PartialEq, Hash)]
|
|
|
|
|
enum GameState {
|
|
|
|
|
#[default]
|
|
|
|
|
Boot,
|
|
|
|
|
Setup,
|
|
|
|
|
Run,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load(mut next: ResMut<NextState<Loading>>, server: Res<AssetServer>, assets: Res<AllAssets>) {
|
|
|
|
|
if assets.handles.iter().all(|h| matches!(server.get_load_state(h.id()), Some(LoadState::Loaded))) {
|
|
|
|
|
/// A list of all assets so we don't lose them
|
|
|
|
|
#[derive(Default, Resource, Debug)]
|
|
|
|
|
struct AllAssets {
|
|
|
|
|
handles: Vec<UntypedHandle>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A "checklist" to know if we can progress from setup to the game
|
|
|
|
|
#[derive(Default, Resource)]
|
|
|
|
|
struct SetupChecklist {
|
|
|
|
|
spawn_shape: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sends the game into Loading::Active if assets are added to the AllAssets list
|
|
|
|
|
fn loading_check(mut next: ResMut<NextState<Loading>>, all_assets: Res<AllAssets>) {
|
|
|
|
|
debug_assert!(all_assets.is_changed());
|
|
|
|
|
|
|
|
|
|
next.set(Loading::Active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Waits in Loading::Active until all assets are loaded then move to Loading::Idle
|
|
|
|
|
fn loading_wait(
|
|
|
|
|
curr: Res<State<Loading>>,
|
|
|
|
|
mut next: ResMut<NextState<Loading>>,
|
|
|
|
|
server: Res<AssetServer>,
|
|
|
|
|
all_assets: Res<AllAssets>,
|
|
|
|
|
) {
|
|
|
|
|
debug_assert!(*curr.get() == Loading::Active);
|
|
|
|
|
if all_assets
|
|
|
|
|
.handles
|
|
|
|
|
.iter()
|
|
|
|
|
.all(|h| matches!(server.get_load_state(h.id()), Some(LoadState::Loaded)))
|
|
|
|
|
{
|
|
|
|
|
next.set(Loading::Idle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Moves the game from Boot to Setup
|
|
|
|
|
fn setup_game(curr: Res<State<GameState>>, mut next: ResMut<NextState<GameState>>) {
|
|
|
|
|
debug_assert!(*curr.get() == GameState::Boot);
|
|
|
|
|
|
|
|
|
|
next.set(GameState::Setup);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn setup_wait(
|
|
|
|
|
curr: Res<State<GameState>>,
|
|
|
|
|
mut next: ResMut<NextState<GameState>>,
|
|
|
|
|
checklist: Res<SetupChecklist>,
|
|
|
|
|
) {
|
|
|
|
|
debug_assert!(*curr.get() == GameState::Setup);
|
|
|
|
|
|
|
|
|
|
// If all checks pass, move on to the run state
|
|
|
|
|
if checklist.spawn_shape {
|
|
|
|
|
next.set(GameState::Run);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A wrapper around a handle for assigning an arbitrary Handle<T> to an entity
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
struct AssetComponent<T: Asset> {
|
|
|
|
|
|