Skip to content

Commit

Permalink
Remove unsafe world cell
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasEi committed Jun 8, 2024
1 parent adf1df8 commit 07a481c
Show file tree
Hide file tree
Showing 21 changed files with 198 additions and 162 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ use bevy_asset_loader::asset_collection::AssetCollection;

#[derive(AssetCollection, Resource)]
struct MyAssets {
#[asset(texture_atlas_layout(tile_size_x = 64., tile_size_y = 64., columns = 8, rows = 1, padding_x = 12., padding_y = 12., offset_x = 6., offset_y = 6.))]
#[asset(texture_atlas_layout(tile_size_x = 64, tile_size_y = 64, columns = 8, rows = 1, padding_x = 12, padding_y = 12, offset_x = 6, offset_y = 6))]
layout: Handle<TextureAtlasLayout>,
#[asset(path = "images/sprite_sheet.png")]
sprite: Handle<Image>,
Expand All @@ -220,19 +220,19 @@ struct MyAssets {
path: "images/sprite_sheet.png",
),
"player.layout": TextureAtlasLayout (
tile_size_x: 100.,
tile_size_y: 64.,
tile_size_x: 100,
tile_size_y: 64,
columns: 8,
rows: 1,
padding_x: 12.,
padding_y: 12.,
offset_x: 6.,
offset_y: 6.,
padding_x: 12,
padding_y: 12,
offset_x: 6,
offset_y: 6,
),
})
```

The four padding & offset fields/attributes are optional, and default to `0.`.
The four padding & offset fields/attributes are optional, and default to `0`.

### Images with sampler configuration

Expand Down Expand Up @@ -483,7 +483,7 @@ fn main() {

#[derive(AssetCollection, Resource)]
struct MyAssets {
#[asset(texture_atlas_layout(tile_size_x = 64., tile_size_y = 64., columns = 8, rows = 1, padding_x = 12., padding_y = 12., offset_x = 6., offset_y = 6.))]
#[asset(texture_atlas_layout(tile_size_x = 64, tile_size_y = 64, columns = 8, rows = 1, padding_x = 12, padding_y = 12, offset_x = 6, offset_y = 6))]
layout: Handle<TextureAtlasLayout>,
#[asset(path = "images/sprite_sheet.png")]
sprite: Handle<Image>,
Expand Down
4 changes: 2 additions & 2 deletions bevy_asset_loader/src/asset_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ impl AssetCollectionApp for App {
// we need to make sure the resource exists here
self.init_resource::<DynamicAssets>();
// make sure the assets start to load
let _ = Collection::load(&mut self.world_mut());
let resource = Collection::create(&mut self.world_mut());
let _ = Collection::load(self.world_mut());
let resource = Collection::create(self.world_mut());
self.insert_resource(resource);
}
self
Expand Down
3 changes: 1 addition & 2 deletions bevy_asset_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@
//! }
//! ```
// Todo: remove usage of UnsafeWorldCell
// #![forbid(unsafe_code)]
#![forbid(unsafe_code)]
#![warn(unused_imports, missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

Expand Down
5 changes: 2 additions & 3 deletions bevy_asset_loader/src/loading_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,10 +718,9 @@ pub trait LoadingStateAppExt {
/// # }
/// # impl FromWorld for TextureAtlasLayoutFromWorld {
/// # fn from_world(world: &mut World) -> Self {
/// # let cell = world.cell();
/// # let mut layouts = cell.get_resource_mut::<Assets<TextureAtlasLayout>>().expect("TextureAtlasLayouts missing");
/// # let mut layouts = world.get_resource_mut::<Assets<TextureAtlasLayout>>().expect("TextureAtlasLayouts missing");
/// # TextureAtlasLayoutFromWorld {
/// # atlas_layout: layouts.add(TextureAtlasLayout::from_grid(Vec2::new(250., 250.), 1, 4, None, None))
/// # atlas_layout: layouts.add(TextureAtlasLayout::from_grid(UVec2::new(250, 250), 1, 4, None, None))
/// # }
/// # }
/// # }
Expand Down
3 changes: 2 additions & 1 deletion bevy_asset_loader/src/loading_state/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub(crate) fn start_loading_collection<S: FreelyMutableState, Assets: AssetColle
world.insert_resource(handles);
}

