Placeholder cover arts

[skip ci]
This commit is contained in:
Aleksander
2025-12-26 13:58:12 +01:00
parent a849d1aed4
commit c4e8dee1fd
2 changed files with 110 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -12,10 +12,13 @@ use wgui::{
i18n::Translation, i18n::Translation,
layout::{Layout, WidgetID, WidgetPair}, layout::{Layout, WidgetID, WidgetPair},
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState},
renderer_vk::text::custom_glyph::{CustomGlyphContent, CustomGlyphData}, renderer_vk::text::{
FontWeight, HorizontalAlign, TextShadow, TextStyle,
custom_glyph::{CustomGlyphContent, CustomGlyphData},
},
taffy::{ taffy::{
self, self, AlignItems, AlignSelf, JustifyContent, JustifySelf,
prelude::{length, percent}, prelude::{auto, length, percent},
}, },
task::Tasks, task::Tasks,
widget::{ widget::{
@@ -33,7 +36,7 @@ use crate::{
util::{ util::{
cover_art_fetcher::{self, CoverArt}, cover_art_fetcher::{self, CoverArt},
popup_manager::MountPopupParams, popup_manager::MountPopupParams,
steam_utils::{self, AppID, SteamUtils}, steam_utils::{self, AppID, AppManifest, SteamUtils},
various::AsyncExecutor, various::AsyncExecutor,
}, },
}; };
@@ -54,6 +57,7 @@ pub struct Params<'a> {
struct Cell { struct Cell {
image_parent: WidgetID, image_parent: WidgetID,
manifest: AppManifest,
} }
pub struct View { pub struct View {
@@ -66,6 +70,7 @@ pub struct View {
steam_utils: steam_utils::SteamUtils, steam_utils: steam_utils::SteamUtils,
cells: HashMap<AppID, Cell>, cells: HashMap<AppID, Cell>,
img_placeholder: Option<CustomGlyphData>,
} }
impl View { impl View {
@@ -93,6 +98,7 @@ impl View {
id_list_parent: list_parent.id, id_list_parent: list_parent.id,
steam_utils, steam_utils,
cells: HashMap::new(), cells: HashMap::new(),
img_placeholder: None,
}) })
} }
@@ -180,6 +186,8 @@ fn construct_game_cover(
height: percent(1.0), height: percent(1.0),
}, },
padding: taffy::Rect::length(2.0), padding: taffy::Rect::length(2.0),
align_items: Some(AlignItems::Center),
justify_content: Some(JustifyContent::Center),
..Default::default() ..Default::default()
}, },
)?; )?;
@@ -257,6 +265,7 @@ fn construct_game_cover(
button, button,
Cell { Cell {
image_parent: image_parent.id, image_parent: image_parent.id,
manifest: manifest.clone(),
}, },
)) ))
} }
@@ -353,36 +362,22 @@ impl View {
Ok(()) Ok(())
} }
fn action_set_cover_art( fn get_placeholder_image(&mut self) -> anyhow::Result<&CustomGlyphData> {
&mut self, if self.img_placeholder.is_none() {
layout: &mut Layout, let c = CustomGlyphData::new(CustomGlyphContent::from_assets(
app_id: &AppID, &self.globals,
cover_art: Rc<CoverArt>, AssetPath::BuiltIn("dashboard/placeholder_cover.png"),
) -> anyhow::Result<()> { )?);
if cover_art.compressed_image_data.is_empty() { self.img_placeholder = Some(c);
return Ok(()); // do nothing
} }
let Some(cell) = self.cells.get(app_id) else { Ok(self.img_placeholder.as_ref().unwrap()) // safe
debug_assert!(false); // this shouldn't happen }
return Ok(());
};
let glyph_content = match CustomGlyphContent::from_bin_raster(&cover_art.compressed_image_data) {
Ok(c) => c,
Err(e) => {
log::warn!(
"failed to decode cover art image for AppID {} ({:?}), skipping",
app_id,
e
);
return Ok(());
}
};
fn mount_image(layout: &mut Layout, cell: &Cell, glyph: &CustomGlyphData) -> anyhow::Result<()> {
let image = WidgetImage::create(WidgetImageParams { let image = WidgetImage::create(WidgetImageParams {
round: WLength::Units(12.0), round: WLength::Units(12.0),
glyph_data: Some(CustomGlyphData::new(glyph_content)), glyph_data: Some(glyph.clone()),
..Default::default() ..Default::default()
}); });
@@ -401,4 +396,90 @@ impl View {
Ok(()) Ok(())
} }
fn mount_placeholder_text(
globals: &WguiGlobals,
layout: &mut Layout,
parent: WidgetID,
text: &str,
) -> anyhow::Result<()> {
let label = WidgetLabel::create(
&mut globals.get(),
WidgetLabelParams {
content: Translation::from_raw_text(text),
style: TextStyle {
weight: Some(FontWeight::Bold),
wrap: true,
size: Some(16.0),
align: Some(HorizontalAlign::Center),
shadow: Some(TextShadow {
color: drawing::Color::new(0.0, 0.0, 0.0, 0.5),
x: 2.0,
y: 2.0,
}),
..Default::default()
},
},
);
layout.add_child(
parent,
label,
taffy::Style {
position: taffy::Position::Absolute,
align_self: Some(AlignSelf::Baseline),
justify_self: Some(JustifySelf::Center),
margin: taffy::Rect {
top: length(32.0),
bottom: auto(),
left: auto(),
right: auto(),
},
..Default::default()
},
)?;
Ok(())
}
fn action_set_cover_art(
&mut self,
layout: &mut Layout,
app_id: &AppID,
cover_art: Rc<CoverArt>,
) -> anyhow::Result<()> {
if cover_art.compressed_image_data.is_empty() {
// mount placeholder
let img = self.get_placeholder_image()?.clone();
let Some(cell) = self.cells.get(app_id) else {
debug_assert!(false); // this shouldn't happen
return Ok(());
};
View::mount_image(layout, cell, &img)?;
View::mount_placeholder_text(&self.globals, layout, cell.image_parent, &cell.manifest.name)?;
} else {
// mount image
let Some(cell) = self.cells.get(app_id) else {
debug_assert!(false); // this shouldn't happen
return Ok(());
};
let glyph = match CustomGlyphContent::from_bin_raster(&cover_art.compressed_image_data) {
Ok(c) => c,
Err(e) => {
log::warn!(
"failed to decode cover art image for AppID {} ({:?}), skipping",
app_id,
e
);
return Ok(());
}
};
View::mount_image(layout, cell, &CustomGlyphData::new(glyph))?;
}
Ok(())
}
} }