/// <summary> /// Constructor from Rotation3D and center point. /// </summary> /// <param name="rotation">Rotation3D.</param> /// <param name="center">Center point.</param> public RotateTransform3D(Rotation3D rotation, Point3D center) { Rotation = rotation; CenterX = center.X; CenterY = center.Y; CenterZ = center.Z; }
/// <summary> /// Constructor from Rotation3D and center point. /// </summary> /// <param name="rotation">Rotation3D.</param> /// <param name="centerX">X center</param> /// <param name="centerY">Y center</param> /// <param name="centerZ">Z center</param> public RotateTransform3D(Rotation3D rotation, double centerX, double centerY, double centerZ) { Rotation = rotation; CenterX = centerX; CenterY = centerY; CenterZ = centerZ; }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Rotation3D vRotation = Rotation; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hRotation = vRotation != null ? ((DUCE.IResource)vRotation).GetHandle(channel) : DUCE.ResourceHandle.Null; // Obtain handles for animated properties DUCE.ResourceHandle hCenterXAnimations = GetAnimationResourceHandle(CenterXProperty, channel); DUCE.ResourceHandle hCenterYAnimations = GetAnimationResourceHandle(CenterYProperty, channel); DUCE.ResourceHandle hCenterZAnimations = GetAnimationResourceHandle(CenterZProperty, channel); // Pack & send command packet DUCE.MILCMD_ROTATETRANSFORM3D data; unsafe { data.Type = MILCMD.MilCmdRotateTransform3D; data.Handle = _duceResource.GetHandle(channel); if (hCenterXAnimations.IsNull) { data.centerX = CenterX; } data.hCenterXAnimations = hCenterXAnimations; if (hCenterYAnimations.IsNull) { data.centerY = CenterY; } data.hCenterYAnimations = hCenterYAnimations; if (hCenterZAnimations.IsNull) { data.centerZ = CenterZ; } data.hCenterZAnimations = hCenterZAnimations; data.hrotation = hRotation; // Send packed command structure channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_ROTATETRANSFORM3D)); } } }
internal override void ReleaseOnChannelCore(DUCE.Channel channel) { Debug.Assert(_duceResource.IsOnChannel(channel)); if (_duceResource.ReleaseOnChannel(channel)) { Rotation3D vRotation = Rotation; if (vRotation != null) { ((DUCE.IResource)vRotation).ReleaseOnChannel(channel); } ReleaseOnChannelAnimations(channel); } }
private static void RotationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // The first change to the default value of a mutable collection property (e.g. GeometryGroup.Children) // will promote the property value from a default value to a local value. This is technically a sub-property // change because the collection was changed and not a new collection set (GeometryGroup.Children. // Add versus GeometryGroup.Children = myNewChildrenCollection). However, we never marshalled // the default value to the compositor. If the property changes from a default value, the new local value // needs to be marshalled to the compositor. We detect this scenario with the second condition // e.OldValueSource != e.NewValueSource. Specifically in this scenario the OldValueSource will be // Default and the NewValueSource will be Local. if (e.IsASubPropertyChange && (e.OldValueSource == e.NewValueSource)) { return; } RotateTransform3D target = ((RotateTransform3D)d); target._cachedRotationValue = (Rotation3D)e.NewValue; Rotation3D oldV = (Rotation3D)e.OldValue; Rotation3D newV = (Rotation3D)e.NewValue; System.Windows.Threading.Dispatcher dispatcher = target.Dispatcher; if (dispatcher != null) { DUCE.IResource targetResource = (DUCE.IResource)target; using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); target.ReleaseResource(oldV, channel); target.AddRefResource(newV, channel); } } } target.PropertyChanged(RotationProperty); }
internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel) { if (_duceResource.CreateOrAddRefOnChannel(this, channel, System.Windows.Media.Composition.DUCE.ResourceType.TYPE_ROTATETRANSFORM3D)) { Rotation3D vRotation = Rotation; if (vRotation != null) { ((DUCE.IResource)vRotation).AddRefOnChannel(channel); } AddRefOnChannelAnimations(channel); UpdateResource(channel, true /* skip "on channel" check - we already know that we're on channel */); } return(_duceResource.GetHandle(channel)); }
public RotateTransform3D(Rotation3D rotation, Point3D center) { }
/// <summary> /// Creates a new EasingRotation3DKeyFrame. /// </summary> public EasingRotation3DKeyFrame(Rotation3D value, KeyTime keyTime, IEasingFunction easingFunction) : this() { Value = value; KeyTime = keyTime; EasingFunction = easingFunction; }
internal static Double GetSegmentLengthRotation3D(Rotation3D from, Rotation3D to) { return GetSegmentLengthQuaternion(from.InternalQuaternion, to.InternalQuaternion); }
internal static bool IsValidAnimationValueRotation3D(Rotation3D value) { return IsValidAnimationValueQuaternion(value.InternalQuaternion); }
/// <summary> /// Calculates the value this animation believes should be the current value for the property. /// </summary> /// <param name="defaultOriginValue"> /// This value is the suggested origin value provided to the animation /// to be used if the animation does not have its own concept of a /// start value. If this animation is the first in a composition chain /// this value will be the snapshot value if one is available or the /// base property value if it is not; otherise this value will be the /// value returned by the previous animation in the chain with an /// animationClock that is not Stopped. /// </param> /// <param name="defaultDestinationValue"> /// This value is the suggested destination value provided to the animation /// to be used if the animation does not have its own concept of an /// end value. This value will be the base value if the animation is /// in the first composition layer of animations on a property; /// otherwise this value will be the output value from the previous /// composition layer of animations for the property. /// </param> /// <param name="animationClock"> /// This is the animationClock which can generate the CurrentTime or /// CurrentProgress value to be used by the animation to generate its /// output value. /// </param> /// <returns> /// The value this animation believes should be the current value for the property. /// </returns> protected override Rotation3D GetCurrentValueCore(Rotation3D defaultOriginValue, Rotation3D defaultDestinationValue, AnimationClock animationClock) { Debug.Assert(animationClock.CurrentState != ClockState.Stopped); if (!_isAnimationFunctionValid) { ValidateAnimationFunction(); } double progress = animationClock.CurrentProgress.Value; IEasingFunction easingFunction = EasingFunction; if (easingFunction != null) { progress = easingFunction.Ease(progress); } Rotation3D from = Rotation3D.Identity; Rotation3D to = Rotation3D.Identity; Rotation3D accumulated = Rotation3D.Identity; Rotation3D foundation = Rotation3D.Identity; // need to validate the default origin and destination values if // the animation uses them as the from, to, or foundation values bool validateOrigin = false; bool validateDestination = false; switch(_animationType) { case AnimationType.Automatic: from = defaultOriginValue; to = defaultDestinationValue; validateOrigin = true; validateDestination = true; break; case AnimationType.From: from = _keyValues[0]; to = defaultDestinationValue; validateDestination = true; break; case AnimationType.To: from = defaultOriginValue; to = _keyValues[0]; validateOrigin = true; break; case AnimationType.By: // According to the SMIL specification, a By animation is // always additive. But we don't force this so that a // user can re-use a By animation and have it replace the // animations that precede it in the list without having // to manually set the From value to the base value. to = _keyValues[0]; foundation = defaultOriginValue; validateOrigin = true; break; case AnimationType.FromTo: from = _keyValues[0]; to = _keyValues[1]; if (IsAdditive) { foundation = defaultOriginValue; validateOrigin = true; } break; case AnimationType.FromBy: from = _keyValues[0]; to = AnimatedTypeHelpers.AddRotation3D(_keyValues[0], _keyValues[1]); if (IsAdditive) { foundation = defaultOriginValue; validateOrigin = true; } break; default: Debug.Fail("Unknown animation type."); break; } if (validateOrigin && !AnimatedTypeHelpers.IsValidAnimationValueRotation3D(defaultOriginValue)) { throw new InvalidOperationException( SR.Get( SRID.Animation_Invalid_DefaultValue, this.GetType(), "origin", defaultOriginValue.ToString(CultureInfo.InvariantCulture))); } if (validateDestination && !AnimatedTypeHelpers.IsValidAnimationValueRotation3D(defaultDestinationValue)) { throw new InvalidOperationException( SR.Get( SRID.Animation_Invalid_DefaultValue, this.GetType(), "destination", defaultDestinationValue.ToString(CultureInfo.InvariantCulture))); } if (IsCumulative) { double currentRepeat = (double)(animationClock.CurrentIteration - 1); if (currentRepeat > 0.0) { Rotation3D accumulator = AnimatedTypeHelpers.SubtractRotation3D(to, from); accumulated = AnimatedTypeHelpers.ScaleRotation3D(accumulator, currentRepeat); } } // return foundation + accumulated + from + ((to - from) * progress) return AnimatedTypeHelpers.AddRotation3D( foundation, AnimatedTypeHelpers.AddRotation3D( accumulated, AnimatedTypeHelpers.InterpolateRotation3D(from, to, progress))); }
internal static Rotation3D AddRotation3D(Rotation3D value1, Rotation3D value2) { if (value1 == null) { value1 = Rotation3D.Identity; } if (value2 == null) { value2 = Rotation3D.Identity; } return new QuaternionRotation3D(AddQuaternion(value1.InternalQuaternion, value2.InternalQuaternion)); }
private static Visual3D CreateSide(object material, Rotation3D rotation) { Transform3DGroup transform = new Transform3DGroup(); Transform3D translation = new TranslateTransform3D(0, 0, 0.5); transform.Children.Add(translation); transform.Children.Add(new RotateTransform3D(rotation)); if (material is Visual) { return new Viewport2DVisual3D { Geometry = quadMesh, Visual = (Visual)material, Material = visualHostMaterial, Transform = transform }; } else { GeometryModel3D model = new GeometryModel3D(quadMesh, new DiffuseMaterial((Brush)material)); return new ModelVisual3D { Content=model, Transform=transform}; } }
/// <summary> /// Creates a new Rotation3DAnimation that will animate a /// Rotation3D property from the "fromValue" parameter of this constructor /// to the "toValue" parameter. /// </summary> public Rotation3DAnimation(Rotation3D fromValue, Rotation3D toValue, Duration duration) : this() { From = fromValue; To = toValue; Duration = duration; }
/// <summary> /// Calculates the value this animation believes should be the current value for the property. /// </summary> /// <param name="defaultOriginValue"> /// This value is the suggested origin value provided to the animation /// to be used if the animation does not have its own concept of a /// start value. If this animation is the first in a composition chain /// this value will be the snapshot value if one is available or the /// base property value if it is not; otherise this value will be the /// value returned by the previous animation in the chain with an /// animationClock that is not Stopped. /// </param> /// <param name="defaultDestinationValue"> /// This value is the suggested destination value provided to the animation /// to be used if the animation does not have its own concept of an /// end value. This value will be the base value if the animation is /// in the first composition layer of animations on a property; /// otherwise this value will be the output value from the previous /// composition layer of animations for the property. /// </param> /// <param name="animationClock"> /// This is the animationClock which can generate the CurrentTime or /// CurrentProgress value to be used by the animation to generate its /// output value. /// </param> /// <returns> /// The value this animation believes should be the current value for the property. /// </returns> public Rotation3D GetCurrentValue(Rotation3D defaultOriginValue, Rotation3D defaultDestinationValue, AnimationClock animationClock) { ReadPreamble(); if (animationClock == null) { throw new ArgumentNullException("animationClock"); } // We check for null above but presharp doesn't notice so we suppress the // warning here. #pragma warning suppress 6506 if (animationClock.CurrentState == ClockState.Stopped) { return defaultDestinationValue; } /* if (!AnimatedTypeHelpers.IsValidAnimationValueRotation3D(defaultDestinationValue)) { throw new ArgumentException( SR.Get( SRID.Animation_InvalidBaseValue, defaultDestinationValue, defaultDestinationValue.GetType(), GetType()), "defaultDestinationValue"); } */ return GetCurrentValueCore(defaultOriginValue, defaultDestinationValue, animationClock); }
/// <summary> /// Creates a new DiscreteRotation3DKeyFrame. /// </summary> public DiscreteRotation3DKeyFrame(Rotation3D value, KeyTime keyTime) : base(value, keyTime) { }
/// <summary> /// Implemented to Easingly interpolate between the baseValue and the /// Value of this KeyFrame using the keyFrameProgress. /// </summary> protected override Rotation3D InterpolateValueCore(Rotation3D baseValue, double keyFrameProgress) { IEasingFunction easingFunction = EasingFunction; if (easingFunction != null) { keyFrameProgress = easingFunction.Ease(keyFrameProgress); } if (keyFrameProgress == 0.0) { return baseValue; } else if (keyFrameProgress == 1.0) { return Value; } else { return AnimatedTypeHelpers.InterpolateRotation3D(baseValue, Value, keyFrameProgress); } }
/// <summary> /// Constructor from Rotation3D. /// </summary> /// <param name="rotation">Rotation3D.</param> public RotateTransform3D(Rotation3D rotation) { Rotation = rotation; }
/// <summary> /// Calculates the value this animation believes should be the current value for the property. /// </summary> /// <param name="defaultOriginValue"> /// This value is the suggested origin value provided to the animation /// to be used if the animation does not have its own concept of a /// start value. If this animation is the first in a composition chain /// this value will be the snapshot value if one is available or the /// base property value if it is not; otherise this value will be the /// value returned by the previous animation in the chain with an /// animationClock that is not Stopped. /// </param> /// <param name="defaultDestinationValue"> /// This value is the suggested destination value provided to the animation /// to be used if the animation does not have its own concept of an /// end value. This value will be the base value if the animation is /// in the first composition layer of animations on a property; /// otherwise this value will be the output value from the previous /// composition layer of animations for the property. /// </param> /// <param name="animationClock"> /// This is the animationClock which can generate the CurrentTime or /// CurrentProgress value to be used by the animation to generate its /// output value. /// </param> /// <returns> /// The value this animation believes should be the current value for the property. /// </returns> protected sealed override Rotation3D GetCurrentValueCore( Rotation3D defaultOriginValue, Rotation3D defaultDestinationValue, AnimationClock animationClock) { Debug.Assert(animationClock.CurrentState != ClockState.Stopped); if (_keyFrames == null) { return defaultDestinationValue; } // We resolved our KeyTimes when we froze, but also got notified // of the frozen state and therefore invalidated ourselves. if (!_areKeyTimesValid) { ResolveKeyTimes(); } if (_sortedResolvedKeyFrames == null) { return defaultDestinationValue; } TimeSpan currentTime = animationClock.CurrentTime.Value; Int32 keyFrameCount = _sortedResolvedKeyFrames.Length; Int32 maxKeyFrameIndex = keyFrameCount - 1; Rotation3D currentIterationValue; Debug.Assert(maxKeyFrameIndex >= 0, "maxKeyFrameIndex is less than zero which means we don't actually have any key frames."); Int32 currentResolvedKeyFrameIndex = 0; // Skip all the key frames with key times lower than the current time. // currentResolvedKeyFrameIndex will be greater than maxKeyFrameIndex // if we are past the last key frame. while ( currentResolvedKeyFrameIndex < keyFrameCount && currentTime > _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime) { currentResolvedKeyFrameIndex++; } // If there are multiple key frames at the same key time, be sure to go to the last one. while ( currentResolvedKeyFrameIndex < maxKeyFrameIndex && currentTime == _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex + 1]._resolvedKeyTime) { currentResolvedKeyFrameIndex++; } if (currentResolvedKeyFrameIndex == keyFrameCount) { // Past the last key frame. currentIterationValue = GetResolvedKeyFrameValue(maxKeyFrameIndex); } else if (currentTime == _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime) { // Exactly on a key frame. currentIterationValue = GetResolvedKeyFrameValue(currentResolvedKeyFrameIndex); } else { // Between two key frames. Double currentSegmentProgress = 0.0; Rotation3D fromValue; if (currentResolvedKeyFrameIndex == 0) { // The current key frame is the first key frame so we have // some special rules for determining the fromValue and an // optimized method of calculating the currentSegmentProgress. // If we're additive we want the base value to be a zero value // so that if there isn't a key frame at time 0.0, we'll use // the zero value for the time 0.0 value and then add that // later to the base value. if (IsAdditive) { fromValue = AnimatedTypeHelpers.GetZeroValueRotation3D(defaultOriginValue); } else { fromValue = defaultOriginValue; } // Current segment time divided by the segment duration. // Note: the reason this works is that we know that we're in // the first segment, so we can assume: // // currentTime.TotalMilliseconds = current segment time // _sortedResolvedKeyFrames[0]._resolvedKeyTime.TotalMilliseconds = current segment duration currentSegmentProgress = currentTime.TotalMilliseconds / _sortedResolvedKeyFrames[0]._resolvedKeyTime.TotalMilliseconds; } else { Int32 previousResolvedKeyFrameIndex = currentResolvedKeyFrameIndex - 1; TimeSpan previousResolvedKeyTime = _sortedResolvedKeyFrames[previousResolvedKeyFrameIndex]._resolvedKeyTime; fromValue = GetResolvedKeyFrameValue(previousResolvedKeyFrameIndex); TimeSpan segmentCurrentTime = currentTime - previousResolvedKeyTime; TimeSpan segmentDuration = _sortedResolvedKeyFrames[currentResolvedKeyFrameIndex]._resolvedKeyTime - previousResolvedKeyTime; currentSegmentProgress = segmentCurrentTime.TotalMilliseconds / segmentDuration.TotalMilliseconds; } currentIterationValue = GetResolvedKeyFrame(currentResolvedKeyFrameIndex).InterpolateValue(fromValue, currentSegmentProgress); } // If we're cumulative, we need to multiply the final key frame // value by the current repeat count and add this to the return // value. if (IsCumulative) { Double currentRepeat = (Double)(animationClock.CurrentIteration - 1); if (currentRepeat > 0.0) { currentIterationValue = AnimatedTypeHelpers.AddRotation3D( currentIterationValue, AnimatedTypeHelpers.ScaleRotation3D(GetResolvedKeyFrameValue(maxKeyFrameIndex), currentRepeat)); } } // If we're additive we need to add the base value to the return value. if (IsAdditive) { return AnimatedTypeHelpers.AddRotation3D(defaultOriginValue, currentIterationValue); } return currentIterationValue; }
/// <summary> /// Creates a new DiscreteRotation3DKeyFrame. /// </summary> public DiscreteRotation3DKeyFrame(Rotation3D value) : base(value) { }
/// <summary> /// Creates a new SplineRotation3DKeyFrame. /// </summary> public SplineRotation3DKeyFrame(Rotation3D value) : this() { Value = value; }
// We don't need to override CloneCore because it won't do anything #endregion #region Rotation3DKeyFrame /// <summary> /// Implemented to linearly interpolate between the baseValue and the /// Value of this KeyFrame using the keyFrameProgress. /// </summary> protected override Rotation3D InterpolateValueCore(Rotation3D baseValue, double keyFrameProgress) { if (keyFrameProgress < 1.0) { return baseValue; } else { return Value; } }
/// <summary> /// Creates a new SplineRotation3DKeyFrame. /// </summary> public SplineRotation3DKeyFrame(Rotation3D value, KeyTime keyTime) : this() { Value = value; KeyTime = keyTime; }
/// <summary> /// Calculates the value this animation believes should be the current value for the property. /// </summary> /// <param name="defaultOriginValue"> /// This value is the suggested origin value provided to the animation /// to be used if the animation does not have its own concept of a /// start value. If this animation is the first in a composition chain /// this value will be the snapshot value if one is available or the /// base property value if it is not; otherise this value will be the /// value returned by the previous animation in the chain with an /// animationClock that is not Stopped. /// </param> /// <param name="defaultDestinationValue"> /// This value is the suggested destination value provided to the animation /// to be used if the animation does not have its own concept of an /// end value. This value will be the base value if the animation is /// in the first composition layer of animations on a property; /// otherwise this value will be the output value from the previous /// composition layer of animations for the property. /// </param> /// <param name="animationClock"> /// This is the animationClock which can generate the CurrentTime or /// CurrentProgress value to be used by the animation to generate its /// output value. /// </param> /// <returns> /// The value this animation believes should be the current value for the property. /// </returns> protected abstract Rotation3D GetCurrentValueCore(Rotation3D defaultOriginValue, Rotation3D defaultDestinationValue, AnimationClock animationClock);
/// <summary> /// Creates a new SplineRotation3DKeyFrame. /// </summary> public SplineRotation3DKeyFrame(Rotation3D value, KeyTime keyTime, KeySpline keySpline) : this() { if (keySpline == null) { throw new ArgumentNullException("keySpline"); } Value = value; KeyTime = keyTime; KeySpline = keySpline; }
/// <summary> /// Creates a new Rotation3DAnimation that will animate a /// Rotation3D property from its base value to the value specified /// by the "toValue" parameter of this constructor. /// </summary> public Rotation3DAnimation(Rotation3D toValue, Duration duration) : this() { To = toValue; Duration = duration; }
/// <summary> /// Creates a new LinearRotation3DKeyFrame. /// </summary> public LinearRotation3DKeyFrame(Rotation3D value) : base(value) { }
/// <summary> /// Creates a new Rotation3DAnimation that will animate a /// Rotation3D property from the "fromValue" parameter of this constructor /// to the "toValue" parameter. /// </summary> public Rotation3DAnimation(Rotation3D fromValue, Rotation3D toValue, Duration duration, FillBehavior fillBehavior) : this() { From = fromValue; To = toValue; Duration = duration; FillBehavior = fillBehavior; }
/// <summary> /// Creates a new LinearRotation3DKeyFrame. /// </summary> public LinearRotation3DKeyFrame(Rotation3D value, KeyTime keyTime) : base(value, keyTime) { }
internal static Rotation3D InterpolateRotation3D(Rotation3D from, Rotation3D to, Double progress) { return new QuaternionRotation3D(InterpolateQuaternion(from.InternalQuaternion, to.InternalQuaternion, progress, /* useShortestPath = */ true)); }
/// <summary> /// Implemented to linearly interpolate between the baseValue and the /// Value of this KeyFrame using the keyFrameProgress. /// </summary> protected override Rotation3D InterpolateValueCore(Rotation3D baseValue, double keyFrameProgress) { if (keyFrameProgress == 0.0) { return baseValue; } else if (keyFrameProgress == 1.0) { return Value; } else { return AnimatedTypeHelpers.InterpolateRotation3D(baseValue, Value, keyFrameProgress); } }
internal static Rotation3D SubtractRotation3D(Rotation3D value1, Rotation3D value2) { return new QuaternionRotation3D(SubtractQuaternion(value1.InternalQuaternion, value2.InternalQuaternion)); }
/// <summary> /// Creates a new EasingRotation3DKeyFrame. /// </summary> public EasingRotation3DKeyFrame(Rotation3D value) : this() { Value = value; }
internal static Rotation3D ScaleRotation3D(Rotation3D value, Double factor) { return new QuaternionRotation3D(ScaleQuaternion(value.InternalQuaternion, factor)); }
/// <summary> /// Creates a new EasingRotation3DKeyFrame. /// </summary> public EasingRotation3DKeyFrame(Rotation3D value, KeyTime keyTime) : this() { Value = value; KeyTime = keyTime; }
internal static Rotation3D GetZeroValueRotation3D(Rotation3D baseValue) { return Rotation3D.Identity; }
public RotateTransform3D(Rotation3D rotation, double centerX, double centerY, double centerZ) { }