mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Add asset removal. Clean up old/removed meshes
This commit is contained in:
parent
86c18edbfd
commit
33d4d5f562
6 changed files with 104 additions and 29 deletions
|
@ -1,19 +1,23 @@
|
|||
use crate::{
|
||||
update_asset_storage_system, AssetChannel, AssetLoader, AssetServer, ChannelAssetHandler,
|
||||
Handle, HandleId, DEFAULT_HANDLE_ID,
|
||||
Handle, HandleId,
|
||||
};
|
||||
use bevy_app::{stage, AppBuilder, Events};
|
||||
use bevy_core::bytes::GetBytes;
|
||||
use legion::prelude::*;
|
||||
use std::{path::{Path, PathBuf}, collections::HashMap};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
pub enum AssetEvent<T> {
|
||||
Created { handle: Handle<T> },
|
||||
Modified { handle: Handle<T> },
|
||||
Removed { handle: Handle<T> },
|
||||
}
|
||||
|
||||
pub struct Assets<T> {
|
||||
assets: HashMap<HandleId, T>,
|
||||
assets: HashMap<Handle<T>, T>,
|
||||
paths: HashMap<PathBuf, Handle<T>>,
|
||||
events: Events<AssetEvent<T>>,
|
||||
}
|
||||
|
@ -34,16 +38,15 @@ impl<T> Assets<T> {
|
|||
}
|
||||
|
||||
pub fn add(&mut self, asset: T) -> Handle<T> {
|
||||
let id = HandleId::new();
|
||||
self.assets.insert(id, asset);
|
||||
let handle = Handle::from_id(id);
|
||||
let handle = Handle::new();
|
||||
self.assets.insert(handle, asset);
|
||||
self.events.send(AssetEvent::Created { handle });
|
||||
handle
|
||||
}
|
||||
|
||||
pub fn set(&mut self, handle: Handle<T>, asset: T) {
|
||||
let exists = self.assets.contains_key(&handle.id);
|
||||
self.assets.insert(handle.id, asset);
|
||||
let exists = self.assets.contains_key(&handle);
|
||||
self.assets.insert(handle, asset);
|
||||
|
||||
if exists {
|
||||
self.events.send(AssetEvent::Modified { handle });
|
||||
|
@ -53,9 +56,9 @@ impl<T> Assets<T> {
|
|||
}
|
||||
|
||||
pub fn add_default(&mut self, asset: T) -> Handle<T> {
|
||||
let exists = self.assets.contains_key(&DEFAULT_HANDLE_ID);
|
||||
self.assets.insert(DEFAULT_HANDLE_ID, asset);
|
||||
let handle = Handle::default();
|
||||
let exists = self.assets.contains_key(&handle);
|
||||
self.assets.insert(handle, asset);
|
||||
if exists {
|
||||
self.events.send(AssetEvent::Modified { handle });
|
||||
} else {
|
||||
|
@ -69,27 +72,44 @@ impl<T> Assets<T> {
|
|||
}
|
||||
|
||||
pub fn get_id(&self, id: HandleId) -> Option<&T> {
|
||||
self.assets.get(&id)
|
||||
self.assets.get(&Handle::from_id(id))
|
||||
}
|
||||
|
||||
pub fn get_id_mut(&mut self, id: HandleId) -> Option<&mut T> {
|
||||
self.assets.get_mut(&id)
|
||||
self.assets.get_mut(&Handle::from_id(id))
|
||||
}
|
||||
|
||||
pub fn get(&self, handle: &Handle<T>) -> Option<&T> {
|
||||
self.assets.get(&handle.id)
|
||||
self.assets.get(&handle)
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, handle: &Handle<T>) -> Option<&mut T> {
|
||||
self.assets.get_mut(&handle.id)
|
||||
self.assets.get_mut(&handle)
|
||||
}
|
||||
|
||||
pub fn get_or_insert_with(&mut self, handle: Handle<T>, insert_fn: impl FnOnce() -> T) -> &mut T {
|
||||
self.assets.entry(handle.id).or_insert_with(insert_fn)
|
||||
pub fn get_or_insert_with(
|
||||
&mut self,
|
||||
handle: Handle<T>,
|
||||
insert_fn: impl FnOnce() -> T,
|
||||
) -> &mut T {
|
||||
let mut event = None;
|
||||
let borrowed = self.assets.entry(handle).or_insert_with(|| {
|
||||
event = Some(AssetEvent::Created { handle });
|
||||
insert_fn()
|
||||
});
|
||||
|
||||
if let Some(event) = event {
|
||||
self.events.send(event);
|
||||
}
|
||||
borrowed
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (Handle<T>, &T)> {
|
||||
self.assets.iter().map(|(k, v)| (Handle::from_id(*k), v))
|
||||
self.assets.iter().map(|(k, v)| (*k, v))
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, handle: &Handle<T>) -> Option<T> {
|
||||
self.assets.remove(&handle)
|
||||
}
|
||||
|
||||
pub fn asset_event_system(
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
VertexBufferDescriptor, VertexBufferDescriptors, VertexFormat,
|
||||
},
|
||||
render_resource::{BufferInfo, BufferUsage},
|
||||
renderer::RenderResources,
|
||||
renderer::{RenderResourceContext, RenderResources},
|
||||
shader::AsUniforms,
|
||||
Renderable, Vertex,
|
||||
};
|
||||
|
@ -320,6 +320,20 @@ pub mod shape {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove_current_mesh_resources(
|
||||
render_resources: &dyn RenderResourceContext,
|
||||
handle: Handle<Mesh>,
|
||||
) {
|
||||
if let Some(resource) = render_resources.get_asset_resource(handle, VERTEX_BUFFER_ASSET_INDEX) {
|
||||
render_resources.remove_buffer(resource);
|
||||
render_resources.remove_asset_resource(handle, VERTEX_BUFFER_ASSET_INDEX);
|
||||
}
|
||||
if let Some(resource) = render_resources.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX) {
|
||||
render_resources.remove_buffer(resource);
|
||||
render_resources.remove_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
let mesh_events = resources.get::<Events<AssetEvent<Mesh>>>().unwrap();
|
||||
|
@ -333,18 +347,26 @@ pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Sched
|
|||
.read_resource::<Events<AssetEvent<Mesh>>>()
|
||||
.with_query(<(Read<Handle<Mesh>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_, world, (render_resource_context, meshes, mesh_events), query| {
|
||||
let render_resources = &*render_resource_context.context;
|
||||
let changed_meshes = mesh_event_reader
|
||||
.iter(&mesh_events)
|
||||
.map(|e| match e {
|
||||
AssetEvent::Created { handle } | AssetEvent::Modified { handle } => {
|
||||
Some(handle)
|
||||
move |_, world, (render_resources, meshes, mesh_events), query| {
|
||||
let render_resources = &*render_resources.context;
|
||||
let mut changed_meshes = HashSet::new();
|
||||
for event in mesh_event_reader.iter(&mesh_events) {
|
||||
match event {
|
||||
AssetEvent::Created { handle } => {
|
||||
changed_meshes.insert(*handle);
|
||||
}
|
||||
})
|
||||
.filter(|h| h.is_some())
|
||||
.map(|h| *h.unwrap())
|
||||
.collect::<HashSet<Handle<Mesh>>>();
|
||||
AssetEvent::Modified { handle } => {
|
||||
changed_meshes.insert(*handle);
|
||||
remove_current_mesh_resources(render_resources, *handle);
|
||||
}
|
||||
AssetEvent::Removed { handle } => {
|
||||
remove_current_mesh_resources(render_resources, *handle);
|
||||
// if mesh was modified and removed in the same update, ignore the modification
|
||||
// events are ordered so future modification events are ok
|
||||
changed_meshes.remove(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for changed_mesh_handle in changed_meshes.iter() {
|
||||
if let Some(mesh) = meshes.get(changed_mesh_handle) {
|
||||
|
|
|
@ -125,4 +125,13 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||
}
|
||||
}
|
||||
fn create_shader_module_from_source(&self, _shader_handle: Handle<Shader>, _shader: &Shader) {}
|
||||
fn remove_asset_resource_untyped(
|
||||
&self,
|
||||
handle: HandleUntyped,
|
||||
index: usize) {
|
||||
self.asset_resources
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(&(handle, index));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,10 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
|||
handle: HandleUntyped,
|
||||
index: usize,
|
||||
) -> Option<RenderResource>;
|
||||
fn remove_asset_resource_untyped(
|
||||
&self,
|
||||
handle: HandleUntyped,
|
||||
index: usize);
|
||||
fn create_render_pipeline(
|
||||
&self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
|
@ -101,6 +105,12 @@ impl dyn RenderResourceContext {
|
|||
{
|
||||
self.get_asset_resource_untyped(handle.into(), index)
|
||||
}
|
||||
pub fn remove_asset_resource<T>(&self, handle: Handle<T>, index: usize)
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.remove_asset_resource_untyped(handle.into(), index);
|
||||
}
|
||||
}
|
||||
|
||||
impl_downcast!(RenderResourceContext);
|
||||
|
|
|
@ -366,6 +366,15 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
asset_resources.get(&(handle, index)).cloned()
|
||||
}
|
||||
|
||||
fn remove_asset_resource_untyped(
|
||||
&self,
|
||||
handle: HandleUntyped,
|
||||
index: usize,
|
||||
) {
|
||||
let mut asset_resources = self.resources.asset_resources.write().unwrap();
|
||||
asset_resources.remove(&(handle, index));
|
||||
}
|
||||
|
||||
fn create_render_pipeline(
|
||||
&self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
|
|
|
@ -6,7 +6,12 @@ use bevy::{
|
|||
fn main() {
|
||||
App::build()
|
||||
.add_default_plugins()
|
||||
// Adds frame time diagnostics
|
||||
.add_plugin(FrameTimeDiagnosticsPlugin::default())
|
||||
// Adds a system that prints diagnostics to the console
|
||||
.add_plugin(PrintDiagnosticsPlugin::default())
|
||||
// Any plugin can register diagnostics
|
||||
// Uncomment this to add some render resource diagnostics:
|
||||
// .add_plugin(bevy::wgpu::diagnostic::WgpuResourceDiagnosticsPlugin::default())
|
||||
.run();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue