
# Objective This is a necessary precursor to #9122 (this was split from that PR to reduce the amount of code to review all at once). Moving `!Send` resource ownership to `App` will make it unambiguously `!Send`. `SubApp` must be `Send`, so it can't wrap `App`. ## Solution Refactor `App` and `SubApp` to not have a recursive relationship. Since `SubApp` no longer wraps `App`, once `!Send` resources are moved out of `World` and into `App`, `SubApp` will become unambiguously `Send`. There could be less code duplication between `App` and `SubApp`, but that would break `App` method chaining. ## Changelog - `SubApp` no longer wraps `App`. - `App` fields are no longer publicly accessible. - `App` can no longer be converted into a `SubApp`. - Various methods now return references to a `SubApp` instead of an `App`. ## Migration Guide - To construct a sub-app, use `SubApp::new()`. `App` can no longer convert into `SubApp`. - If you implemented a trait for `App`, you may want to implement it for `SubApp` as well. - If you're accessing `app.world` directly, you now have to use `app.world()` and `app.world_mut()`. - `App::sub_app` now returns `&SubApp`. - `App::sub_app_mut` now returns `&mut SubApp`. - `App::get_sub_app` now returns `Option<&SubApp>.` - `App::get_sub_app_mut` now returns `Option<&mut SubApp>.`
86 lines
3.0 KiB
Rust
86 lines
3.0 KiB
Rust
#[allow(clippy::module_inception)]
|
|
mod mesh;
|
|
pub mod morph;
|
|
pub mod primitives;
|
|
|
|
use bevy_utils::HashSet;
|
|
pub use mesh::*;
|
|
pub use primitives::*;
|
|
use std::{
|
|
hash::{Hash, Hasher},
|
|
sync::Arc,
|
|
};
|
|
|
|
use crate::{prelude::Image, render_asset::RenderAssetPlugin, RenderApp};
|
|
use bevy_app::{App, Plugin};
|
|
use bevy_asset::AssetApp;
|
|
use bevy_ecs::{entity::Entity, system::Resource};
|
|
|
|
/// Adds the [`Mesh`] as an asset and makes sure that they are extracted and prepared for the GPU.
|
|
pub struct MeshPlugin;
|
|
|
|
impl Plugin for MeshPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.init_asset::<Mesh>()
|
|
.init_asset::<skinning::SkinnedMeshInverseBindposes>()
|
|
.register_asset_reflect::<Mesh>()
|
|
.register_type::<skinning::SkinnedMesh>()
|
|
.register_type::<Vec<Entity>>()
|
|
// 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready
|
|
.add_plugins(RenderAssetPlugin::<Mesh, Image>::default());
|
|
|
|
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
|
return;
|
|
};
|
|
|
|
render_app.init_resource::<MeshVertexBufferLayouts>();
|
|
}
|
|
}
|
|
|
|
/// Describes the layout of the mesh vertices in GPU memory.
|
|
///
|
|
/// At most one copy of a mesh vertex buffer layout ever exists in GPU memory at
|
|
/// once. Therefore, comparing these for equality requires only a single pointer
|
|
/// comparison, and this type's [`PartialEq`] and [`Hash`] implementations take
|
|
/// advantage of this. To that end, this type doesn't implement
|
|
/// [`bevy_derive::Deref`] or [`bevy_derive::DerefMut`] in order to reduce the
|
|
/// possibility of accidental deep comparisons, which would be needlessly
|
|
/// expensive.
|
|
#[derive(Clone, Debug)]
|
|
pub struct MeshVertexBufferLayoutRef(pub Arc<MeshVertexBufferLayout>);
|
|
|
|
/// Stores the single copy of each mesh vertex buffer layout.
|
|
#[derive(Clone, Default, Resource)]
|
|
pub struct MeshVertexBufferLayouts(HashSet<Arc<MeshVertexBufferLayout>>);
|
|
|
|
impl MeshVertexBufferLayouts {
|
|
/// Inserts a new mesh vertex buffer layout in the store and returns a
|
|
/// reference to it, reusing the existing reference if this mesh vertex
|
|
/// buffer layout was already in the store.
|
|
pub fn insert(&mut self, layout: MeshVertexBufferLayout) -> MeshVertexBufferLayoutRef {
|
|
// Because the special `PartialEq` and `Hash` implementations that
|
|
// compare by pointer are on `MeshVertexBufferLayoutRef`, not on
|
|
// `Arc<MeshVertexBufferLayout>`, this compares the mesh vertex buffer
|
|
// structurally, not by pointer.
|
|
MeshVertexBufferLayoutRef(
|
|
self.0
|
|
.get_or_insert_with(&layout, |layout| Arc::new(layout.clone()))
|
|
.clone(),
|
|
)
|
|
}
|
|
}
|
|
|
|
impl PartialEq for MeshVertexBufferLayoutRef {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
Arc::ptr_eq(&self.0, &other.0)
|
|
}
|
|
}
|
|
|
|
impl Eq for MeshVertexBufferLayoutRef {}
|
|
|
|
impl Hash for MeshVertexBufferLayoutRef {
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
(&*self.0 as *const MeshVertexBufferLayout as usize).hash(state);
|
|
}
|
|
}
|