Commit 5d5e3f9
This allows easier conditional behavior without having to resort to
`Box<dyn Scene>` with an empty `bsn!{}` in the negative case.
# Objective
While designing custom widgets and extra scene tooling I have found
several cases where I would like to optionally include a set of
components.
Right now (as best I can tell) this requires constructing a `Box<dyn
Scene>` which either has the components, or is an empty scene
(`bsn!{}`).
Every time I try to do this, I always first end up with a type error
that the `if` and `else` branches don't have matching types.
This is fixable, but prone to mistakes.
Allowing `Option<P: Scene>` is much simpler, and doesn't require
allocations.
## Solution
Allow `Option<P: Scene>` to be a `Scene` which optionally resolves the
contained scene.
## Testing
I have been using a new-typed version of this implementation
(`ConditionalScene<P>(Option<P>)`) in my own personal widget library to
get around Orphan rules.
I added a simple `#[test]` to the `bevy_scene` test suite.
---
## Showcase
I put together an example widget for a "PullQuote" which can optionally
use the inherited font from the parent, or use a larger font by default.
<details>
<summary>Click to view showcase</summary>
```rust
use bevy::{
feathers::{
FeathersPlugins,
constants::{fonts, size},
dark_theme::create_dark_theme,
font_styles::InheritableFont,
theme::{ThemeBorderColor, ThemedText, UiTheme},
tokens,
},
prelude::*,
};
fn main() {
App::new()
.add_plugins((DefaultPlugins, FeathersPlugins))
.insert_resource(UiTheme(create_dark_theme()))
.add_systems(Startup, scene.spawn())
.run();
}
fn scene() -> impl SceneList {
bsn_list!(Camera2d, ui())
}
#[derive(SceneComponent, Default, Clone)]
#[scene(PullQuoteProps)]
pub struct PullQuote;
pub struct PullQuoteProps {
/// Set a specific font for the Pull Quote body elements using `ThemedText`, otherwise inherit the font from the outer context
pub use_quote_font: bool,
}
impl Default for PullQuoteProps {
fn default() -> Self {
Self {
use_quote_font: true,
}
}
}
impl PullQuote {
fn scene(props: PullQuoteProps) -> impl Scene {
let quote_font = props.use_quote_font.then(|| {
bsn! {
InheritableFont {
font: fonts::REGULAR,
font_size: px(24),
weight: FontWeight::NORMAL,
}
}
});
bsn! {
Node {
border: px(1),
padding: UiRect::horizontal(px(4)),
}
ThemeBorderColor(tokens::SUBPANE_HEADER_BORDER)
{quote_font}
ThemedText // Propagate text theme even if quote font isn't used
}
}
}
fn ui() -> impl Scene {
bsn! {
Node {
flex_direction: FlexDirection::Column,
padding: px(8),
row_gap: px(2),
}
InheritableFont {
font: fonts::REGULAR,
font_size: size::MEDIUM_FONT,
weight: FontWeight::NORMAL,
}
Children [
Text("Inherited Font") ThemedText,
@PullQuote
Children [
Text("A Big Quote!") ThemedText
],
@PullQuote {
@use_quote_font: false
}
Children [
Text("A Quote using the inherited font!") ThemedText
]
]
}
}
```
</details>
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: Daniel Skates <zeophlite@gmail.com>
1 parent 79d3afe commit 5d5e3f9
2 files changed
Lines changed: 36 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2202 | 2202 | | |
2203 | 2203 | | |
2204 | 2204 | | |
| 2205 | + | |
| 2206 | + | |
| 2207 | + | |
| 2208 | + | |
| 2209 | + | |
| 2210 | + | |
| 2211 | + | |
| 2212 | + | |
| 2213 | + | |
| 2214 | + | |
| 2215 | + | |
| 2216 | + | |
| 2217 | + | |
| 2218 | + | |
| 2219 | + | |
| 2220 | + | |
| 2221 | + | |
| 2222 | + | |
| 2223 | + | |
| 2224 | + | |
| 2225 | + | |
2205 | 2226 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
211 | 211 | | |
212 | 212 | | |
213 | 213 | | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
214 | 229 | | |
215 | 230 | | |
216 | 231 | | |
| |||
0 commit comments