Files
Xune/UIX.RenderApi.Skia/Microsoft/Iris/Render/Animation/KeyframeAnimation.cs
T
2021-07-11 23:07:04 -05:00

568 lines
26 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Microsoft.Iris.Render.Animation.KeyframeAnimation
// Assembly: UIX.RenderApi, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
// MVID: D47658B8-A8EA-43D6-8837-ECE823BFFFC1
// Assembly location: C:\Program Files\Zune\UIX.RenderApi.dll
using Microsoft.Iris.Render.Common;
using Microsoft.Iris.Render.Protocol;
using Microsoft.Iris.Render.Protocols.Splash.Rendering;
using System;
namespace Microsoft.Iris.Render.Animation
{
internal class KeyframeAnimation :
Microsoft.Iris.Render.Animation.Animation,
IKeyframeAnimation,
IAnimation,
IRenderHandleOwner,
IAnimatableObject,
IAnimatable,
ISharedRenderObject,
IActivatableObject,
IActivatable
{
private static LinearInterpolation s_defaultInterpolation = new LinearInterpolation();
private AnimationSystem m_animationSystem;
private RemoteAnimation m_remoteObject;
private AnimationInput m_reference;
private AnimationInput m_scale;
private AnimationInputType m_animationType;
private Vector m_keyframeList;
private Vector m_targetList;
private int m_repeatCount;
private bool m_isActive;
private bool m_isPlaying;
private bool m_autoReset;
private AnimationResetBehavior m_resetBehavior;
internal KeyframeAnimation(AnimationSystem owner, AnimationInput initialValue)
{
this.m_animationSystem = owner;
this.m_reference = null;
this.m_scale = null;
this.m_animationType = initialValue.InputType;
this.m_keyframeList = new Vector();
this.m_repeatCount = 0;
this.m_autoReset = false;
this.m_resetBehavior = AnimationResetBehavior.LeaveCurrent;
this.m_animationSystem.RegisterUsage(this);
this.m_remoteObject = owner.Session.BuildRemoteAnimation(this, this.m_animationType);
if (this.m_animationSystem.BackCompat)
return;
this.AddKeyframe(new AnimationKeyframe(0.0f, initialValue, s_defaultInterpolation));
}
protected override void Dispose(bool inDispose)
{
try
{
if (inDispose)
{
this.RemoveAllEvents();
this.RemoveAllTargets();
if (this.m_keyframeList != null)
{
foreach (AnimationKeyframe keyframe in this.m_keyframeList)
keyframe.Value.UnregisterUsage(this);
this.m_keyframeList.Clear();
}
if (this.m_remoteObject != null)
this.m_remoteObject.Dispose();
this.m_animationSystem.UnregisterUsage(this);
}
this.m_remoteObject = null;
this.m_reference = null;
this.m_keyframeList = null;
this.m_targetList = null;
this.m_animationSystem = null;
}
finally
{
base.Dispose(inDispose);
}
}
public override int RepeatCount
{
get => this.m_repeatCount;
set
{
if (this.m_repeatCount == value)
return;
this.m_remoteObject.SendSetRepeatCount(value);
this.m_repeatCount = value;
}
}
public override bool IsPlaying => this.m_isPlaying;
public override bool IsActive => this.m_isActive;
public override bool AutoReset
{
get => this.m_autoReset;
set
{
if (this.m_autoReset == value)
return;
this.m_autoReset = value;
this.m_remoteObject.SendSetAutoReset(value);
}
}
public override AnimationResetBehavior ResetBehavior
{
get => this.m_resetBehavior;
set
{
if (this.m_resetBehavior == value)
return;
this.m_resetBehavior = value;
this.m_remoteObject.SendSetResetBehavior(value);
}
}
public override void Play()
{
this.m_isActive = true;
this.m_isPlaying = true;
this.m_remoteObject.SendPlay();
}
public override void Pause()
{
if (this.m_isActive)
this.m_isPlaying = false;
this.m_remoteObject.SendPause();
}
public override void Reset()
{
this.m_isActive = false;
this.m_isPlaying = false;
this.m_remoteObject.SendReset();
}
public override void InstantAdvance(float advanceTime)
{
Debug2.Validate(advanceTime >= 0.0, typeof(ArgumentOutOfRangeException), nameof(advanceTime));
this.m_remoteObject.SendInstantAdvance(advanceTime);
}
public override void InstantFinish() => this.m_remoteObject.SendInstantFinish();
public AnimationInputType Type => this.m_animationType;
public AnimationInput InitialValue => this.GetKeyframe(0).Value;
public int KeyframeCount => this.m_keyframeList.Count;
public AnimationInput Reference
{
get => this.m_reference;
set
{
this.SendInput(-1, value);
this.m_reference = value;
}
}
public AnimationInput Scale
{
get => this.m_scale;
set
{
this.SendInput(-2, value);
this.m_scale = value;
}
}
void IKeyframeAnimation.AddKeyframe(AnimationKeyframe keyframe)
{
Debug2.Validate(keyframe != null, typeof(ArgumentNullException), nameof(keyframe));
this.AddKeyframe(keyframe);
}
internal void AddKeyframe(AnimationKeyframe keyframe)
{
this.m_keyframeList.Add(keyframe);
this.m_remoteObject.SendAddKeyframe(this.m_keyframeList.Count - 1, keyframe.Time);
this.SetKeyframe(this.m_keyframeList.Count - 1, keyframe, false);
}
AnimationKeyframe IKeyframeAnimation.GetKeyframe(
int keyframeIndex)
{
Debug2.Validate(keyframeIndex >= 0 || keyframeIndex < this.m_keyframeList.Count, typeof(ArgumentOutOfRangeException), nameof(keyframeIndex));
return this.GetKeyframe(keyframeIndex);
}
internal AnimationKeyframe GetKeyframe(int keyframeIndex) => this.m_keyframeList[keyframeIndex] as AnimationKeyframe;
void IKeyframeAnimation.SetKeyframe(
int keyframeIndex,
AnimationKeyframe keyframe)
{
Debug2.Validate(keyframe != null, typeof(ArgumentNullException), nameof(keyframe));
Debug2.Validate(keyframeIndex >= 0 || keyframeIndex < this.m_keyframeList.Count, typeof(ArgumentOutOfRangeException), nameof(keyframeIndex));
if (keyframeIndex == 0 && !this.m_animationSystem.BackCompat)
Debug2.Validate(keyframe.Time == 0.0, typeof(ArgumentException), "Cannot change the time for keyframe 0");
this.SetKeyframe(keyframeIndex, keyframe, true);
}
internal void SetKeyframe(int keyframeIndex, AnimationKeyframe keyframe, bool replaceKeyframe)
{
keyframe.Value.RegisterUsage(this);
if (replaceKeyframe)
{
AnimationKeyframe keyframe1 = (AnimationKeyframe)this.m_keyframeList[keyframeIndex];
this.m_keyframeList.RemoveAt(keyframeIndex);
this.m_keyframeList.Insert(keyframeIndex, keyframe);
keyframe1.Value.UnregisterUsage(this);
}
this.m_remoteObject.SendSetKeyframeTime(keyframeIndex, keyframe.Time);
this.SendInput(keyframeIndex, keyframe.Value);
this.SendInterpolation(keyframeIndex, keyframe.Interpolation);
}
void IKeyframeAnimation.AddTarget(
IAnimatable targetObject,
string targetPropertyName)
{
Debug2.Validate(targetObject is IAnimatableObject, typeof(ArgumentException), nameof(targetObject));
this.AddTarget((IAnimatableObject)targetObject, targetPropertyName, null);
}
void IKeyframeAnimation.AddTarget(
IAnimatable targetObject,
string targetPropertyName,
string targetMask)
{
Debug2.Validate(targetObject is IAnimatableObject, typeof(ArgumentException), nameof(targetObject));
this.AddTarget((IAnimatableObject)targetObject, targetPropertyName, targetMask);
}
internal void AddTarget(
IAnimatableObject targetObject,
string targetPropertyName,
string targetMaskSpec)
{
Debug2.Validate(targetObject != null, typeof(ArgumentNullException), nameof(targetObject));
Debug2.Validate(targetPropertyName != null, typeof(ArgumentNullException), nameof(targetPropertyName));
Debug2.Validate(!(targetObject is IAnimation), typeof(ArgumentException), "Animations can't be set as animation targets");
AnimationTarget target = new AnimationTarget(targetObject, targetPropertyName);
AnimationTypeMask sourceMask = AnimationTypeMask.FromString(targetMaskSpec);
if (!sourceMask.CanMapFromType(this.m_animationType))
throw new ArgumentException(string.Format("Mask cannot be applied to a {0} animation", m_animationType));
if (!sourceMask.CanMapToType(target.TargetPropertyType))
throw new ArgumentException(string.Format("Mask cannot be applied to a property of type {0}", target.TargetPropertyType));
uint propertyInfo = this.GeneratePropertyInfo(target.TargetPropertyType, sourceMask);
this.m_remoteObject.SendAddTarget(target.TargetId, target.TargetObject.GetObjectId(), target.TargetObject.GetPropertyId(target.TargetPropertyName), propertyInfo);
if (this.m_targetList == null)
this.m_targetList = new Vector();
this.m_targetList.Add(new KeyframeAnimation.AnimationTargetInfo(target, targetMaskSpec));
}
void IKeyframeAnimation.RemoveTarget(
IAnimatable targetObject,
string targetPropertyName,
string targetMaskSpec)
{
Debug2.Validate(targetObject != null, typeof(ArgumentNullException), nameof(targetObject));
Debug2.Validate(targetPropertyName != null, typeof(ArgumentNullException), nameof(targetPropertyName));
KeyframeAnimation.AnimationTargetInfo animationTargetInfo = null;
if (this.m_targetList != null)
{
foreach (KeyframeAnimation.AnimationTargetInfo target in this.m_targetList)
{
if (target.Target.TargetObject == targetObject && target.Target.TargetPropertyName == targetPropertyName && string.Compare(target.MaskSpec, targetMaskSpec, StringComparison.OrdinalIgnoreCase) == 0)
{
animationTargetInfo = target;
break;
}
}
}
if (animationTargetInfo == null)
return;
this.m_remoteObject.SendRemoveTarget(animationTargetInfo.Target.TargetId);
this.m_targetList.Remove(animationTargetInfo);
animationTargetInfo.Target.Dispose();
}
void IKeyframeAnimation.RemoveAllTargets() => this.RemoveAllTargets();
internal void RemoveAllTargets()
{
if (this.m_targetList == null)
return;
foreach (KeyframeAnimation.AnimationTargetInfo target in this.m_targetList)
{
this.m_remoteObject.SendRemoveTarget(target.Target.TargetId);
target.Target.Dispose();
}
this.m_targetList.Clear();
}
void IKeyframeAnimation.AddStageEvent(
AnimationStage animationStage,
AnimationEvent animationEvent)
{
Debug2.Validate(animationEvent != null, typeof(ArgumentNullException), nameof(animationEvent));
Debug2.Validate(animationStage < AnimationStage.Count, typeof(ArgumentException), "invalid animation stage");
RENDERHANDLE targetObjectId = animationEvent.TargetObjectId;
if (!(targetObjectId != RENDERHANDLE.NULL))
return;
this.m_remoteObject.SendAddStageEvent(animationEvent.EventId, animationStage, targetObjectId, animationEvent.TargetMethodId, animationEvent.TargetMethodArg, animationEvent.InitialActivation, animationEvent.AllowRepeat);
}
void IKeyframeAnimation.AddTimeEvent(
float absoluteTime,
AnimationEvent animationEvent)
{
Debug2.Validate(animationEvent != null, typeof(ArgumentNullException), nameof(animationEvent));
Debug2.Validate(absoluteTime >= 0.0, typeof(ArgumentException), "absoluteTime value must be >= 0.0f");
RENDERHANDLE targetObjectId = animationEvent.TargetObjectId;
if (!(targetObjectId != RENDERHANDLE.NULL))
return;
this.m_remoteObject.SendAddTimeEvent(animationEvent.EventId, absoluteTime, targetObjectId, animationEvent.TargetMethodId, animationEvent.TargetMethodArg, animationEvent.InitialActivation, animationEvent.AllowRepeat);
}
void IKeyframeAnimation.AddProgressEvent(
float progress,
AnimationEvent animationEvent)
{
Debug2.Validate(animationEvent != null, typeof(ArgumentNullException), nameof(animationEvent));
Debug2.Validate(progress >= 0.0 && progress <= 1.0, typeof(ArgumentException), "'progress' value must be between 0.0f and 1.0f");
RENDERHANDLE targetObjectId = animationEvent.TargetObjectId;
if (!(targetObjectId != RENDERHANDLE.NULL))
return;
this.m_remoteObject.SendAddProgressEvent(animationEvent.EventId, progress, targetObjectId, animationEvent.TargetMethodId, animationEvent.TargetMethodArg, animationEvent.InitialActivation, animationEvent.AllowRepeat);
}
void IKeyframeAnimation.AddValueEvent(
ValueEventCondition condition,
AnimationInput reference,
AnimationEvent animationEvent)
{
Debug2.Validate(animationEvent != null, typeof(ArgumentNullException), nameof(animationEvent));
Debug2.Validate(reference != null, typeof(ArgumentNullException), nameof(reference));
Debug2.Validate(condition < ValueEventCondition.Count, typeof(ArgumentNullException), nameof(condition));
RENDERHANDLE targetObjectId = animationEvent.TargetObjectId;
if (!(targetObjectId != RENDERHANDLE.NULL))
return;
this.SendInput(-3, reference);
this.m_remoteObject.SendAddValueEvent(animationEvent.EventId, condition, targetObjectId, animationEvent.TargetMethodId, animationEvent.TargetMethodArg, animationEvent.InitialActivation, animationEvent.AllowRepeat);
}
void IKeyframeAnimation.RemoveEvent(AnimationEvent animationEvent)
{
Debug2.Validate(animationEvent != null, typeof(ArgumentNullException), nameof(animationEvent));
this.m_remoteObject.SendRemoveEvent(animationEvent.EventId);
}
void IKeyframeAnimation.RemoveAllEvents() => this.RemoveAllEvents();
internal void RemoveAllEvents() => this.m_remoteObject.SendRemoveAllEvents();
RENDERHANDLE IAnimatableObject.GetObjectId() => ((IRenderHandleOwner)this).RenderHandle;
uint IAnimatableObject.GetPropertyId(string propertyName)
{
if (string.Compare(propertyName, OutputProperty, StringComparison.OrdinalIgnoreCase) == 0)
return 1;
Debug2.Validate(false, typeof(ArgumentException), "Unsupported property: {0}", propertyName);
return 0;
}
AnimationInputType IAnimatableObject.GetPropertyType(
string propertyName)
{
if (string.Compare(propertyName, OutputProperty, StringComparison.OrdinalIgnoreCase) == 0)
return this.Type;
Debug2.Validate(false, typeof(ArgumentException), "Unsupported property: {0}", propertyName);
return AnimationInputType.Float;
}
RENDERHANDLE IActivatableObject.GetObjectId() => ((IRenderHandleOwner)this).RenderHandle;
uint IActivatableObject.GetMethodId(string methodName)
{
if (string.Compare(methodName, PlayMethod, StringComparison.OrdinalIgnoreCase) == 0)
return 1;
if (string.Compare(methodName, PauseMethod, StringComparison.OrdinalIgnoreCase) == 0)
return 2;
if (string.Compare(methodName, ResetMethod, StringComparison.OrdinalIgnoreCase) == 0)
return 3;
if (string.Compare(methodName, FinishMethod, StringComparison.OrdinalIgnoreCase) == 0)
return 4;
if (string.Compare(methodName, NotifyMethod, StringComparison.OrdinalIgnoreCase) == 0)
return 5;
Debug2.Validate(false, typeof(ArgumentException), "Unsupported method: {0}", methodName);
return 0;
}
RENDERHANDLE IRenderHandleOwner.RenderHandle => this.m_remoteObject.RenderHandle;
void IRenderHandleOwner.OnDisconnect() => this.m_remoteObject = null;
private void SendInput(int keyframeIndex, AnimationInput input)
{
Debug2.Validate(input != null, typeof(ArgumentNullException), "keyframe.Value.InputType");
Debug2.Validate(input.InputType == this.m_animationType, typeof(ArgumentException), "keyframe.Value.InputType");
Debug2.Validate(input.InputType == AnimationInputType.Float || input.InputType == AnimationInputType.Vector2 || (input.InputType == AnimationInputType.Vector3 || input.InputType == AnimationInputType.Vector4) || input.InputType == AnimationInputType.Quaternion, typeof(ArgumentException), "keyframe.Value.InputType");
int num;
switch (input)
{
case ConstantAnimationInput _:
case ContinuousAnimationInput _:
case CapturedAnimationInput _:
num = 1;
break;
default:
num = input is BinaryOperation ? 1 : 0;
break;
}
System.Type exceptionType = typeof(ArgumentException);
Debug2.Validate(num != 0, exceptionType, "Invalid animation input in keyframe");
this.m_remoteObject.SendBeginAnimationInput(keyframeIndex);
this.SendInputWorker(keyframeIndex, input);
this.m_remoteObject.SendEndAnimationInput(keyframeIndex);
}
private void SendInputWorker(int keyframeIndex, AnimationInput input)
{
switch (input)
{
case ConstantAnimationInput _:
ConstantAnimationInput constantAnimationInput = (ConstantAnimationInput)input;
switch (constantAnimationInput.InputType)
{
case AnimationInputType.Float:
this.m_remoteObject.SendSetFloat(keyframeIndex, (float)constantAnimationInput.RawValue);
return;
case AnimationInputType.Vector2:
this.m_remoteObject.SendSetVector2(keyframeIndex, (Vector2)constantAnimationInput.RawValue);
return;
case AnimationInputType.Vector3:
this.m_remoteObject.SendSetVector3(keyframeIndex, (Vector3)constantAnimationInput.RawValue);
return;
case AnimationInputType.Vector4:
this.m_remoteObject.SendSetVector4(keyframeIndex, (Vector4)constantAnimationInput.RawValue);
return;
case AnimationInputType.Quaternion:
this.m_remoteObject.SendSetQuaternion(keyframeIndex, (Quaternion)constantAnimationInput.RawValue);
return;
default:
Debug2.Throw(false, "Unexpected constant input type");
return;
}
case CapturedAnimationInput _:
uint propertyInfo1 = this.GeneratePropertyInfo(input.SourceType, input.SourceMask);
CapturedAnimationInput capturedAnimationInput = (CapturedAnimationInput)input;
this.m_remoteObject.SendSetCaptured(keyframeIndex, capturedAnimationInput.ObjectId, capturedAnimationInput.PropertyId, propertyInfo1, capturedAnimationInput.RefreshOnRepeat);
break;
case ContinuousAnimationInput _:
uint propertyInfo2 = this.GeneratePropertyInfo(input.SourceType, input.SourceMask);
ContinuousAnimationInput continuousAnimationInput = (ContinuousAnimationInput)input;
this.m_remoteObject.SendSetContinuous(keyframeIndex, continuousAnimationInput.ObjectId, continuousAnimationInput.PropertyId, propertyInfo2);
break;
case BinaryOperation _:
BinaryOperation binaryOperation = (BinaryOperation)input;
this.SendInputWorker(keyframeIndex, binaryOperation.LeftOperand);
this.SendInputWorker(keyframeIndex, binaryOperation.RightOperand);
this.m_remoteObject.SendSetBinaryOperation(keyframeIndex, binaryOperation.Operation);
break;
default:
Debug2.Throw(false, "Unexpected animation input type!");
break;
}
}
private void SendInterpolation(int keyframeIndex, AnimationInterpolation interpolation)
{
int num;
switch (interpolation)
{
case LinearInterpolation _:
case ExponentialInterpolation _:
case LogarithmicInterpolation _:
case SCurveInterpolation _:
case SineInterpolation _:
case CosineInterpolation _:
case BezierInterpolation _:
case EaseInInterpolation _:
num = 1;
break;
default:
num = interpolation is EaseOutInterpolation ? 1 : 0;
break;
}
System.Type exceptionType = typeof(ArgumentException);
Debug2.Validate(num != 0, exceptionType, "Invalid interpolation in keyframe");
int idxKeyframe = !this.m_animationSystem.BackCompat ? (keyframeIndex > 0 ? keyframeIndex - 1 : 0) : keyframeIndex;
switch (interpolation)
{
case LinearInterpolation _:
this.m_remoteObject.SendSetLinear(idxKeyframe, interpolation.UseSphericalCombination);
break;
case ExponentialInterpolation _:
ExponentialInterpolation exponentialInterpolation = (ExponentialInterpolation)interpolation;
this.m_remoteObject.SendSetExponential(idxKeyframe, interpolation.UseSphericalCombination, exponentialInterpolation.Weight);
break;
case LogarithmicInterpolation _:
LogarithmicInterpolation logarithmicInterpolation = (LogarithmicInterpolation)interpolation;
this.m_remoteObject.SendSetLogarithmic(idxKeyframe, interpolation.UseSphericalCombination, logarithmicInterpolation.Weight);
break;
case SCurveInterpolation _:
SCurveInterpolation scurveInterpolation = (SCurveInterpolation)interpolation;
this.m_remoteObject.SendSetSCurve(idxKeyframe, interpolation.UseSphericalCombination, scurveInterpolation.Weight);
break;
case SineInterpolation _:
this.m_remoteObject.SendSetSine(idxKeyframe, interpolation.UseSphericalCombination);
break;
case CosineInterpolation _:
this.m_remoteObject.SendSetCosine(idxKeyframe, interpolation.UseSphericalCombination);
break;
case BezierInterpolation _:
BezierInterpolation bezierInterpolation = (BezierInterpolation)interpolation;
this.m_remoteObject.SendSetBezier(idxKeyframe, interpolation.UseSphericalCombination, bezierInterpolation.ControlPoint1, bezierInterpolation.ControlPoint2);
break;
case EaseInInterpolation _:
EaseInInterpolation easeInInterpolation = (EaseInInterpolation)interpolation;
this.m_remoteObject.SendSetEaseIn(idxKeyframe, interpolation.UseSphericalCombination, easeInInterpolation.Weight, easeInInterpolation.Handle);
break;
case EaseOutInterpolation _:
EaseOutInterpolation outInterpolation = (EaseOutInterpolation)interpolation;
this.m_remoteObject.SendSetEaseOut(idxKeyframe, interpolation.UseSphericalCombination, outInterpolation.Weight, outInterpolation.Handle);
break;
default:
Debug2.Throw(false, "Unexpected interpolation!");
break;
}
}
private uint GeneratePropertyInfo(AnimationInputType sourceType, AnimationTypeMask sourceMask) => (uint)((int)(sourceType & (AnimationInputType.Vector4 | AnimationInputType.Quaternion)) << 19 | ((int)sourceMask.ChannelCount & 7) << 16 | sourceMask.MaskCode & ushort.MaxValue);
private enum KeyframeSlots
{
ValueEvent = -3, // 0xFFFFFFFD
Scale = -2, // 0xFFFFFFFE
Reference = -1, // 0xFFFFFFFF
Default = 0,
}
private class AnimationTargetInfo
{
internal AnimationTarget Target;
internal string MaskSpec;
internal AnimationTargetInfo(AnimationTarget target, string maskSpec)
{
this.Target = target;
this.MaskSpec = maskSpec;
}
}
}
}