#[allow(clippy::type_complexity)]
pub(crate) fn check_loading_collection<S: FreelyMutableState, Assets: AssetCollection>(
world: &mut World,
system_state: &mut SystemState<(
Expand Down Expand Up @@ -223,7 +224,7 @@ pub fn apply_internal_state_transition<S: FreelyMutableState>(world: &mut World)
{
world.run_schedule(OnEnterInternalLoadingState(state, entered_state));
}
world.insert_resource(NextState::<InternalLoadingState<S>>::Unchanged)
world.insert_resource(NextState::<InternalLoadingState<S>>::Unchanged);
}
Some(next_state) => world.insert_resource(next_state),
_ => {}
Expand Down
93 changes: 48 additions & 45 deletions bevy_asset_loader/src/standard_dynamic_asset.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::dynamic_asset::{DynamicAsset, DynamicAssetType};
use crate::dynamic_asset::{DynamicAssetCollection, DynamicAssets};
use bevy::asset::{Asset, AssetServer, Assets, LoadedFolder, UntypedHandle};
use bevy::ecs::system::SystemState;
use bevy::ecs::world::{Command, World};
use bevy::reflect::TypePath;
use bevy::utils::HashMap;
Expand All @@ -10,6 +11,7 @@ use serde::{Deserialize, Serialize};
use bevy::math::UVec2;
#[cfg(feature = "3d")]
use bevy::pbr::StandardMaterial;
use bevy::prelude::{Res, ResMut};
#[cfg(feature = "2d")]
use bevy::sprite::TextureAtlasLayout;

Expand Down Expand Up @@ -161,34 +163,32 @@ impl DynamicAsset for StandardDynamicAsset {
}

fn build(&self, world: &mut World) -> Result<DynamicAssetType, anyhow::Error> {
let cell = world.as_unsafe_world_cell();
let asset_server = unsafe {
cell.get_resource::<AssetServer>()
.expect("Cannot get AssetServer")
};
match self {
StandardDynamicAsset::File { path } => Ok(DynamicAssetType::Single(
asset_server.get_handle_untyped(path).unwrap(),
)),
StandardDynamicAsset::File { path } => {
let asset_server = world
.get_resource::<AssetServer>()
.expect("Cannot get AssetServer");
Ok(DynamicAssetType::Single(
asset_server.get_handle_untyped(path).unwrap(),
))
}
#[cfg(any(feature = "3d", feature = "2d"))]
StandardDynamicAsset::Image { path, sampler } => {
let mut system_state =
SystemState::<(ResMut<Assets<Image>>, Res<AssetServer>)>::new(world);
let (mut images, asset_server) = system_state.get_mut(world);
let mut handle = asset_server.load(path);
if let Some(sampler) = sampler {
let mut images = unsafe {
cell.get_resource_mut::<Assets<Image>>()
.expect("Cannot get resource Assets<Image>")
};
Self::update_image_sampler(&mut handle, &mut images, sampler);
}

Ok(DynamicAssetType::Single(handle.untyped()))
}
#[cfg(feature = "3d")]
StandardDynamicAsset::StandardMaterial { path } => {
let mut materials = unsafe {
cell.get_resource_mut::<Assets<StandardMaterial>>()
.expect("Cannot get resource Assets<StandardMaterial>")
};
let mut system_state =
SystemState::<(ResMut<Assets<StandardMaterial>>, Res<AssetServer>)>::new(world);
let (mut materials, asset_server) = system_state.get_mut(world);
let handle = materials
.add(StandardMaterial::from(
asset_server.get_handle::<Image>(path).unwrap(),
Expand All @@ -208,10 +208,9 @@ impl DynamicAsset for StandardDynamicAsset {
offset_x,
offset_y,
} => {
let mut atlases = unsafe {
cell.get_resource_mut::<Assets<TextureAtlasLayout>>()
.expect("Cannot get resource Assets<TextureAtlasLayout>")
};
let mut atlases = world
.get_resource_mut::<Assets<TextureAtlasLayout>>()
.expect("Cannot get Assets<TextureAtlasLayout>");
let texture_atlas_handle = atlases
.add(TextureAtlasLayout::from_grid(
UVec2::new(*tile_size_x, *tile_size_y),
Expand All @@ -225,10 +224,9 @@ impl DynamicAsset for StandardDynamicAsset {
Ok(DynamicAssetType::Single(texture_atlas_handle))
}
StandardDynamicAsset::Folder { path } => {
let folders = unsafe {
cell.get_resource_mut::<Assets<LoadedFolder>>()
.expect("Cannot get resource Assets<LoadedFolder>")
};
let mut system_state =
SystemState::<(Res<Assets<LoadedFolder>>, Res<AssetServer>)>::new(world);
let (folders, asset_server) = system_state.get(world);
Ok(DynamicAssetType::Collection(
folders
.get(&asset_server.get_handle(path).unwrap())
Expand All @@ -237,16 +235,21 @@ impl DynamicAsset for StandardDynamicAsset {
.to_vec(),
))
}
StandardDynamicAsset::Files { paths } => Ok(DynamicAssetType::Collection(
paths
.iter()
.map(|path| {
asset_server
.get_handle_untyped(path)
.expect("No Handle for path")
})
.collect(),
)),
StandardDynamicAsset::Files { paths } => {
let asset_server = world
.get_resource::<AssetServer>()
.expect("Cannot get AssetServer");
Ok(DynamicAssetType::Collection(
paths
.iter()
.map(|path| {
asset_server
.get_handle_untyped(path)
.expect("No Handle for path")
})
.collect(),
))
}
}
}
}
Expand Down Expand Up @@ -411,11 +414,11 @@ mod tests {
fn serialize_and_deserialize_atlas() {
let dynamic_asset_file = r#"({
"texture_atlas": TextureAtlasLayout(
tile_size_x: 96.0,
tile_size_y: 99.0,
tile_size_x: 96,
tile_size_y: 99,
columns: 8,
rows: 1,
padding_x: 42.42,
padding_x: 42,
),
})"#;
serialize_and_deserialize(dynamic_asset_file);
Expand All @@ -437,26 +440,26 @@ mod tests {
let dynamic_asset_file = r#"({
"layouts": [
TextureAtlasLayout(
tile_size_x: 32.0,
tile_size_y: 32.0,
tile_size_x: 32,
tile_size_y: 32,
columns: 12,
rows: 12,
),
TextureAtlasLayout(
tile_size_x: 32.0,
tile_size_y: 64.0,
tile_size_x: 32,
tile_size_y: 64,
columns: 12,
rows: 6,
),
TextureAtlasLayout(
tile_size_x: 64.0,
tile_size_y: 32.0,
tile_size_x: 64,
tile_size_y: 32,
columns: 6,
rows: 12,
),
TextureAtlasLayout(
tile_size_x: 64.0,
tile_size_y: 64.0,
tile_size_x: 64,
tile_size_y: 64,
columns: 6,
rows: 6,
),
Expand Down
30 changes: 16 additions & 14 deletions bevy_asset_loader/tests/can_run_without_next_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,32 @@ use bevy::app::AppExit;
use bevy::asset::AssetPlugin;
use bevy::audio::AudioPlugin;
use bevy::prelude::*;
use bevy::state::app::StatesPlugin;
use bevy_asset_loader::prelude::*;

#[test]
fn can_run_without_next_state() {
let mut app = App::new();
app.init_state::<MyStates>();

#[cfg(feature = "progress_tracking")]
app.add_plugins(iyes_progress::ProgressPlugin::new(MyStates::Load));
app.init_state::<MyStates>();
app.add_plugins((
MinimalPlugins,
AssetPlugin::default(),
AudioPlugin::default(),
))
.add_loading_state(LoadingState::new(MyStates::Load).load_collection::<MyAssets>())
.init_resource::<TestState>()
.add_systems(
Update,
(
expect.run_if(in_state(MyStates::Load)),
timeout.run_if(in_state(MyStates::Load)),
),
)
.run();
StatesPlugin,
));
#[cfg(feature = "progress_tracking")]
app.add_plugins(iyes_progress::ProgressPlugin::new(MyStates::Load));
app.add_loading_state(LoadingState::new(MyStates::Load).load_collection::<MyAssets>())
.init_resource::<TestState>()
.add_systems(
Update,
(
expect.run_if(in_state(MyStates::Load)),
timeout.run_if(in_state(MyStates::Load)),
),
)
.run();
}

fn timeout(time: Res<Time>) {
Expand Down
23 changes: 12 additions & 11 deletions bevy_asset_loader/tests/continues_to_failure_state.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
use bevy::app::AppExit;
use bevy::asset::AssetPlugin;
use bevy::prelude::*;
use bevy::state::app::StatesPlugin;
use bevy_asset_loader::prelude::*;

#[test]
fn continues_to_failure_state() {
let mut app = App::new();
app.init_state::<MyStates>();

app.add_plugins((MinimalPlugins, AssetPlugin::default(), StatesPlugin));
#[cfg(feature = "progress_tracking")]
app.add_plugins(iyes_progress::ProgressPlugin::new(MyStates::Load));
app.add_plugins((MinimalPlugins, AssetPlugin::default()))
.add_loading_state(
LoadingState::new(MyStates::Load)
.continue_to_state(MyStates::Next)
.on_failure_continue_to_state(MyStates::Error)
.load_collection::<Audio>(),
)
.add_systems(Update, timeout.run_if(in_state(MyStates::Load)))
.add_systems(OnEnter(MyStates::Next), fail)
.add_systems(OnEnter(MyStates::Error), exit)
.run();
app.add_loading_state(
LoadingState::new(MyStates::Load)
.continue_to_state(MyStates::Next)
.on_failure_continue_to_state(MyStates::Error)
.load_collection::<Audio>(),
)
.add_systems(Update, timeout.run_if(in_state(MyStates::Load)))
.add_systems(OnEnter(MyStates::Next), fail)
.add_systems(OnEnter(MyStates::Error), exit)
.run();
}

fn fail() {
Expand Down
5 changes: 3 additions & 2 deletions bevy_asset_loader/tests/continues_without_collection.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use bevy::app::AppExit;
use bevy::asset::AssetPlugin;
use bevy::prelude::*;
use bevy::state::app::StatesPlugin;
use bevy_asset_loader::prelude::*;

#[test]
fn continues_without_collection() {
let mut app = App::new();
app.init_state::<MyStates>();

app.add_plugins((MinimalPlugins, AssetPlugin::default(), StatesPlugin));
#[cfg(feature = "progress_tracking")]
app.add_plugins(iyes_progress::ProgressPlugin::new(MyStates::Load));
app.add_plugins((MinimalPlugins, AssetPlugin::default()))
.add_loading_state(LoadingState::new(MyStates::Load).continue_to_state(MyStates::Next))
app.add_loading_state(LoadingState::new(MyStates::Load).continue_to_state(MyStates::Next))
.init_resource::<TestState>()
.add_systems(Update, expect.run_if(in_state(MyStates::Load)))
.add_systems(OnEnter(MyStates::Next), exit)
Expand Down
Loading

0 comments on commit 07a481c

Please sign in to comment.