-
-
Notifications
You must be signed in to change notification settings - Fork 492
/
Copy pathComposition.CompositionDevice.cpp
126 lines (104 loc) · 3.51 KB
/
Composition.CompositionDevice.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "pch.h"
#include "Composition.CompositionDevice.h"
#include "Composition.DirectRectangleClip.h"
namespace winrt::Telegram::Native::Composition::implementation
{
winrt::slim_mutex CompositionDevice::s_lock;
winrt::com_ptr<CompositionDevice> CompositionDevice::s_current{ nullptr };
CompositionDevice::CompositionDevice() {
HRESULT hr = ::CoCreateInstance(
CLSID_UIAnimationManager2,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IUIAnimationManager2,
reinterpret_cast<LPVOID*>(&_manager));
if (SUCCEEDED(hr)) {
hr = ::CoCreateInstance(
CLSID_UIAnimationTransitionLibrary2,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IUIAnimationTransitionLibrary2,
reinterpret_cast<LPVOID*>(&_transitionLibrary));
}
}
winrt::Telegram::Native::Composition::DirectRectangleClip CompositionDevice::CreateRectangleClip(Visual visual)
{
HRESULT hr;
auto compositor = visual.Compositor();
auto device = compositor.as<IDCompositionDesktopDevice>();
winrt::com_ptr<IDCompositionRectangleClip> clip;
hr = device->CreateRectangleClip(clip.put());
auto abi = visual.as<IDCompositionVisual2>();
hr = abi->SetClip(clip.get());
auto result = winrt::make_self<implementation::DirectRectangleClip>(clip);
return *result;
}
HRESULT CompositionDevice::CreateCubicBezierAnimation(Compositor compositor, float from, float to, double duration, IDCompositionAnimation** slideAnimation)
{
HRESULT hr = (slideAnimation == nullptr) ? E_POINTER : S_OK;
auto device = compositor.as<IDCompositionDesktopDevice>();
if (SUCCEEDED(hr))
{
*slideAnimation = nullptr;
}
//WAM propagates curves to DirectComposition using the IDCompositionAnimation object
winrt::com_ptr<IDCompositionAnimation> animation;
if (SUCCEEDED(hr))
{
hr = device->CreateAnimation(animation.put());
}
//Create a storyboard for the slide animation
winrt::com_ptr<IUIAnimationStoryboard2> storyboard;
if (SUCCEEDED(hr))
{
hr = _manager->CreateStoryboard(storyboard.put());
}
// Synchronizing WAM and DirectComposition time such that when WAM Update is called,
// the value reflects the DirectComposition value at the given time.
DCOMPOSITION_FRAME_STATISTICS frameStatistics = { 0 };
if (SUCCEEDED(hr))
{
hr = device->GetFrameStatistics(&frameStatistics);
}
UI_ANIMATION_SECONDS nextEstimatedFrameTime = 0.0;
if (SUCCEEDED(hr))
{
nextEstimatedFrameTime = static_cast<double>(frameStatistics.nextEstimatedFrameTime.QuadPart) / static_cast<double>(frameStatistics.timeFrequency.QuadPart);
}
//Upating the WAM time
if (SUCCEEDED(hr))
{
hr = _manager->Update(nextEstimatedFrameTime);
}
winrt::com_ptr<IUIAnimationVariable2> animationVariable;
if (SUCCEEDED(hr))
{
hr = _manager->CreateAnimationVariable(from, animationVariable.put());
}
winrt::com_ptr<IUIAnimationTransition2> transition;
if (SUCCEEDED(hr))
{
hr = _transitionLibrary->CreateCubicBezierLinearTransition(duration, to, .41F, .51999998F, .00F, .94F, transition.put());
}
//Add above transition to storyboard
if (SUCCEEDED(hr))
{
hr = storyboard->AddTransition(animationVariable.get(), transition.get());
}
//schedule the storyboard for play at the next estimate vblank
if (SUCCEEDED(hr))
{
hr = storyboard->Schedule(nextEstimatedFrameTime);
}
//Giving WAM varialbe the IDCompositionAnimation object to receive the animation curves
if (SUCCEEDED(hr))
{
hr = animationVariable->GetCurve(animation.get());
}
if (SUCCEEDED(hr))
{
*slideAnimation = animation.detach();
}
return hr;
}
}