This repository was archived by the owner on Feb 25, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathCompositionExtensions.cs
More file actions
308 lines (275 loc) · 14.4 KB
/
CompositionExtensions.cs
File metadata and controls
308 lines (275 loc) · 14.4 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Composition;
using Windows.UI.Composition.Interactions;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Expressions
{
/// <summary>
/// Class CompositionExtensions.
/// </summary>
public static class CompositionExtensions
{
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>AmbientLightReferenceNode.</returns>
public static AmbientLightReferenceNode GetReference(this AmbientLight compObj)
{
return new AmbientLightReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>ColorBrushReferenceNode.</returns>
public static ColorBrushReferenceNode GetReference(this CompositionColorBrush compObj)
{
return new ColorBrushReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>DistantLightReferenceNode.</returns>
public static DistantLightReferenceNode GetReference(this DistantLight compObj)
{
return new DistantLightReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>DropShadowReferenceNode.</returns>
public static DropShadowReferenceNode GetReference(this DropShadow compObj)
{
return new DropShadowReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>InsetClipReferenceNode.</returns>
public static InsetClipReferenceNode GetReference(this InsetClip compObj)
{
return new InsetClipReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>InteractionTrackerReferenceNode.</returns>
public static InteractionTrackerReferenceNode GetReference(this InteractionTracker compObj)
{
return new InteractionTrackerReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>NineGridBrushReferenceNode.</returns>
public static NineGridBrushReferenceNode GetReference(this CompositionNineGridBrush compObj)
{
return new NineGridBrushReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>PointLightReferenceNode.</returns>
public static PointLightReferenceNode GetReference(this PointLight compObj)
{
return new PointLightReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>PropertySetReferenceNode.</returns>
public static PropertySetReferenceNode GetReference(this CompositionPropertySet compObj)
{
return new PropertySetReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>SpotLightReferenceNode.</returns>
public static SpotLightReferenceNode GetReference(this SpotLight compObj)
{
return new SpotLightReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>SurfaceBrushReferenceNode.</returns>
public static SurfaceBrushReferenceNode GetReference(this CompositionSurfaceBrush compObj)
{
return new SurfaceBrushReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this CompositionObject.
/// </summary>
/// <param name="compObj">The comp object.</param>
/// <returns>VisualReferenceNode.</returns>
public static VisualReferenceNode GetReference(this Visual compObj)
{
return new VisualReferenceNode(null, compObj);
}
/// <summary>
/// Create an ExpressionNode reference to this specialized PropertySet.
/// </summary>
/// <typeparam name="T">A class that derives from PropertySetReferenceNode.</typeparam>
/// <param name="ps">The ps.</param>
/// <returns>T.</returns>
/// <exception cref="System.Exception">Invalid property set specialization</exception>
public static T GetSpecializedReference<T>(this CompositionPropertySet ps)
where T : PropertySetReferenceNode
{
if (typeof(T) == typeof(ManipulationPropertySetReferenceNode))
{
return new ManipulationPropertySetReferenceNode(null, ps) as T;
}
else if (typeof(T) == typeof(PointerPositionPropertySetReferenceNode))
{
return new PointerPositionPropertySetReferenceNode(null, ps) as T;
}
else
{
throw new System.Exception("Invalid property set specialization");
}
}
/// <summary>
/// Connects the specified ExpressionNode with the specified property of the object.
/// </summary>
/// <param name="compObject">The comp object.</param>
/// <param name="propertyName">The name of the property that the expression will target.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void StartAnimation(this CompositionObject compObject, string propertyName, ExpressionNode expressionNode)
{
compObject.StartAnimation(propertyName, CreateExpressionAnimationFromNode(compObject.Compositor, expressionNode));
}
/// <summary>
/// Inserts a KeyFrame whose value is calculated using the specified ExpressionNode.
/// </summary>
/// <param name="keyframeAnimation">The keyframe animation.</param>
/// <param name="normalizedProgressKey">The time the key frame should occur at, expressed as a percentage of the animation Duration. Allowed value is from 0.0 to 1.0.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
/// <param name="easing">The easing function to use when interpolating between frames.</param>
public static void InsertExpressionKeyFrame(this KeyFrameAnimation keyframeAnimation, float normalizedProgressKey, ExpressionNode expressionNode, CompositionEasingFunction easing = null)
{
expressionNode.ClearReferenceInfo();
keyframeAnimation.InsertExpressionKeyFrame(normalizedProgressKey, expressionNode.ToExpressionString(), easing);
expressionNode.SetAllParameters(keyframeAnimation);
}
/// <summary>
/// Use the value of specified ExpressionNode to determine if this inertia modifier should be chosen.
/// </summary>
/// <param name="modifier">The modifier.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void SetCondition(this InteractionTrackerInertiaRestingValue modifier, ExpressionNode expressionNode)
{
modifier.Condition = CreateExpressionAnimationFromNode(modifier.Compositor, expressionNode);
}
/// <summary>
/// Use the value of specified ExpressionNode as the resting value for this inertia modifier.
/// </summary>
/// <param name="modifier">The modifier.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void SetRestingValue(this InteractionTrackerInertiaRestingValue modifier, ExpressionNode expressionNode)
{
modifier.RestingValue = CreateExpressionAnimationFromNode(modifier.Compositor, expressionNode);
}
/// <summary>
/// Use the value of specified ExpressionNode to determine if this inertia modifier should be chosen.
/// </summary>
/// <param name="modifier">The modifier.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void SetCondition(this InteractionTrackerInertiaMotion modifier, ExpressionNode expressionNode)
{
modifier.Condition = CreateExpressionAnimationFromNode(modifier.Compositor, expressionNode);
}
/// <summary>
/// Use the value of specified ExpressionNode to dictate the motion for this inertia modifier.
/// </summary>
/// <param name="modifier">The modifier.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void SetMotion(this InteractionTrackerInertiaMotion modifier, ExpressionNode expressionNode)
{
modifier.Motion = CreateExpressionAnimationFromNode(modifier.Compositor, expressionNode);
}
/// <summary>
/// Use the value of specified ExpressionNode to determine if this composition conditional value modifier should be chosen.
/// </summary>
/// <param name="modifier">The modifier.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void SetCondition(this CompositionConditionalValue modifier, ExpressionNode expressionNode)
{
modifier.Condition = CreateExpressionAnimationFromNode(modifier.Compositor, expressionNode);
}
/// <summary>
/// Use the value of specified ExpressionNode as the value for this composition conditional value
/// </summary>
/// <param name="modifier">The modifier.</param>
/// <param name="expressionNode">The root ExpressionNode that represents the ExpressionAnimation.</param>
public static void SetValue(this CompositionConditionalValue modifier, ExpressionNode expressionNode)
{
modifier.Value = CreateExpressionAnimationFromNode(modifier.Compositor, expressionNode);
}
/// <summary>
/// Creates the expression animation from node.
/// </summary>
/// <param name="compositor">The compositor.</param>
/// <param name="expressionNode">The expression node.</param>
/// <returns>ExpressionAnimation.</returns>
private static ExpressionAnimation CreateExpressionAnimationFromNode(Compositor compositor, ExpressionNode expressionNode)
{
// Only create a new animation if this node hasn't already generated one before, so we don't have to re-parse the expression string.
if (expressionNode.ExpressionAnimation == null)
{
expressionNode.ClearReferenceInfo();
expressionNode.ExpressionAnimation = compositor.CreateExpressionAnimation(expressionNode.ToExpressionString());
}
// We need to make sure all parameters are up to date, even if the animation already existed.
expressionNode.SetAllParameters(expressionNode.ExpressionAnimation);
return expressionNode.ExpressionAnimation;
}
internal static float EvaluateSubchannel(this ExpressionNode node, string subchannel) => (node, subchannel) switch
{
(Vector2Node n, "X") => n.Evaluate().X,
(Vector2Node n, "Y") => n.Evaluate().Y,
(Vector3Node n, "X") => n.Evaluate().X,
(Vector3Node n, "Y") => n.Evaluate().Y,
(Vector3Node n, "Z") => n.Evaluate().Z,
(Vector4Node n, "X") => n.Evaluate().X,
(Vector4Node n, "Y") => n.Evaluate().Y,
(Vector4Node n, "Z") => n.Evaluate().Z,
(Vector4Node n, "W") => n.Evaluate().W,
(Matrix3x2Node n, "Channel11") => n.Evaluate().M11,
(Matrix3x2Node n, "Channel12") => n.Evaluate().M12,
(Matrix3x2Node n, "Channel21") => n.Evaluate().M21,
(Matrix3x2Node n, "Channel22") => n.Evaluate().M22,
(Matrix3x2Node n, "Channel31") => n.Evaluate().M31,
(Matrix3x2Node n, "Channel32") => n.Evaluate().M32,
(Matrix4x4Node n, "Channel11") => n.Evaluate().M11,
(Matrix4x4Node n, "Channel12") => n.Evaluate().M12,
(Matrix4x4Node n, "Channel13") => n.Evaluate().M13,
(Matrix4x4Node n, "Channel14") => n.Evaluate().M14,
(Matrix4x4Node n, "Channel21") => n.Evaluate().M21,
(Matrix4x4Node n, "Channel22") => n.Evaluate().M22,
(Matrix4x4Node n, "Channel23") => n.Evaluate().M23,
(Matrix4x4Node n, "Channel24") => n.Evaluate().M24,
(Matrix4x4Node n, "Channel31") => n.Evaluate().M31,
(Matrix4x4Node n, "Channel32") => n.Evaluate().M32,
(Matrix4x4Node n, "Channel33") => n.Evaluate().M33,
(Matrix4x4Node n, "Channel34") => n.Evaluate().M34,
(Matrix4x4Node n, "Channel41") => n.Evaluate().M41,
(Matrix4x4Node n, "Channel42") => n.Evaluate().M42,
(Matrix4x4Node n, "Channel43") => n.Evaluate().M43,
(Matrix4x4Node n, "Channel44") => n.Evaluate().M44,
_ => 0
};
}
}