-
Notifications
You must be signed in to change notification settings - Fork 675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added new AVP::AnimationOptimization property #6269
Changes from 1 commit
19ba938
5092403
6c3d3d8
46afdcd
4edad8e
5bcd360
9186ad7
2379dd7
2e7b4c8
601d778
977005a
36f65b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,10 @@ void AnimatedVisualPlayer::AnimationPlay::Start() | |
MUX_ASSERT(m_owner); | ||
MUX_ASSERT(!m_controller); | ||
|
||
// Set lastPlayProgress to fromProgress. | ||
// When we call Stop() root progress will be set to lastPlayProgress. | ||
m_owner->m_lastPlayProgress = m_fromProgress; | ||
|
||
// If the duration is really short (< 20ms) don't bother trying to animate. | ||
if (m_playDuration < winrt::TimeSpan{ 20ms }) | ||
{ | ||
|
@@ -117,6 +121,18 @@ void AnimatedVisualPlayer::AnimationPlay::Start() | |
// Subscribe to the batch completed event. | ||
m_batchCompletedToken = m_batch.Completed([this](winrt::IInspectable const&, winrt::CompositionBatchCompletedEventArgs const&) | ||
{ | ||
if (m_owner) | ||
{ | ||
// If currentPlay completed succesfully, set lastPlayProgress to toProgress. | ||
m_owner->m_lastPlayProgress = m_toProgress; | ||
|
||
// If cache mode is set to None - destroy animations immediately after player stops. | ||
if (m_owner->AnimationsCacheMode() == winrt::AnimationsCacheModeEnum::None) | ||
{ | ||
m_owner->DestroyAnimations(); | ||
} | ||
} | ||
|
||
// Complete the play when the batch completes. | ||
// | ||
// The "this" pointer is guaranteed to be valid because: | ||
|
@@ -622,12 +638,20 @@ winrt::IAsyncAction AnimatedVisualPlayer::PlayAsync(double fromProgress, double | |
co_return; | ||
} | ||
|
||
// Make sure that animations are instantiated. | ||
InstantiateAnimations(); | ||
|
||
// Used to detect reentrance. | ||
const auto version = ++m_playAsyncVersion; | ||
|
||
// Cause any other plays to return. | ||
// Complete m_nowPlaying if it is still running. | ||
// Identical to Stop() call but without destroying the animations. | ||
// WARNING - this call may cause reentrance via the IsPlaying DP. | ||
Stop(); | ||
if (m_nowPlaying) | ||
{ | ||
m_progressPropertySet.InsertScalar(L"Progress", static_cast<float>(m_lastPlayProgress)); | ||
m_nowPlaying->Complete(); | ||
} | ||
|
||
if (version != m_playAsyncVersion) | ||
{ | ||
|
@@ -707,13 +731,17 @@ void AnimatedVisualPlayer::SetProgress(double progress) | |
return; | ||
} | ||
|
||
// Make sure that animations are instantiated. | ||
InstantiateAnimations(); | ||
|
||
auto clampedProgress = std::clamp(static_cast<float>(progress), 0.0F, 1.0F); | ||
|
||
// WARNING: Reentrance via IsPlaying DP may occur from this point down to the end of the method | ||
// iff m_nowPlaying. | ||
|
||
// Setting the Progress value will stop the current play. | ||
m_progressPropertySet.InsertScalar(L"Progress", static_cast<float>(clampedProgress)); | ||
m_lastPlayProgress = progress; | ||
|
||
// Ensure the current PlayAsync task is completed. | ||
// Note that this explicit call is necessary, even though InsertScalar | ||
|
@@ -725,6 +753,11 @@ void AnimatedVisualPlayer::SetProgress(double progress) | |
{ | ||
m_nowPlaying->Complete(); | ||
} | ||
|
||
// If cache mode is set to None - destroy annimations immediately. | ||
if (AnimationsCacheMode() == winrt::AnimationsCacheModeEnum::None) { | ||
DestroyAnimations(); | ||
} | ||
} | ||
|
||
// Public API. | ||
|
@@ -736,7 +769,7 @@ void AnimatedVisualPlayer::Stop() | |
// Stop the animation by setting the Progress value to the fromProgress of the | ||
// most recent play. | ||
// This may cause reentrance via the IsPlaying DP. | ||
SetProgress(m_currentPlayFromProgress); | ||
SetProgress(m_lastPlayProgress); | ||
} | ||
} | ||
|
||
|
@@ -755,6 +788,66 @@ void AnimatedVisualPlayer::OnAutoPlayPropertyChanged( | |
} | ||
} | ||
|
||
void AnimatedVisualPlayer::OnAnimationsCacheModePropertyChanged( | ||
winrt::DependencyPropertyChangedEventArgs const& args) | ||
{ | ||
auto cacheMode = unbox_value<winrt::AnimationsCacheModeEnum>(args.NewValue()); | ||
|
||
if (m_nowPlaying) | ||
{ | ||
// If there is something in play right now we should not instantiate/destroy animations. | ||
return; | ||
} | ||
|
||
if (cacheMode == winrt::AnimationsCacheModeEnum::None) | ||
{ | ||
DestroyAnimations(); | ||
} | ||
else if (cacheMode == winrt::AnimationsCacheModeEnum::Always) | ||
{ | ||
InstantiateAnimations(); | ||
} | ||
} | ||
|
||
void AnimatedVisualPlayer::InstantiateAnimations() { | ||
if (m_isAnimationsCached) | ||
{ | ||
return; | ||
} | ||
|
||
// Check if current animated visual supports instantiating animations and create them. | ||
if (const auto& animatedVisual = m_animatedVisual.get()) | ||
{ | ||
if (const auto& animatedVisual2 = m_animatedVisual.try_as<winrt::IAnimatedVisual2>()) | ||
{ | ||
animatedVisual2.InstantiateAnimations(m_lastPlayProgress); | ||
m_isAnimationsCached = true; | ||
} | ||
} | ||
} | ||
|
||
void AnimatedVisualPlayer::DestroyAnimations() { | ||
if (!m_isAnimationsCached) | ||
{ | ||
return; | ||
} | ||
|
||
// Call RequestCommit to make sure that previous compositor calls complete before destroying animations. | ||
m_rootVisual.Compositor().RequestCommitAsync().Completed( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RequestCommitAsync() is only available on Rs4+ we need to gracefully handle the case where this API isn't available on RS2 and RS3. |
||
[&](auto, auto) { | ||
// Check if current animated visual supports destroyig animations. | ||
if (const auto& animatedVisual = m_animatedVisual.get()) | ||
{ | ||
if (const auto& animatedVisual2 = m_animatedVisual.try_as<winrt::IAnimatedVisual2>()) | ||
{ | ||
animatedVisual2.DestroyAnimations(); | ||
m_isAnimationsCached = false; | ||
} | ||
} | ||
} | ||
); | ||
} | ||
|
||
void AnimatedVisualPlayer::OnFallbackContentPropertyChanged( | ||
winrt::DependencyPropertyChangedEventArgs const& args) | ||
{ | ||
|
@@ -845,7 +938,18 @@ void AnimatedVisualPlayer::UpdateContent() | |
} | ||
|
||
winrt::IInspectable diagnostics{}; | ||
auto animatedVisual = source.TryCreateAnimatedVisual(m_rootVisual.Compositor(), diagnostics); | ||
winrt::IAnimatedVisual animatedVisual; | ||
if (auto source3 = source.try_as<winrt::IAnimatedVisualSource3>()) | ||
{ | ||
bool instantiateAnimations = AnimationsCacheMode() == winrt::AnimationsCacheModeEnum::Always; | ||
animatedVisual = source3.TryCreateAnimatedVisual(m_rootVisual.Compositor(), instantiateAnimations, diagnostics); | ||
m_isAnimationsCached = instantiateAnimations; | ||
} | ||
else | ||
{ | ||
animatedVisual = source.TryCreateAnimatedVisual(m_rootVisual.Compositor(), diagnostics); | ||
m_isAnimationsCached = true; | ||
} | ||
m_animatedVisual.set(animatedVisual); | ||
|
||
if (!animatedVisual) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,14 @@ interface IAnimatedVisual | |
Windows.Foundation.TimeSpan Duration{ get; }; | ||
}; | ||
|
||
[MUX_PREVIEW] | ||
[webhosthidden] | ||
interface IAnimatedVisual2 requires IAnimatedVisual | ||
{ | ||
void InstantiateAnimations(Double progressHint); | ||
void DestroyAnimations(); | ||
}; | ||
|
||
[MUX_PUBLIC] | ||
[webhosthidden] | ||
interface IAnimatedVisualSource | ||
|
@@ -28,6 +36,16 @@ interface IDynamicAnimatedVisualSource | |
event Windows.Foundation.TypedEventHandler<IDynamicAnimatedVisualSource, Object> AnimatedVisualInvalidated; | ||
}; | ||
|
||
[MUX_PREVIEW] | ||
[webhosthidden] | ||
interface IAnimatedVisualSource3 | ||
{ | ||
IAnimatedVisual2 TryCreateAnimatedVisual( | ||
Windows.UI.Composition.Compositor compositor, | ||
Boolean instantiateAnimations, | ||
out Object diagnostics); | ||
}; | ||
|
||
[MUX_INTERNAL] | ||
[webhosthidden] | ||
interface ISelfPlayingAnimatedVisual | ||
|
@@ -43,6 +61,14 @@ interface ISelfPlayingAnimatedVisual | |
void SetSize(Windows.Foundation.Size size); | ||
}; | ||
|
||
[MUX_PUBLIC] | ||
[webhosthidden] | ||
enum AnimationsCacheModeEnum | ||
{ | ||
None, | ||
Always | ||
}; | ||
|
||
[MUX_PUBLIC] | ||
[webhosthidden] | ||
[contentproperty("Source")] | ||
|
@@ -62,6 +88,9 @@ unsealed runtimeclass AnimatedVisualPlayer | |
[MUX_DEFAULT_VALUE("true")] | ||
[MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] | ||
Boolean AutoPlay; | ||
[MUX_DEFAULT_VALUE("winrt::AnimationsCacheModeEnum::Always")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You would need to version these APIs since you are adding to an existing type. See MUX_PUBLIC_V2 to see how it is done in other types. @kmahone as FYI There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, done |
||
[MUX_PROPERTY_CHANGED_CALLBACK(TRUE)] | ||
AnimationsCacheModeEnum AnimationsCacheMode; | ||
Boolean IsAnimatedVisualLoaded{ get; }; | ||
Boolean IsPlaying{ get; }; | ||
[MUX_DEFAULT_VALUE("1")] | ||
|
@@ -82,6 +111,7 @@ unsealed runtimeclass AnimatedVisualPlayer | |
|
||
// Dependency properties | ||
static Windows.UI.Xaml.DependencyProperty AutoPlayProperty{ get; }; | ||
static Windows.UI.Xaml.DependencyProperty AnimationsCacheModeProperty{ get; }; | ||
static Windows.UI.Xaml.DependencyProperty DiagnosticsProperty{ get; }; | ||
static Windows.UI.Xaml.DependencyProperty DurationProperty{ get; }; | ||
static Windows.UI.Xaml.DependencyProperty FallbackContentProperty{ get; }; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_lastPlayProgress will be clamped later when it is used? (i.e. in stop?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, probably it is better to set it to
clampedProgress
here, thx