mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
significantly reduced annoying visual lag when generating asset previews
This commit is contained in:
@@ -25,13 +25,16 @@ use crate::{
|
||||
},
|
||||
fyrox::{
|
||||
asset::untyped::UntypedResource,
|
||||
core::{futures::executor::block_on, ok_or_continue, pool::Handle, Uuid},
|
||||
core::{futures::executor::block_on, parking_lot::Mutex, pool::Handle, Uuid},
|
||||
engine::Engine,
|
||||
fxhash::FxHashMap,
|
||||
gui::{message::MessageDirection, UiNode},
|
||||
},
|
||||
};
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
sync::{mpsc::Receiver, Arc},
|
||||
};
|
||||
|
||||
pub struct IconRequest {
|
||||
pub widget_handle: Handle<UiNode>,
|
||||
@@ -40,75 +43,95 @@ pub struct IconRequest {
|
||||
}
|
||||
|
||||
pub struct AssetPreviewCache {
|
||||
receiver: Receiver<IconRequest>,
|
||||
container: FxHashMap<Uuid, AssetPreviewTexture>,
|
||||
throughput: usize,
|
||||
queue: Arc<Mutex<VecDeque<IconRequest>>>,
|
||||
}
|
||||
|
||||
impl AssetPreviewCache {
|
||||
pub fn new(receiver: Receiver<IconRequest>, throughput: usize) -> Self {
|
||||
let queue = Arc::new(Mutex::new(VecDeque::new()));
|
||||
let queue2 = queue.clone();
|
||||
std::thread::spawn(move || {
|
||||
for request in receiver.iter() {
|
||||
let resource = request.resource.clone();
|
||||
if block_on(resource).is_ok() {
|
||||
queue.lock().push_back(request);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Self {
|
||||
receiver,
|
||||
container: Default::default(),
|
||||
throughput,
|
||||
queue: queue2,
|
||||
}
|
||||
}
|
||||
|
||||
fn preview_for(
|
||||
&mut self,
|
||||
resource: &UntypedResource,
|
||||
generators: &mut AssetPreviewGeneratorsCollection,
|
||||
force_update: bool,
|
||||
generated_counter: &mut usize,
|
||||
engine: &mut Engine,
|
||||
) -> Option<AssetPreviewTexture> {
|
||||
let resource_uuid = resource.resource_uuid()?;
|
||||
|
||||
if let (false, Some(cached_preview)) = (force_update, self.container.get(&resource_uuid)) {
|
||||
return Some(cached_preview.clone());
|
||||
} else if let Some(generator) = resource
|
||||
.type_uuid()
|
||||
.and_then(|type_uuid| generators.map.get_mut(&type_uuid))
|
||||
{
|
||||
if let Some(preview) = generator.generate_preview(resource, engine) {
|
||||
*generated_counter += 1;
|
||||
self.container.insert(resource_uuid, preview.clone());
|
||||
return Some(preview);
|
||||
} else if let Some(icon) = generator.simple_icon(resource, &engine.resource_manager) {
|
||||
let preview = AssetPreviewTexture {
|
||||
texture: icon,
|
||||
flip_y: false,
|
||||
};
|
||||
self.container.insert(resource_uuid, preview.clone());
|
||||
return Some(preview);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
generators: &mut AssetPreviewGeneratorsCollection,
|
||||
engine: &mut Engine,
|
||||
) {
|
||||
for request in self.receiver.try_iter().take(self.throughput) {
|
||||
let mut generated = 0;
|
||||
let queue = self.queue.clone();
|
||||
let mut queue = queue.lock();
|
||||
while let Some(request) = queue.pop_back() {
|
||||
let IconRequest {
|
||||
widget_handle: asset_item,
|
||||
widget_handle,
|
||||
resource,
|
||||
force_update,
|
||||
} = request;
|
||||
|
||||
let resource = ok_or_continue!(block_on(resource));
|
||||
|
||||
let preview = if let Some(resource_uuid) = resource.resource_uuid() {
|
||||
if let (false, Some(cached_preview)) =
|
||||
(force_update, self.container.get(&resource_uuid))
|
||||
{
|
||||
Some(cached_preview.clone())
|
||||
} else if let Some(generator) = resource
|
||||
.type_uuid()
|
||||
.and_then(|type_uuid| generators.map.get_mut(&type_uuid))
|
||||
{
|
||||
if let Some(preview) = generator.generate_preview(&resource, engine) {
|
||||
self.container.insert(resource_uuid, preview.clone());
|
||||
Some(preview)
|
||||
} else if let Some(icon) =
|
||||
generator.simple_icon(&resource, &engine.resource_manager)
|
||||
{
|
||||
let preview = AssetPreviewTexture {
|
||||
texture: icon,
|
||||
flip_y: false,
|
||||
};
|
||||
self.container.insert(resource_uuid, preview.clone());
|
||||
Some(preview)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(preview) = preview {
|
||||
if let Some(preview) =
|
||||
self.preview_for(&resource, generators, force_update, &mut generated, engine)
|
||||
{
|
||||
let ui = engine.user_interfaces.first();
|
||||
|
||||
ui.send_message(AssetItemMessage::icon(
|
||||
asset_item,
|
||||
widget_handle,
|
||||
MessageDirection::ToWidget,
|
||||
Some(preview.texture),
|
||||
preview.flip_y,
|
||||
));
|
||||
}
|
||||
|
||||
if generated >= self.throughput {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user