AnimatedVisualPlayer¶
Header: winui/ui/media/AnimatedVisualPlayer.hpp. Spec: winui/ui/media/AnimatedVisualPlayer.hpp.
Plays a caller-supplied AnimatedVisualSource by advancing its progress over time and drawing each frame with the source's render_frame().
With auto_play() on (the default), a newly loaded source starts looping from 0 to 1 at once. Otherwise the app calls play(), pause(), resume(), stop() or set_progress(). A play from from to to lasts duration() * (to - from), scaled by playback_rate() while it runs. A negative rate plays backwards. The source is fitted into the player's bounds as stretch() says. When the source can't be shown (its available() is false), the fallback content takes its place. The player doesn't own the source, so it must outlive the player.
A play keeps running in real time while the player is off screen, scrolled out of view or clipped away, but nothing is drawn and the window isn't kept busy for it. Back on screen, the player shows the progress the play has reached by then, with a looped play wrapped around. A play that ends off screen still completes on time.
Example:
// A source drawing a circle that grows over one second.
struct Pulse final : ui::AnimatedVisualSource
{
ui::Size natural_size() const override { return {48.0f, 48.0f}; }
ui::Duration duration() const override { return ui::Duration{1000.0}; }
void render_frame(ui::Renderer& r, const ui::Rect& b, double progress) const override
{
const float radius = static_cast<float>(progress) * b.width / 2.0f;
r.fill_ellipse(b.center(), radius, radius, ui::colors::Black);
}
};
static const Pulse pulse; // outlives every player showing it
ui::Control<ui::AnimatedVisualPlayer> player;
window.set_content(ui::VerticalStack{
.content = {
ui::AnimatedVisualPlayer{.source = &pulse, .auto_play = false, .width = 96.0f,
.height = 96.0f, .control = player,
.fallback_content = ui::Text{.text = "(no animation)"}},
ui::Button{.text = "Play once", .on_click = [&] { player->play(0.0, 1.0, false); }},
ui::Button{.text = "Pause", .on_click = [&] { player->pause(); }},
},
});
ui::AnimatedVisualPlayer¶
A player for a caller-supplied AnimatedVisualSource (render/AnimatedVisualSource.hpp). Builds a ui::AnimatedVisualPlayerControl.
source is a non-owning pointer, so the AnimatedVisualSource must outlive the built control. Changing the source, through a binding or set_source() on the control, stops the player. fallback_content shows instead when the source can't be shown.
Example:
extern const ui::AnimatedVisualSource& logo; // the app's own subclass, alive as long as the window
ui::Control<ui::AnimatedVisualPlayer> player;
window.set_content(ui::VerticalStack{.spacing = 8, .content = {
ui::AnimatedVisualPlayer{.source = &logo,
.auto_play = false,
.width = 400.0f,
.height = 400.0f,
.control = player,
.fallback_content = ui::Text{.text = "Animation unavailable"}},
ui::HorizontalStack{.spacing = 8, .content = {
ui::Button{.text = "Play", .on_click = [&] { player->play(0.0, 1.0, true); }},
ui::Button{.text = "Pause", .on_click = [&] { player->pause(); }},
ui::Button{.text = "Stop", .on_click = [&] { player->stop(); }},
}},
}});
Every field, in the order a designated initializer names them:
ui::AnimatedVisualPlayer{
.source, .auto_play, .playback_rate, .stretch, .style, .margin, .width, .height,
.min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
.vertical_alignment, .visible, .tool_tip, .accessibility, .on_pointer_entered,
.on_pointer_exited, .on_got_focus, .on_lost_focus, .on_key_down, .on_wheel, .control,
.fallback_content
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
source |
ui::Binding<const ui::AnimatedVisualSource*> |
The animation. Not owned, so it must outlive the built control. | |
auto_play |
ui::Binding<bool> |
{true} |
Whether the whole animation loops as soon as the source loads. |
playback_rate |
ui::Binding<double> |
{1.0} |
Playback speed. 1 is normal speed, and a negative rate plays backwards. |
stretch |
ui::Binding<ui::Stretch> |
{ui::Stretch::Uniform} |
How the animation fills the player's box. |
on_pointer_entered |
ui::Action |
The pointer moved onto the control. | |
on_pointer_exited |
ui::Action |
The pointer left the control. | |
on_got_focus |
ui::Action |
Keyboard focus arrived on the control, or on anything inside it, from outside it. A control with nothing focusable in it never gets focus, and never raises this. | |
on_lost_focus |
ui::Action |
Keyboard focus left the control and everything inside it. | |
on_key_down |
ui::Callback<ui::Handling(const ui::KeyEvent&)> |
A key pressed while focus is on the control or inside it, before the control's own handling; ui::Handled stops it there (Element::on_key_down()). | |
on_wheel |
ui::Callback<ui::Handling(const ui::PointerEvent&)> |
A wheel turn over the control, before the control scrolls; ui::Handled stops it there (Element::on_wheel()). | |
control |
ui::ControlOut<ui::AnimatedVisualPlayer> |
Out: the handle that receives the built control. | |
fallback_content |
ui::Spec |
Shown instead of the animation when the source can't be shown. |
Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, accessibility every spec carries (conventions).
build¶
Consumes the spec and returns the built ui::AnimatedVisualPlayerControl; the caller owns it.
ui::AnimatedVisualPlayerControl¶
Derives from ui::Panel.
Plays a caller-supplied AnimatedVisualSource by advancing its progress over time and drawing each frame with the source's render_frame().
With auto_play() on (the default), a newly loaded source starts looping from 0 to 1 at once. Otherwise the app calls play(), pause(), resume(), stop() or set_progress(). A play from from to to lasts duration() * (to - from), scaled by playback_rate() while it runs. A negative rate plays backwards. The source is fitted into the player's bounds as stretch() says. When the source can't be shown (its available() is false), the fallback content takes its place. The player doesn't own the source, so it must outlive the player.
A play keeps running in real time while the player is off screen, scrolled out of view or clipped away, but nothing is drawn and the window isn't kept busy for it. Back on screen, the player shows the progress the play has reached by then, with a looped play wrapped around. A play that ends off screen still completes on time.
Example:
// A source drawing a circle that grows over one second.
struct Pulse final : ui::AnimatedVisualSource
{
ui::Size natural_size() const override { return {48.0f, 48.0f}; }
ui::Duration duration() const override { return ui::Duration{1000.0}; }
void render_frame(ui::Renderer& r, const ui::Rect& b, double progress) const override
{
const float radius = static_cast<float>(progress) * b.width / 2.0f;
r.fill_ellipse(b.center(), radius, radius, ui::colors::Black);
}
};
static const Pulse pulse; // outlives every player showing it
ui::Control<ui::AnimatedVisualPlayer> player;
window.set_content(ui::VerticalStack{
.content = {
ui::AnimatedVisualPlayer{.source = &pulse, .auto_play = false, .width = 96.0f,
.height = 96.0f, .control = player,
.fallback_content = ui::Text{.text = "(no animation)"}},
ui::Button{.text = "Play once", .on_click = [&] { player->play(0.0, 1.0, false); }},
ui::Button{.text = "Pause", .on_click = [&] { player->pause(); }},
},
});
AnimatedVisualPlayerControl¶
A player with no source: auto-play on, rate 1, Uniform stretch.
source¶
The source being played, or null.
set_source¶
Sets the source to play. The player doesn't own it, so the source must outlive the player. Replacing the source stops whatever was playing, and auto-play then starts on the new one. nullptr unloads it. Shows or hides the fallback content as the source's available() says.
is_animated_visual_loaded¶
A source is set, available and has a size.
set_fallback_content¶
Sets what shows instead when the source can't be shown. Takes ownership, returns a non-owning observer and replaces any earlier fallback.
fallback_content¶
The fallback content (whether or not it is showing), or null if none was set.
is_fallen_back¶
Whether the fallback content is what is showing.
auto_play¶
Whether a loaded source starts looping 0..1 on its own. Default true.
set_auto_play¶
Turns auto-play on or off. Turning it on while a source is loaded and nothing plays starts the looping play at once.
playback_rate¶
How fast plays run, 1 by default. A negative rate plays backwards.
set_playback_rate¶
Sets the playback rate. A running play speeds up, slows down or reverses at once.
stretch¶
How the source's natural size fits the player's bounds. Uniform by default.
set_stretch¶
Sets the stretch. Updates layout and redraws.
is_playing¶
Whether a play has started and not completed. A paused play counts as playing.
is_paused¶
Whether the current play is paused.
progress¶
The current position in the animation, from 0 to 1.
duration¶
0 until a source is loaded, then the source's duration().
play¶
Completes any play in progress, rewinding it, then plays from from_progress to to_progress, repeating forever when looped is true. Without a loaded source the play waits and doesn't start, and setting a source cancels it.
pause¶
Pauses the current play where it is. Does nothing when nothing is playing.
resume¶
Continues a paused play. Does nothing when nothing is playing.
stop¶
Completes the current play and rewinds progress() to 0. Does nothing when nothing is playing.
set_progress¶
Completes any play and jumps to progress, clamped to [0,1].
on_screen_changed¶
When the player comes back on screen, draws the progress the play reached while away.
automation_role¶
Exposed to UI Automation as an image.
measure_override¶
Fits the source's natural size into available as stretch() says, or measures the fallback.
arrange_override¶
Arranges the fallback content when it is showing.
render_override¶
Draws the source's frame at progress(), clipped for UniformToFill, or draws the fallback.
tick_override¶
Advances the current play by delta * playback_rate(), and completes or loops it at its ends. Off screen it draws nothing and keeps the window idle, and a play that ends there still completes on time.
Tests¶
tests/test_animated_visual_player.cpp