How to pass a font asset handle to a style builder?
I'm trying to pass a handle:
#[derive(Clone, PartialEq)]
pub struct MyUi;
impl ViewTemplate for MyUi {
type View = impl View;
fn create(&self, cx: &mut Cx) -> Self::View {
let font_assets = cx.use_resource::<MyFontAssets>();
let font = font_assets.comic_sans.clone();
Element::<NodeBundle>::new().style(move |ss: &mut StyleBuilder| {
ss.font(font);
})
}
}
But it doesn't work because the style builder function must be Fn:
expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
required for `{closure@src/my_ui.rs:26:44: 26:72}` to implement `bevy_mod_stylebuilder::StyleTuple`
Is there a way to make font handles work with quill?
Hmmm, not sure why this doesn't work. That being said, there's a few things you can do right now:
-
Use style_dyn, and pass in the font handle as an explicit dependency.
-
Instead of passing in a handle,
ss.font()should be able to accept the asset path string directly, e.g..font("embedded://bevy_quill_obsidian/assets/fonts/Open_Sans/static/OpenSans-Medium.ttf").
Thanks, but I ended up inserting InheritableFontStyles at the root node instead:
Element::<NodeBundle>::new()
.insert(InheritableFontStyles {
...
})
Use style_dyn, and pass in the font handle as an explicit dependency.
I'll try this if I ever need to override the font on a specific node.
Instead of passing in a handle,
ss.font()should be able to accept the asset path string directly, e.g..font("embedded://bevy_quill_obsidian/assets/fonts/Open_Sans/static/OpenSans-Medium.ttf").
This won't work well for me, because I want to have the font fully loaded before the game starts (I'm using bevy_asset_loader)
EDIT: It looks like even when passing it as dep with style_dyn you still need to call .clone() on the resource or you'll get a lifetime error.
To clarify, this is what my resource looks like:
#[derive(AssetCollection, Clone, Resource, PartialEq, PartialOrd, Eq)]
pub struct MyAssets {
#[asset(path = "foobar.png")]
pub foobar: Handle<Image>,
// ...and tens of other asset fields
}
I wonder if there's a more efficient approach that avoids cloning.
Ok, I figured it out:
#[derive(Clone, PartialEq)]
pub struct MyUi;
impl ViewTemplate for MyUi {
type View = impl View;
fn create(&self, cx: &mut Cx) -> Self::View {
let font_assets = cx.use_resource::<MyFontAssets>();
let font = font_assets.comic_sans.clone();
Element::<NodeBundle>::new().style(move |ss: &mut StyleBuilder| {
ss.font(font.clone()); // <- you need to clone it so that the closure becomes `Fn`
// See: https://doc.rust-lang.org/std/keyword.move.html
})
}
}
It seems that this is more of a Rust issue, so I think I'll close this. But before that, would it be possible for .style() and other callbacks to be a FnOnce instead? Do they need to be called multiple times?
FnOnce: Certainly worth investigating.