Пример #1
0
        public void GetDefaultDurationTest()
        {
            var timelineGroup = new TimelineGroup();
            var animation     = new Vector2FAnimation();
            var animation2    = new AnimationClip <float>
            {
                Animation = new SingleFromToByAnimation(),
                Delay     = TimeSpan.FromSeconds(10),
            };
            var animation3 = new AnimationClip <float>
            {
                Animation = new SingleFromToByAnimation(),
                Delay     = TimeSpan.FromSeconds(8),
                Duration  = TimeSpan.FromSeconds(4),
            };

            Assert.AreEqual(TimeSpan.FromSeconds(0.0), timelineGroup.GetTotalDuration());

            timelineGroup.Add(animation);
            Assert.AreEqual(TimeSpan.FromSeconds(0.0), timelineGroup.GetTotalDuration());

            timelineGroup.Add(animation2);
            Assert.AreEqual(TimeSpan.FromSeconds(11.0), timelineGroup.GetTotalDuration());

            timelineGroup.Add(animation3);
            Assert.AreEqual(TimeSpan.FromSeconds(12.0), timelineGroup.GetTotalDuration());
        }
Пример #2
0
        public void GetSelfAndAncestors()
        {
            var animationA = new TimelineGroup();
            var animationB = new SingleFromToByAnimation();
            var animationC = new SingleFromToByAnimation();
            var animationD = new TimelineGroup();
            var animationE = new TimelineGroup();
            var animationF = new SingleFromToByAnimation();
            var animationG = new TimelineGroup();

            animationA.Add(animationB);
            animationA.Add(animationC);
            animationA.Add(animationD);
            animationD.Add(animationE);
            animationD.Add(animationF);
            animationE.Add(animationG);

            Assert.That(() => AnimationHelper.GetSelfAndAncestors(null), Throws.TypeOf <ArgumentNullException>());

            var animationInstance = animationA.CreateInstance();
            var ancestors         = animationInstance.Children[2].Children[0].GetSelfAndAncestors().ToArray();

            Assert.AreEqual(3, ancestors.Length);
            Assert.AreEqual(animationInstance.Children[2].Children[0], ancestors[0]);
            Assert.AreEqual(animationInstance.Children[2], ancestors[1]);
            Assert.AreEqual(animationInstance, ancestors[2]);
        }
Пример #3
0
        public void GetDescendantsDepthFirst()
        {
            var animationA = new TimelineGroup();
            var animationB = new SingleFromToByAnimation();
            var animationC = new SingleFromToByAnimation();
            var animationD = new TimelineGroup();
            var animationE = new TimelineGroup();
            var animationF = new SingleFromToByAnimation();
            var animationG = new TimelineGroup();

            animationA.Add(animationB);
            animationA.Add(animationC);
            animationA.Add(animationD);
            animationD.Add(animationE);
            animationD.Add(animationF);
            animationE.Add(animationG);

            Assert.That(() => AnimationHelper.GetDescendants(null), Throws.TypeOf <ArgumentNullException>());

            var animationInstance = animationA.CreateInstance();
            var descendants       = animationInstance.GetDescendants().ToArray();

            Assert.AreEqual(6, descendants.Length);
            Assert.AreEqual(animationInstance.Children[0], descendants[0]);
            Assert.AreEqual(animationInstance.Children[1], descendants[1]);
            Assert.AreEqual(animationInstance.Children[2], descendants[2]);
            Assert.AreEqual(animationInstance.Children[2].Children[0], descendants[3]);
            Assert.AreEqual(animationInstance.Children[2].Children[0].Children[0], descendants[4]);
            Assert.AreEqual(animationInstance.Children[2].Children[1], descendants[5]);
        }
Пример #4
0
        public void CreateInstanceTest()
        {
            var animation1 = new SingleFromToByAnimation();
            var animation2 = new SingleFromToByAnimation();
            var animation3 = new SingleFromToByAnimation();

            var childGroup = new TimelineGroup();

            childGroup.Add(animation2);
            childGroup.Add(animation3);

            var rootGroup = new TimelineGroup();

            rootGroup.Add(animation1);
            rootGroup.Add(childGroup);

            var animationInstance = rootGroup.CreateInstance();

            Assert.IsNotNull(animationInstance);
            Assert.AreEqual(2, animationInstance.Children.Count);
            Assert.That(animationInstance.Children[0], Is.TypeOf <AnimationInstance <float> >());
            Assert.That(animationInstance.Children[0].Animation, Is.EqualTo(animation1));
            Assert.That(animationInstance.Children[1], Is.TypeOf <AnimationInstance>());
            Assert.That(animationInstance.Children[1].Animation, Is.EqualTo(childGroup));
            Assert.That(animationInstance.Children[1].Children[0], Is.TypeOf <AnimationInstance <float> >());
            Assert.That(animationInstance.Children[1].Children[0].Animation, Is.EqualTo(animation2));
            Assert.That(animationInstance.Children[1].Children[1], Is.TypeOf <AnimationInstance <float> >());
            Assert.That(animationInstance.Children[1].Children[1].Animation, Is.EqualTo(animation3));
        }
Пример #5
0
        public void GetDefaultDurationTest()
        {
            var timelineGroup = new TimelineGroup();
              var animation = new Vector2FAnimation();
              var animation2 = new AnimationClip<float>
              {
            Animation = new SingleFromToByAnimation(),
            Delay = TimeSpan.FromSeconds(10),
              };
              var animation3 = new AnimationClip<float>
              {
            Animation = new SingleFromToByAnimation(),
            Delay = TimeSpan.FromSeconds(8),
            Duration = TimeSpan.FromSeconds(4),
              };

              Assert.AreEqual(TimeSpan.FromSeconds(0.0), timelineGroup.GetTotalDuration());

              timelineGroup.Add(animation);
              Assert.AreEqual(TimeSpan.FromSeconds(0.0), timelineGroup.GetTotalDuration());

              timelineGroup.Add(animation2);
              Assert.AreEqual(TimeSpan.FromSeconds(11.0), timelineGroup.GetTotalDuration());

              timelineGroup.Add(animation3);
              Assert.AreEqual(TimeSpan.FromSeconds(12.0), timelineGroup.GetTotalDuration());
        }
Пример #6
0
        public void CreateInstanceTest()
        {
            var animation1 = new SingleFromToByAnimation();
              var animation2 = new SingleFromToByAnimation();
              var animation3 = new SingleFromToByAnimation();

              var childGroup = new TimelineGroup();
              childGroup.Add(animation2);
              childGroup.Add(animation3);

              var rootGroup = new TimelineGroup();
              rootGroup.Add(animation1);
              rootGroup.Add(childGroup);

              var animationInstance = rootGroup.CreateInstance();
              Assert.IsNotNull(animationInstance);
              Assert.AreEqual(2, animationInstance.Children.Count);
              Assert.That(animationInstance.Children[0], Is.TypeOf<AnimationInstance<float>>());
              Assert.That(animationInstance.Children[0].Animation, Is.EqualTo(animation1));
              Assert.That(animationInstance.Children[1], Is.TypeOf<AnimationInstance>());
              Assert.That(animationInstance.Children[1].Animation, Is.EqualTo(childGroup));
              Assert.That(animationInstance.Children[1].Children[0], Is.TypeOf<AnimationInstance<float>>());
              Assert.That(animationInstance.Children[1].Children[0].Animation, Is.EqualTo(animation2));
              Assert.That(animationInstance.Children[1].Children[1], Is.TypeOf<AnimationInstance<float>>());
              Assert.That(animationInstance.Children[1].Children[1].Animation, Is.EqualTo(animation3));
        }
Пример #7
0
        public void AnimateProperty()
        {
            var property = new AnimatableProperty <float> {
                Value = 10.0f
            };

            var animationA = new SingleFromToByAnimation
            {
                From           = 100.0f,
                To             = 200.0f,
                TargetObject   = "ObjectA",   // Should be ignored.
                TargetProperty = "PropertyA", // Should be ignored.
            };
            var animationB = new SingleFromToByAnimation
            {
                From           = 200.0f,
                To             = 300.0f,
                TargetObject   = "ObjectB",   // Should be ignored.
                TargetProperty = "PropertyB", // Should be ignored.
            };
            var animationGroup = new TimelineGroup();

            animationGroup.Add(animationA);
            animationGroup.Add(animationB);

            var manager = new AnimationManager();

            // Should assign both animations to 'property'.
            var controller = manager.CreateController(animationGroup, property);

            Assert.AreEqual(property, ((AnimationInstance <float>)controller.AnimationInstance.Children[0]).Property);
            Assert.AreEqual(property, ((AnimationInstance <float>)controller.AnimationInstance.Children[1]).Property);
            Assert.IsFalse(manager.IsAnimated(property));

            // When started then animationB (last in the composition chain) should be active.
            controller.Start();
            controller.UpdateAndApply();
            Assert.AreEqual(200.0f, property.Value);
            Assert.IsTrue(manager.IsAnimated(property));

            controller.Stop();
            controller.UpdateAndApply();
            Assert.AreEqual(10.0f, property.Value);
            Assert.IsFalse(manager.IsAnimated(property));

            // Same test for AnimationManager.StartAnimation()
            controller = manager.StartAnimation(animationGroup, property);
            controller.UpdateAndApply();
            Assert.AreEqual(property, ((AnimationInstance <float>)controller.AnimationInstance.Children[0]).Property);
            Assert.AreEqual(property, ((AnimationInstance <float>)controller.AnimationInstance.Children[1]).Property);
            Assert.AreEqual(200.0f, property.Value);
            Assert.IsTrue(manager.IsAnimated(property));

            manager.StopAnimation(property);
            manager.UpdateAndApplyAnimation(property);
            Assert.AreEqual(10.0f, property.Value);
            Assert.IsFalse(manager.IsAnimated(property));
        }
Пример #8
0
        // The following code contains two helper methods to animate the opacity and offset
        // of a group of UI controls. The methods basically do the same, they animate the
        // properties from/to a specific value. However the methods demonstrate two different
        // approaches.
        //
        // The AnimateFrom method uses a more direct approach. It directly starts an
        // animation for each UI control in list, thereby creating several independently
        // running animations.
        //
        // The AnimateTo method uses a more declarative approach. All animations are
        // defined and assigned to the target objects by setting the name of the UI control
        // in the TargetObject property. Then all animations are grouped together into
        // a single animation. When the resulting animation is started the animation system
        // creates the required animation instances and assigns the instances to the correct
        // objects and properties by matching the TargetObject and TargetProperty with the
        // name of the UI controls and their properties.
        //
        // Both methods achieve a similar result. The advantage of the first method is more
        // direct control. The advantage of the seconds method is that only a single animation
        // controller is required to control all animations at once.

        /// <summary>
        /// Animates the opacity and offset of a group of controls from the specified value to their
        /// current value.
        /// </summary>
        /// <param name="controls">The UI controls to be animated.</param>
        /// <param name="opacity">The initial opacity.</param>
        /// <param name="offset">The initial offset.</param>
        private void AnimateFrom(IList <UIControl> controls, float opacity, Vector2F offset)
        {
            TimeSpan duration = TimeSpan.FromSeconds(0.8);

            // First, let's define the animation that is going to be applied to a control.
            // Animate the "Opacity" from the specified value to its current value.
            var opacityAnimation = new SingleFromToByAnimation
            {
                TargetProperty = "Opacity",
                From           = opacity,
                Duration       = duration,
                EasingFunction = new CubicEase {
                    Mode = EasingMode.EaseOut
                },
            };

            // Animate the "RenderTranslation" property from the specified offset to its
            // its current value, which is usually (0, 0).
            var offsetAnimation = new Vector2FFromToByAnimation
            {
                TargetProperty = "RenderTranslation",
                From           = offset,
                Duration       = duration,
                EasingFunction = new CubicEase {
                    Mode = EasingMode.EaseOut
                },
            };

            // Group the opacity and offset animation together using a TimelineGroup.
            var timelineGroup = new TimelineGroup();

            timelineGroup.Add(opacityAnimation);
            timelineGroup.Add(offsetAnimation);

            // Run the animation on each control using a negative delay to give the first controls
            // a slight head start.
            var numberOfControls = controls.Count;

            for (int i = 0; i < controls.Count; i++)
            {
                var clip = new TimelineClip(timelineGroup)
                {
                    Delay        = TimeSpan.FromSeconds(-0.04 * (numberOfControls - i)),
                    FillBehavior = FillBehavior.Stop, // Stop and remove the animation when it is done.
                };
                var animationController = AnimationService.StartAnimation(clip, controls[i]);

                animationController.UpdateAndApply();

                // Enable "auto-recycling" to ensure that the animation resources are recycled once
                // the animation stops or the target objects are garbage collected.
                animationController.AutoRecycle();
            }
        }
        public CharacterCrossFadeSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            var modelNode = ContentManager.Load <ModelNode>("Marine/PlayerMarine");

            _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            SampleHelper.EnablePerPixelLighting(_meshNode);
            GraphicsScreen.Scene.Children.Add(_meshNode);

            Dictionary <string, SkeletonKeyFrameAnimation> animations = _meshNode.Mesh.Animations;

            // Create a looping 'Idle' animation.
            _idleAnimation = new AnimationClip <SkeletonPose>(animations["Idle"])
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            // Create a looping 'Run' animation.
            _runAnimation = new AnimationClip <SkeletonPose>(animations["Run"])
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            // Combine the 'Aim' and 'Shoot' animation. The 'Aim' animation should start immediately.
            // The 'Shoot' animation should start after 0.3 seconds.
            // (Animations can be combined by creating timeline groups. All timelines/animations
            // in a timeline group are played simultaneously. AnimationClips can be used to
            // arrange animations on a timeline. The property Delay, for example, can be used to
            // set the begin time.)
            _aimAndShootAnimation = new TimelineGroup();
            _aimAndShootAnimation.Add(animations["Aim"]);
            _aimAndShootAnimation.Add(new AnimationClip <SkeletonPose>(animations["Shoot"])
            {
                Delay = TimeSpan.FromSeconds(0.3)
            });

            // Start 'Idle' animation. We use a Replace transition with a fade-in.
            _idleAnimationController = AnimationService.StartAnimation(
                _idleAnimation,
                (IAnimatableProperty)_meshNode.SkeletonPose,
                AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)));

            _idleAnimationController.AutoRecycle();
        }
Пример #10
0
    public CharacterCrossFadeSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Marine/PlayerMarine");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      Dictionary<string, SkeletonKeyFrameAnimation> animations = _meshNode.Mesh.Animations;

      // Create a looping 'Idle' animation.
      _idleAnimation = new AnimationClip<SkeletonPose>(animations["Idle"])
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Create a looping 'Run' animation.
      _runAnimation = new AnimationClip<SkeletonPose>(animations["Run"])
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Combine the 'Aim' and 'Shoot' animation. The 'Aim' animation should start immediately. 
      // The 'Shoot' animation should start after 0.3 seconds.
      // (Animations can be combined by creating timeline groups. All timelines/animations 
      // in a timeline group are played simultaneously. AnimationClips can be used to 
      // arrange animations on a timeline. The property Delay, for example, can be used to
      // set the begin time.)
      _aimAndShootAnimation = new TimelineGroup();
      _aimAndShootAnimation.Add(animations["Aim"]);
      _aimAndShootAnimation.Add(new AnimationClip<SkeletonPose>(animations["Shoot"]) { Delay = TimeSpan.FromSeconds(0.3) });

      // Start 'Idle' animation. We use a Replace transition with a fade-in.
      _idleAnimationController = AnimationService.StartAnimation(
        _idleAnimation,
        (IAnimatableProperty)_meshNode.SkeletonPose,
        AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)));

      _idleAnimationController.AutoRecycle();
    }
Пример #11
0
        public void GetRoot()
        {
            var animationA = new TimelineGroup();
            var animationB = new SingleFromToByAnimation();
            var animationC = new SingleFromToByAnimation();
            var animationD = new TimelineGroup();
            var animationE = new TimelineGroup();
            var animationF = new SingleFromToByAnimation();
            var animationG = new TimelineGroup();

            animationA.Add(animationB);
            animationA.Add(animationC);
            animationA.Add(animationD);
            animationD.Add(animationE);
            animationD.Add(animationF);
            animationE.Add(animationG);

            Assert.That(() => AnimationHelper.GetRoot(null), Throws.TypeOf <ArgumentNullException>());

            var animationInstance = animationA.CreateInstance();

            Assert.AreEqual(animationInstance, animationInstance.GetRoot());
            Assert.AreEqual(animationInstance, animationInstance.Children[2].Children[0].GetRoot());
        }
Пример #12
0
        public void AnimateObjects()
        {
            var objectA    = new AnimatableObject("ObjectA");
            var propertyA1 = new AnimatableProperty <float> {
                Value = 10.0f
            };

            objectA.Properties.Add("Value", propertyA1);
            var propertyA2 = new AnimatableProperty <float> {
                Value = 20.0f
            };

            objectA.Properties.Add("Value2", propertyA2);

            var objectB   = new AnimatableObject("ObjectB");
            var propertyB = new AnimatableProperty <float> {
                Value = 30.0f
            };

            objectB.Properties.Add("Value", propertyB);

            var objectC   = new AnimatableObject("ObjectC");
            var propertyC = new AnimatableProperty <float> {
                Value = 40.0f
            };

            objectC.Properties.Add("Value", propertyC);

            var animationA1 = new SingleFromToByAnimation // Should be assigned to ObjectA
            {
                From           = 100.0f,
                To             = 200.0f,
                TargetObject   = "ObjectXyz",             // Ignored because ObjectA is selected by animationGroup1.
                TargetProperty = "Value",                 // Required.
            };
            var animationA2 = new SingleFromToByAnimation // Should be assigned to ObjectA
            {
                From           = 200.0f,
                To             = 300.0f,
                TargetObject   = "ObjectB",                 // Ignored because ObjectA is selected by animationGroup1.
                TargetProperty = "Value",                   // Required.
            };
            var animationA3 = new Vector3FFromToByAnimation // Ignored because of incompatible type.
            {
                From           = new Vector3F(300.0f),
                To             = new Vector3F(400.0f),
                TargetObject   = "ObjectA",
                TargetProperty = "Value",
            };
            var animationA4 = new SingleFromToByAnimation // Ignored because TargetProperty is not set.
            {
                From           = 400.0f,
                To             = 500.0f,
                TargetObject   = "",
                TargetProperty = "",
            };
            var animationGroupA = new TimelineGroup {
                TargetObject = "ObjectA"
            };

            animationGroupA.Add(animationA1);
            animationGroupA.Add(animationA2);
            animationGroupA.Add(animationA3);
            animationGroupA.Add(animationA4);

            var animationB1 = new SingleFromToByAnimation // Should be assigned to ObjectB
            {
                From           = 100.0f,
                To             = 200.0f,
                TargetObject   = "ObjectB",
                TargetProperty = "Value",
            };
            var animationA5 = new SingleFromToByAnimation
            {
                From           = 600.0f,
                To             = 700.0f,
                TargetObject   = "",
                TargetProperty = "Value",
            };

            var animationGroupRoot = new TimelineGroup();

            animationGroupRoot.Add(animationGroupA);
            animationGroupRoot.Add(animationB1);
            animationGroupRoot.Add(animationA5);

            var manager = new AnimationManager();

            // CreateController()
            var controller = manager.CreateController(animationGroupRoot, new[] { objectA, objectB, objectC });

            Assert.AreEqual(propertyA1, ((AnimationInstance <float>)controller.AnimationInstance.Children[0].Children[0]).Property);
            Assert.AreEqual(propertyA1, ((AnimationInstance <float>)controller.AnimationInstance.Children[0].Children[1]).Property);
            Assert.AreEqual(null, ((AnimationInstance <Vector3F>)controller.AnimationInstance.Children[0].Children[2]).Property);
            Assert.AreEqual(null, ((AnimationInstance <float>)controller.AnimationInstance.Children[0].Children[3]).Property);
            Assert.AreEqual(propertyB, ((AnimationInstance <float>)controller.AnimationInstance.Children[1]).Property);
            Assert.AreEqual(propertyA1, ((AnimationInstance <float>)controller.AnimationInstance.Children[2]).Property);
            Assert.AreEqual(10.0f, propertyA1.Value);
            Assert.AreEqual(20.0f, propertyA2.Value);
            Assert.AreEqual(30.0f, propertyB.Value);
            Assert.AreEqual(40.0f, propertyC.Value);
            Assert.IsFalse(manager.IsAnimated(objectA));
            Assert.IsFalse(manager.IsAnimated(propertyA1));
            Assert.IsFalse(manager.IsAnimated(propertyA2));
            Assert.IsFalse(manager.IsAnimated(objectB));
            Assert.IsFalse(manager.IsAnimated(propertyB));
            Assert.IsFalse(manager.IsAnimated(objectC));
            Assert.IsFalse(manager.IsAnimated(propertyC));

            controller.Start();
            controller.UpdateAndApply();
            Assert.AreEqual(600.0f, propertyA1.Value);
            Assert.AreEqual(20.0f, propertyA2.Value);
            Assert.AreEqual(100.0f, propertyB.Value);
            Assert.AreEqual(40.0f, propertyC.Value);
            Assert.IsTrue(manager.IsAnimated(objectA));
            Assert.IsTrue(manager.IsAnimated(propertyA1));
            Assert.IsFalse(manager.IsAnimated(propertyA2));
            Assert.IsTrue(manager.IsAnimated(objectB));
            Assert.IsTrue(manager.IsAnimated(propertyB));
            Assert.IsFalse(manager.IsAnimated(objectC));
            Assert.IsFalse(manager.IsAnimated(propertyC));

            controller.Stop();
            controller.UpdateAndApply();
            Assert.AreEqual(10.0f, propertyA1.Value);
            Assert.AreEqual(20.0f, propertyA2.Value);
            Assert.AreEqual(30.0f, propertyB.Value);
            Assert.AreEqual(40.0f, propertyC.Value);
            Assert.IsFalse(manager.IsAnimated(objectA));
            Assert.IsFalse(manager.IsAnimated(propertyA1));
            Assert.IsFalse(manager.IsAnimated(propertyA2));
            Assert.IsFalse(manager.IsAnimated(objectB));
            Assert.IsFalse(manager.IsAnimated(propertyB));
            Assert.IsFalse(manager.IsAnimated(objectC));
            Assert.IsFalse(manager.IsAnimated(propertyC));

            // StartAnimation()
            controller = manager.StartAnimation(animationGroupRoot, new[] { objectA, objectB, objectC });
            controller.UpdateAndApply();
            Assert.AreEqual(propertyA1, ((AnimationInstance <float>)controller.AnimationInstance.Children[0].Children[0]).Property);
            Assert.AreEqual(propertyA1, ((AnimationInstance <float>)controller.AnimationInstance.Children[0].Children[1]).Property);
            Assert.AreEqual(null, ((AnimationInstance <Vector3F>)controller.AnimationInstance.Children[0].Children[2]).Property);
            Assert.AreEqual(null, ((AnimationInstance <float>)controller.AnimationInstance.Children[0].Children[3]).Property);
            Assert.AreEqual(propertyB, ((AnimationInstance <float>)controller.AnimationInstance.Children[1]).Property);
            Assert.AreEqual(propertyA1, ((AnimationInstance <float>)controller.AnimationInstance.Children[2]).Property);
            Assert.AreEqual(600.0f, propertyA1.Value);
            Assert.AreEqual(20.0f, propertyA2.Value);
            Assert.AreEqual(100.0f, propertyB.Value);
            Assert.AreEqual(40.0f, propertyC.Value);
            Assert.IsTrue(manager.IsAnimated(objectA));
            Assert.IsTrue(manager.IsAnimated(propertyA1));
            Assert.IsFalse(manager.IsAnimated(propertyA2));
            Assert.IsTrue(manager.IsAnimated(objectB));
            Assert.IsTrue(manager.IsAnimated(propertyB));
            Assert.IsFalse(manager.IsAnimated(objectC));
            Assert.IsFalse(manager.IsAnimated(propertyC));

            manager.StopAnimation(new[] { objectA, objectB, objectC });
            manager.UpdateAndApplyAnimation(new[] { objectA, objectB, objectC });
            Assert.AreEqual(10.0f, propertyA1.Value);
            Assert.AreEqual(20.0f, propertyA2.Value);
            Assert.AreEqual(30.0f, propertyB.Value);
            Assert.AreEqual(40.0f, propertyC.Value);
            Assert.IsFalse(manager.IsAnimated(objectA));
            Assert.IsFalse(manager.IsAnimated(propertyA1));
            Assert.IsFalse(manager.IsAnimated(propertyA2));
            Assert.IsFalse(manager.IsAnimated(objectB));
            Assert.IsFalse(manager.IsAnimated(propertyB));
            Assert.IsFalse(manager.IsAnimated(objectC));
            Assert.IsFalse(manager.IsAnimated(propertyC));
        }
Пример #13
0
        public void AnimateObject()
        {
            var obj      = new AnimatableObject("TestObject");
            var property = new AnimatableProperty <float> {
                Value = 10.0f
            };

            obj.Properties.Add("Value", property);
            var property2 = new AnimatableProperty <float> {
                Value = 20.0f
            };

            obj.Properties.Add("Value2", property2);

            var animationA = new SingleFromToByAnimation
            {
                From           = 100.0f,
                To             = 200.0f,
                TargetObject   = "ObjectA", // Should be ignored.
                TargetProperty = "Value",
            };
            var animationB = new SingleFromToByAnimation
            {
                From           = 200.0f,
                To             = 300.0f,
                TargetObject   = "ObjectB", // Should be ignored.
                TargetProperty = "",
            };
            var animationGroup = new TimelineGroup();

            animationGroup.Add(animationA);
            animationGroup.Add(animationB);

            var manager = new AnimationManager();

            // Should assign animationA to 'obj'.
            var controller = manager.CreateController(animationGroup, obj);

            Assert.AreEqual(property, ((AnimationInstance <float>)controller.AnimationInstance.Children[0]).Property);
            Assert.AreEqual(null, ((AnimationInstance <float>)controller.AnimationInstance.Children[1]).Property);
            Assert.IsFalse(manager.IsAnimated(property));
            Assert.IsFalse(manager.IsAnimated(property2));
            Assert.IsFalse(manager.IsAnimated(obj));

            // When started then animationA should be active.
            controller.Start();
            controller.UpdateAndApply();
            Assert.AreEqual(100.0f, property.Value);
            Assert.AreEqual(20.0f, property2.Value);
            Assert.IsTrue(manager.IsAnimated(obj));
            Assert.IsTrue(manager.IsAnimated(property));
            Assert.IsFalse(manager.IsAnimated(property2));

            controller.Stop();
            controller.UpdateAndApply();
            Assert.AreEqual(10.0f, property.Value);
            Assert.AreEqual(20.0f, property2.Value);
            Assert.IsFalse(manager.IsAnimated(obj));
            Assert.IsFalse(manager.IsAnimated(property));
            Assert.IsFalse(manager.IsAnimated(property2));

            // Same test for AnimationManager.StartAnimation()
            controller = manager.StartAnimation(animationGroup, obj);
            controller.UpdateAndApply();
            Assert.AreEqual(property, ((AnimationInstance <float>)controller.AnimationInstance.Children[0]).Property);
            Assert.AreEqual(null, ((AnimationInstance <float>)controller.AnimationInstance.Children[1]).Property);
            Assert.AreEqual(100.0f, property.Value);
            Assert.AreEqual(20.0f, property2.Value);
            Assert.IsTrue(manager.IsAnimated(obj));
            Assert.IsTrue(manager.IsAnimated(property));
            Assert.IsFalse(manager.IsAnimated(property2));

            manager.StopAnimation(obj);
            manager.UpdateAndApplyAnimation(obj);
            Assert.AreEqual(10.0f, property.Value);
            Assert.AreEqual(20.0f, property2.Value);
            Assert.IsFalse(manager.IsAnimated(obj));
            Assert.IsFalse(manager.IsAnimated(property));
            Assert.IsFalse(manager.IsAnimated(property2));
        }
Пример #14
0
    /// <summary>
    /// Animates the opacity and offset of a group of controls from their current value to the 
    /// specified value.
    /// </summary>
    /// <param name="controls">The UI controls to be animated.</param>
    /// <param name="opacity">The opacity.</param>
    /// <param name="offset">The offset.</param>
    private AnimationController AnimateTo(IList<UIControl> controls, float opacity, Vector2F offset)
    {
      TimeSpan duration = TimeSpan.FromSeconds(0.6f);

      // First, let's define the animation that is going to be applied to a control.
      // Animate the "Opacity" from its current value to the specified value.
      var opacityAnimation = new SingleFromToByAnimation
      {
        TargetProperty = "Opacity",
        To = opacity,
        Duration = duration,
        EasingFunction = new CubicEase { Mode = EasingMode.EaseIn },
      };

      // Animate the "RenderTranslation" property from its current value, which is 
      // usually (0, 0), to the specified value.
      var offsetAnimation = new Vector2FFromToByAnimation
      {
        TargetProperty = "RenderTranslation",
        To = offset,
        Duration = duration,
        EasingFunction = new CubicEase { Mode = EasingMode.EaseIn },
      };

      // Group the opacity and offset animation together using a TimelineGroup.
      var timelineGroup = new TimelineGroup();
      timelineGroup.Add(opacityAnimation);
      timelineGroup.Add(offsetAnimation);

      // Now we duplicate this animation by creating new TimelineClips that wrap the TimelineGroup.
      // A TimelineClip is assigned to a target by setting the TargetObject property.
      var storyboard = new TimelineGroup();

      for (int i = 0; i < controls.Count; i++)
      {
        var clip = new TimelineClip(timelineGroup)
        {
          TargetObject = controls[i].Name,  // Assign the clip to the i-th control.
          Delay = TimeSpan.FromSeconds(0.04f * i),
          FillBehavior = FillBehavior.Hold, // Hold the last value of the animation when it            
        };                                  // because we don't want to opacity and offset to
        // jump back to their original value.
        storyboard.Add(clip);
      }

      // Now we apply the "storyboard" to the group of UI controls. The animation system
      // will automatically assign individual animations to the right objects and 
      // properties.
#if !XBOX && !WP7
      var animationController = AnimationService.StartAnimation(storyboard, controls);
#else
      var animationController = AnimationService.StartAnimation(storyboard, controls.Cast<IAnimatableObject>());
#endif

      animationController.UpdateAndApply();

      // The returned animation controller can be used to start, stop, pause, ... all
      // animations at once. (Note that we don't set AutoRecycle here, because we will 
      // explicitly stop and recycle the animations in the code above.)
      return animationController;
    }
Пример #15
0
        protected override void LoadContent()
        {
            _model = Game.Content.Load<Model>("PlayerMarine");
              var additionalData = (Dictionary<string, object>)_model.Tag;
              var skeleton = (Skeleton)additionalData["Skeleton"];
              _skeletonPose = SkeletonPose.Create(skeleton);
              var animations = (Dictionary<string, SkeletonKeyFrameAnimation>)additionalData["Animations"];

              // Create a looping 'Idle' animation.
              _idleAnimation = new AnimationClip<SkeletonPose>(animations["Idle"])
              {
            LoopBehavior = LoopBehavior.Cycle,
            Duration = TimeSpan.MaxValue,
              };

              // Create a looping 'Run' animation.
              _runAnimation = new AnimationClip<SkeletonPose>(animations["Run"])
              {
            LoopBehavior = LoopBehavior.Cycle,
            Duration = TimeSpan.MaxValue,
              };

              // Combine the 'Aim' and 'Shoot' animation. The 'Aim' animation should start immediately.
              // The 'Shoot' animation should start after 0.3 seconds.
              // (Animations can be combined by creating timeline groups. All timelines/animations
              // in a timeline group are played simultaneously. AnimationClips can be used to
              // arrange animations on a timeline. The property Delay, for example, can be used to
              // set the begin time.)
              _aimAndShootAnimation = new TimelineGroup();
              _aimAndShootAnimation.Add(animations["Aim"]);
              _aimAndShootAnimation.Add(new AnimationClip<SkeletonPose>(animations["Shoot"]) { Delay = TimeSpan.FromSeconds(0.3) });

              // Start 'Idle' animation. We use a Replace transition with a fade-in.
              _idleAnimationController = AnimationService.StartAnimation(
            _idleAnimation,
            (IAnimatableProperty)_skeletonPose,
            AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)));

              _idleAnimationController.AutoRecycle();

              base.LoadContent();
        }
Пример #16
0
        public void AnimateObject()
        {
            var obj = new AnimatableObject("TestObject");
              var property = new AnimatableProperty<float> { Value = 10.0f };
              obj.Properties.Add("Value", property);
              var property2 = new AnimatableProperty<float> { Value = 20.0f };
              obj.Properties.Add("Value2", property2);

              var animationA = new SingleFromToByAnimation
              {
            From = 100.0f,
            To = 200.0f,
            TargetObject = "ObjectA",     // Should be ignored.
            TargetProperty = "Value",
              };
              var animationB = new SingleFromToByAnimation
              {
            From = 200.0f,
            To = 300.0f,
            TargetObject = "ObjectB",     // Should be ignored.
            TargetProperty = "",
              };
              var animationGroup = new TimelineGroup();
              animationGroup.Add(animationA);
              animationGroup.Add(animationB);

              var manager = new AnimationManager();

              // Should assign animationA to 'obj'.
              var controller = manager.CreateController(animationGroup, obj);
              Assert.AreEqual(property, ((AnimationInstance<float>)controller.AnimationInstance.Children[0]).Property);
              Assert.AreEqual(null, ((AnimationInstance<float>)controller.AnimationInstance.Children[1]).Property);
              Assert.IsFalse(manager.IsAnimated(property));
              Assert.IsFalse(manager.IsAnimated(property2));
              Assert.IsFalse(manager.IsAnimated(obj));

              // When started then animationA should be active.
              controller.Start();
              controller.UpdateAndApply();
              Assert.AreEqual(100.0f, property.Value);
              Assert.AreEqual(20.0f, property2.Value);
              Assert.IsTrue(manager.IsAnimated(obj));
              Assert.IsTrue(manager.IsAnimated(property));
              Assert.IsFalse(manager.IsAnimated(property2));

              controller.Stop();
              controller.UpdateAndApply();
              Assert.AreEqual(10.0f, property.Value);
              Assert.AreEqual(20.0f, property2.Value);
              Assert.IsFalse(manager.IsAnimated(obj));
              Assert.IsFalse(manager.IsAnimated(property));
              Assert.IsFalse(manager.IsAnimated(property2));

              // Same test for AnimationManager.StartAnimation()
              controller = manager.StartAnimation(animationGroup, obj);
              controller.UpdateAndApply();
              Assert.AreEqual(property, ((AnimationInstance<float>)controller.AnimationInstance.Children[0]).Property);
              Assert.AreEqual(null, ((AnimationInstance<float>)controller.AnimationInstance.Children[1]).Property);
              Assert.AreEqual(100.0f, property.Value);
              Assert.AreEqual(20.0f, property2.Value);
              Assert.IsTrue(manager.IsAnimated(obj));
              Assert.IsTrue(manager.IsAnimated(property));
              Assert.IsFalse(manager.IsAnimated(property2));

              manager.StopAnimation(obj);
              manager.UpdateAndApplyAnimation(obj);
              Assert.AreEqual(10.0f, property.Value);
              Assert.AreEqual(20.0f, property2.Value);
              Assert.IsFalse(manager.IsAnimated(obj));
              Assert.IsFalse(manager.IsAnimated(property));
              Assert.IsFalse(manager.IsAnimated(property2));
        }
Пример #17
0
        public void AnimateProperty()
        {
            var property = new AnimatableProperty<float> { Value = 10.0f };

              var animationA = new SingleFromToByAnimation
              {
            From = 100.0f,
            To = 200.0f,
            TargetObject = "ObjectA",     // Should be ignored.
            TargetProperty = "PropertyA", // Should be ignored.
              };
              var animationB = new SingleFromToByAnimation
              {
            From = 200.0f,
            To = 300.0f,
            TargetObject = "ObjectB",     // Should be ignored.
            TargetProperty = "PropertyB", // Should be ignored.
              };
              var animationGroup = new TimelineGroup();
              animationGroup.Add(animationA);
              animationGroup.Add(animationB);

              var manager = new AnimationManager();

              // Should assign both animations to 'property'.
              var controller = manager.CreateController(animationGroup, property);
              Assert.AreEqual(property, ((AnimationInstance<float>)controller.AnimationInstance.Children[0]).Property);
              Assert.AreEqual(property, ((AnimationInstance<float>)controller.AnimationInstance.Children[1]).Property);
              Assert.IsFalse(manager.IsAnimated(property));

              // When started then animationB (last in the composition chain) should be active.
              controller.Start();
              controller.UpdateAndApply();
              Assert.AreEqual(200.0f, property.Value);
              Assert.IsTrue(manager.IsAnimated(property));

              controller.Stop();
              controller.UpdateAndApply();
              Assert.AreEqual(10.0f, property.Value);
              Assert.IsFalse(manager.IsAnimated(property));

              // Same test for AnimationManager.StartAnimation()
              controller = manager.StartAnimation(animationGroup, property);
              controller.UpdateAndApply();
              Assert.AreEqual(property, ((AnimationInstance<float>)controller.AnimationInstance.Children[0]).Property);
              Assert.AreEqual(property, ((AnimationInstance<float>)controller.AnimationInstance.Children[1]).Property);
              Assert.AreEqual(200.0f, property.Value);
              Assert.IsTrue(manager.IsAnimated(property));

              manager.StopAnimation(property);
              manager.UpdateAndApplyAnimation(property);
              Assert.AreEqual(10.0f, property.Value);
              Assert.IsFalse(manager.IsAnimated(property));
        }
Пример #18
0
        public void AnimateObjects()
        {
            var objectA = new AnimatableObject("ObjectA");
              var propertyA1 = new AnimatableProperty<float> { Value = 10.0f };
              objectA.Properties.Add("Value", propertyA1);
              var propertyA2 = new AnimatableProperty<float> { Value = 20.0f };
              objectA.Properties.Add("Value2", propertyA2);

              var objectB = new AnimatableObject("ObjectB");
              var propertyB = new AnimatableProperty<float> { Value = 30.0f };
              objectB.Properties.Add("Value", propertyB);

              var objectC = new AnimatableObject("ObjectC");
              var propertyC = new AnimatableProperty<float> { Value = 40.0f };
              objectC.Properties.Add("Value", propertyC);

              var animationA1 = new SingleFromToByAnimation // Should be assigned to ObjectA
              {
            From = 100.0f,
            To = 200.0f,
            TargetObject = "ObjectXyz", // Ignored because ObjectA is selected by animationGroup1.
            TargetProperty = "Value",   // Required.
              };
              var animationA2 = new SingleFromToByAnimation // Should be assigned to ObjectA
              {
            From = 200.0f,
            To = 300.0f,
            TargetObject = "ObjectB",   // Ignored because ObjectA is selected by animationGroup1.
            TargetProperty = "Value",   // Required.
              };
              var animationA3 = new Vector3FFromToByAnimation // Ignored because of incompatible type.
              {
            From = new Vector3F(300.0f),
            To = new Vector3F(400.0f),
            TargetObject = "ObjectA",
            TargetProperty = "Value",
              };
              var animationA4 = new SingleFromToByAnimation   // Ignored because TargetProperty is not set.
              {
            From = 400.0f,
            To = 500.0f,
            TargetObject = "",
            TargetProperty = "",
              };
              var animationGroupA = new TimelineGroup { TargetObject = "ObjectA" };
              animationGroupA.Add(animationA1);
              animationGroupA.Add(animationA2);
              animationGroupA.Add(animationA3);
              animationGroupA.Add(animationA4);

              var animationB1 = new SingleFromToByAnimation // Should be assigned to ObjectB
              {
            From = 100.0f,
            To = 200.0f,
            TargetObject = "ObjectB",
            TargetProperty = "Value",
              };
              var animationA5 = new SingleFromToByAnimation
              {
            From = 600.0f,
            To = 700.0f,
            TargetObject = "",
            TargetProperty = "Value",
              };

              var animationGroupRoot = new TimelineGroup();
              animationGroupRoot.Add(animationGroupA);
              animationGroupRoot.Add(animationB1);
              animationGroupRoot.Add(animationA5);

              var manager = new AnimationManager();

              // CreateController()
              var controller = manager.CreateController(animationGroupRoot, new[] { objectA, objectB, objectC });
              Assert.AreEqual(propertyA1, ((AnimationInstance<float>)controller.AnimationInstance.Children[0].Children[0]).Property);
              Assert.AreEqual(propertyA1, ((AnimationInstance<float>)controller.AnimationInstance.Children[0].Children[1]).Property);
              Assert.AreEqual(null, ((AnimationInstance<Vector3F>)controller.AnimationInstance.Children[0].Children[2]).Property);
              Assert.AreEqual(null, ((AnimationInstance<float>)controller.AnimationInstance.Children[0].Children[3]).Property);
              Assert.AreEqual(propertyB, ((AnimationInstance<float>)controller.AnimationInstance.Children[1]).Property);
              Assert.AreEqual(propertyA1, ((AnimationInstance<float>)controller.AnimationInstance.Children[2]).Property);
              Assert.AreEqual(10.0f, propertyA1.Value);
              Assert.AreEqual(20.0f, propertyA2.Value);
              Assert.AreEqual(30.0f, propertyB.Value);
              Assert.AreEqual(40.0f, propertyC.Value);
              Assert.IsFalse(manager.IsAnimated(objectA));
              Assert.IsFalse(manager.IsAnimated(propertyA1));
              Assert.IsFalse(manager.IsAnimated(propertyA2));
              Assert.IsFalse(manager.IsAnimated(objectB));
              Assert.IsFalse(manager.IsAnimated(propertyB));
              Assert.IsFalse(manager.IsAnimated(objectC));
              Assert.IsFalse(manager.IsAnimated(propertyC));

              controller.Start();
              controller.UpdateAndApply();
              Assert.AreEqual(600.0f, propertyA1.Value);
              Assert.AreEqual(20.0f, propertyA2.Value);
              Assert.AreEqual(100.0f, propertyB.Value);
              Assert.AreEqual(40.0f, propertyC.Value);
              Assert.IsTrue(manager.IsAnimated(objectA));
              Assert.IsTrue(manager.IsAnimated(propertyA1));
              Assert.IsFalse(manager.IsAnimated(propertyA2));
              Assert.IsTrue(manager.IsAnimated(objectB));
              Assert.IsTrue(manager.IsAnimated(propertyB));
              Assert.IsFalse(manager.IsAnimated(objectC));
              Assert.IsFalse(manager.IsAnimated(propertyC));

              controller.Stop();
              controller.UpdateAndApply();
              Assert.AreEqual(10.0f, propertyA1.Value);
              Assert.AreEqual(20.0f, propertyA2.Value);
              Assert.AreEqual(30.0f, propertyB.Value);
              Assert.AreEqual(40.0f, propertyC.Value);
              Assert.IsFalse(manager.IsAnimated(objectA));
              Assert.IsFalse(manager.IsAnimated(propertyA1));
              Assert.IsFalse(manager.IsAnimated(propertyA2));
              Assert.IsFalse(manager.IsAnimated(objectB));
              Assert.IsFalse(manager.IsAnimated(propertyB));
              Assert.IsFalse(manager.IsAnimated(objectC));
              Assert.IsFalse(manager.IsAnimated(propertyC));

              // StartAnimation()
              controller = manager.StartAnimation(animationGroupRoot, new[] { objectA, objectB, objectC });
              controller.UpdateAndApply();
              Assert.AreEqual(propertyA1, ((AnimationInstance<float>)controller.AnimationInstance.Children[0].Children[0]).Property);
              Assert.AreEqual(propertyA1, ((AnimationInstance<float>)controller.AnimationInstance.Children[0].Children[1]).Property);
              Assert.AreEqual(null, ((AnimationInstance<Vector3F>)controller.AnimationInstance.Children[0].Children[2]).Property);
              Assert.AreEqual(null, ((AnimationInstance<float>)controller.AnimationInstance.Children[0].Children[3]).Property);
              Assert.AreEqual(propertyB, ((AnimationInstance<float>)controller.AnimationInstance.Children[1]).Property);
              Assert.AreEqual(propertyA1, ((AnimationInstance<float>)controller.AnimationInstance.Children[2]).Property);
              Assert.AreEqual(600.0f, propertyA1.Value);
              Assert.AreEqual(20.0f, propertyA2.Value);
              Assert.AreEqual(100.0f, propertyB.Value);
              Assert.AreEqual(40.0f, propertyC.Value);
              Assert.IsTrue(manager.IsAnimated(objectA));
              Assert.IsTrue(manager.IsAnimated(propertyA1));
              Assert.IsFalse(manager.IsAnimated(propertyA2));
              Assert.IsTrue(manager.IsAnimated(objectB));
              Assert.IsTrue(manager.IsAnimated(propertyB));
              Assert.IsFalse(manager.IsAnimated(objectC));
              Assert.IsFalse(manager.IsAnimated(propertyC));

              manager.StopAnimation(new[] { objectA, objectB, objectC });
              manager.UpdateAndApplyAnimation(new[] { objectA, objectB, objectC });
              Assert.AreEqual(10.0f, propertyA1.Value);
              Assert.AreEqual(20.0f, propertyA2.Value);
              Assert.AreEqual(30.0f, propertyB.Value);
              Assert.AreEqual(40.0f, propertyC.Value);
              Assert.IsFalse(manager.IsAnimated(objectA));
              Assert.IsFalse(manager.IsAnimated(propertyA1));
              Assert.IsFalse(manager.IsAnimated(propertyA2));
              Assert.IsFalse(manager.IsAnimated(objectB));
              Assert.IsFalse(manager.IsAnimated(propertyB));
              Assert.IsFalse(manager.IsAnimated(objectC));
              Assert.IsFalse(manager.IsAnimated(propertyC));
        }
Пример #19
0
        // Create morph target animation in code.
        private static ITimeline CreateMorphingAnimation()
        {
            // The weight of each morph target is controlled by a keyframe animation.
            var browMad = new SingleKeyFrameAnimation {
                TargetProperty = "BROW-mad"
            };

            browMad.KeyFrames.Add(new KeyFrame <float>(FrameToTime(15), 0));
            browMad.KeyFrames.Add(new KeyFrame <float>(FrameToTime(30), 1));
            browMad.KeyFrames.Add(new KeyFrame <float>(FrameToTime(65), 1));
            browMad.KeyFrames.Add(new KeyFrame <float>(FrameToTime(80), 0));

            var browSurp = new SingleKeyFrameAnimation {
                TargetProperty = "BROW-surp"
            };

            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(0), 0));
            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(15), 0.5f));
            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(30), 0));
            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(210), 0));
            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(220), 0.5f));
            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(230), 0.5f));
            browSurp.KeyFrames.Add(new KeyFrame <float>(FrameToTime(250), 0));

            var cheekIn = new SingleKeyFrameAnimation {
                TargetProperty = "CHEEK-in"
            };

            cheekIn.KeyFrames.Add(new KeyFrame <float>(FrameToTime(0), 0));
            cheekIn.KeyFrames.Add(new KeyFrame <float>(FrameToTime(15), 1));
            cheekIn.KeyFrames.Add(new KeyFrame <float>(FrameToTime(30), 0));

            var cheekOut = new SingleKeyFrameAnimation {
                TargetProperty = "CHEEK-out"
            };

            cheekOut.KeyFrames.Add(new KeyFrame <float>(FrameToTime(25), 0));
            cheekOut.KeyFrames.Add(new KeyFrame <float>(FrameToTime(35), 1));
            cheekOut.KeyFrames.Add(new KeyFrame <float>(FrameToTime(65), 1));
            cheekOut.KeyFrames.Add(new KeyFrame <float>(FrameToTime(80), 0));

            var eyeClosed = new SingleKeyFrameAnimation {
                TargetProperty = "EYE-closed"
            };

            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(20), 0));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(25), 1));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(55), 0.2f));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(65), 0.2f));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(80), 0));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(230), 0));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(235), 1));
            eyeClosed.KeyFrames.Add(new KeyFrame <float>(FrameToTime(240), 0));

            var mouthE = new SingleKeyFrameAnimation {
                TargetProperty = "MOUTH-e"
            };

            mouthE.KeyFrames.Add(new KeyFrame <float>(FrameToTime(115), 0));
            mouthE.KeyFrames.Add(new KeyFrame <float>(FrameToTime(125), 0.7f));
            mouthE.KeyFrames.Add(new KeyFrame <float>(FrameToTime(130), 0.7f));
            mouthE.KeyFrames.Add(new KeyFrame <float>(FrameToTime(140), 0.9f));
            mouthE.KeyFrames.Add(new KeyFrame <float>(FrameToTime(145), 0.9f));
            mouthE.KeyFrames.Add(new KeyFrame <float>(FrameToTime(155), 0.0f));

            var mouthU = new SingleKeyFrameAnimation {
                TargetProperty = "MOUTH-u"
            };

            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(25), 0));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(35), 0.5f));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(55), 0));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(145), 0));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(155), 0.5f));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(160), 0.5f));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(170), 0.9f));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(175), 0.9f));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(170), 0.9f));
            mouthU.KeyFrames.Add(new KeyFrame <float>(FrameToTime(190), 0.0f));

            var mouthSmile = new SingleKeyFrameAnimation {
                TargetProperty = "MOUTH-smile"
            };

            mouthSmile.KeyFrames.Add(new KeyFrame <float>(FrameToTime(210), 0));
            mouthSmile.KeyFrames.Add(new KeyFrame <float>(FrameToTime(220), 1));
            mouthSmile.KeyFrames.Add(new KeyFrame <float>(FrameToTime(230), 1));
            mouthSmile.KeyFrames.Add(new KeyFrame <float>(FrameToTime(250), 0));

            // Combine the key frame animations into a single animation.
            var timelineGroup = new TimelineGroup();

            timelineGroup.Add(browMad);
            timelineGroup.Add(browSurp);
            timelineGroup.Add(cheekIn);
            timelineGroup.Add(cheekOut);
            timelineGroup.Add(eyeClosed);
            timelineGroup.Add(mouthE);
            timelineGroup.Add(mouthU);
            timelineGroup.Add(mouthSmile);

            // Make an endless loop.
            return(new TimelineClip(timelineGroup)
            {
                Duration = TimeSpan.MaxValue,
                LoopBehavior = LoopBehavior.Cycle
            });
        }
Пример #20
0
    /// <summary>
    /// Animates the opacity and offset of a group of controls from their current value to the 
    /// specified value.
    /// </summary>
    /// <param name="controls">The UI controls to be animated.</param>
    /// <param name="opacity">The opacity.</param>
    /// <param name="offset">The offset.</param>
    private AnimationController AnimateTo(IList<UIControl> controls, float opacity, Vector2F offset)
    {
      TimeSpan duration = TimeSpan.FromSeconds(0.6f);

      // First, let's define the animation that is going to be applied to a control.
      // Animate the "Opacity" from its current value to the specified value.
      var opacityAnimation = new SingleFromToByAnimation
      {
        TargetProperty = "Opacity",
        To = opacity,
        Duration = duration,
        EasingFunction = new CubicEase { Mode = EasingMode.EaseIn },
      };

      // Animate the "RenderTranslation" property from its current value, which is 
      // usually (0, 0), to the specified value.
      var offsetAnimation = new Vector2FFromToByAnimation
      {
        TargetProperty = "RenderTranslation",
        To = offset,
        Duration = duration,
        EasingFunction = new CubicEase { Mode = EasingMode.EaseIn },
      };

      // Group the opacity and offset animation together using a TimelineGroup.
      var timelineGroup = new TimelineGroup();
      timelineGroup.Add(opacityAnimation);
      timelineGroup.Add(offsetAnimation);

      // Now we duplicate this animation by creating new TimelineClips that wrap the TimelineGroup.
      // A TimelineClip is assigned to a target by setting the TargetObject property.
      var storyboard = new TimelineGroup();

      for (int i = 0; i < controls.Count; i++)
      {
        var clip = new TimelineClip(timelineGroup)
        {
          TargetObject = controls[i].Name,  // Assign the clip to the i-th control.
          Delay = TimeSpan.FromSeconds(0.04f * i),
          FillBehavior = FillBehavior.Hold, // Hold the last value of the animation when it            
        };                                  // because we don't want to opacity and offset to
        // jump back to their original value.
        storyboard.Add(clip);
      }

      // Now we apply the "storyboard" to the group of UI controls. The animation system
      // will automatically assign individual animations to the right objects and 
      // properties.

      var animationController = AnimationService.StartAnimation(storyboard, controls);
#else
      var animationController = AnimationService.StartAnimation(storyboard, controls.Cast<IAnimatableObject>());


      animationController.UpdateAndApply();

      // The returned animation controller can be used to start, stop, pause, ... all
      // animations at once. (Note that we don't set AutoRecycle here, because we will 
      // explicitly stop and recycle the animations in the code above.)
      return animationController;
    }
Пример #21
0
    // Create morph target animation in code.
    private static ITimeline CreateMorphingAnimation()
    {
      // The weight of each morph target is controlled by a keyframe animation.
      var browMad = new SingleKeyFrameAnimation { TargetProperty = "BROW-mad" };
      browMad.KeyFrames.Add(new KeyFrame<float>(FrameToTime(15), 0));
      browMad.KeyFrames.Add(new KeyFrame<float>(FrameToTime(30), 1));
      browMad.KeyFrames.Add(new KeyFrame<float>(FrameToTime(65), 1));
      browMad.KeyFrames.Add(new KeyFrame<float>(FrameToTime(80), 0));

      var browSurp = new SingleKeyFrameAnimation { TargetProperty = "BROW-surp" };
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(0), 0));
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(15), 0.5f));
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(30), 0));
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(210), 0));
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(220), 0.5f));
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(230), 0.5f));
      browSurp.KeyFrames.Add(new KeyFrame<float>(FrameToTime(250), 0));

      var cheekIn = new SingleKeyFrameAnimation { TargetProperty = "CHEEK-in" };
      cheekIn.KeyFrames.Add(new KeyFrame<float>(FrameToTime(0), 0));
      cheekIn.KeyFrames.Add(new KeyFrame<float>(FrameToTime(15), 1));
      cheekIn.KeyFrames.Add(new KeyFrame<float>(FrameToTime(30), 0));

      var cheekOut = new SingleKeyFrameAnimation { TargetProperty = "CHEEK-out" };
      cheekOut.KeyFrames.Add(new KeyFrame<float>(FrameToTime(25), 0));
      cheekOut.KeyFrames.Add(new KeyFrame<float>(FrameToTime(35), 1));
      cheekOut.KeyFrames.Add(new KeyFrame<float>(FrameToTime(65), 1));
      cheekOut.KeyFrames.Add(new KeyFrame<float>(FrameToTime(80), 0));

      var eyeClosed = new SingleKeyFrameAnimation { TargetProperty = "EYE-closed" };
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(20), 0));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(25), 1));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(55), 0.2f));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(65), 0.2f));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(80), 0));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(230), 0));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(235), 1));
      eyeClosed.KeyFrames.Add(new KeyFrame<float>(FrameToTime(240), 0));

      var mouthE = new SingleKeyFrameAnimation { TargetProperty = "MOUTH-e" };
      mouthE.KeyFrames.Add(new KeyFrame<float>(FrameToTime(115), 0));
      mouthE.KeyFrames.Add(new KeyFrame<float>(FrameToTime(125), 0.7f));
      mouthE.KeyFrames.Add(new KeyFrame<float>(FrameToTime(130), 0.7f));
      mouthE.KeyFrames.Add(new KeyFrame<float>(FrameToTime(140), 0.9f));
      mouthE.KeyFrames.Add(new KeyFrame<float>(FrameToTime(145), 0.9f));
      mouthE.KeyFrames.Add(new KeyFrame<float>(FrameToTime(155), 0.0f));

      var mouthU = new SingleKeyFrameAnimation { TargetProperty = "MOUTH-u" };
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(25), 0));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(35), 0.5f));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(55), 0));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(145), 0));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(155), 0.5f));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(160), 0.5f));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(170), 0.9f));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(175), 0.9f));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(170), 0.9f));
      mouthU.KeyFrames.Add(new KeyFrame<float>(FrameToTime(190), 0.0f));

      var mouthSmile = new SingleKeyFrameAnimation { TargetProperty = "MOUTH-smile" };
      mouthSmile.KeyFrames.Add(new KeyFrame<float>(FrameToTime(210), 0));
      mouthSmile.KeyFrames.Add(new KeyFrame<float>(FrameToTime(220), 1));
      mouthSmile.KeyFrames.Add(new KeyFrame<float>(FrameToTime(230), 1));
      mouthSmile.KeyFrames.Add(new KeyFrame<float>(FrameToTime(250), 0));

      // Combine the key frame animations into a single animation.
      var timelineGroup = new TimelineGroup();
      timelineGroup.Add(browMad);
      timelineGroup.Add(browSurp);
      timelineGroup.Add(cheekIn);
      timelineGroup.Add(cheekOut);
      timelineGroup.Add(eyeClosed);
      timelineGroup.Add(mouthE);
      timelineGroup.Add(mouthU);
      timelineGroup.Add(mouthSmile);

      // Make an endless loop.
      return new TimelineClip(timelineGroup)
      {
        Duration = TimeSpan.MaxValue,
        LoopBehavior = LoopBehavior.Cycle
      };
    }
Пример #22
0
    public AnimatableObjectSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      Rectangle bounds = GraphicsService.GraphicsDevice.Viewport.TitleSafeArea;

      // ----- Create three named AnimatableSprite instances.
      _animatableSpriteA = new AnimatableSprite("SpriteA", SpriteBatch, Logo)
      {
        Position = new Vector2(bounds.Center.X, bounds.Center.Y / 2.0f),
        Color = Color.Red,
      };

      _animatableSpriteB = new AnimatableSprite("SpriteB", SpriteBatch, Logo)
      {
        Position = new Vector2(bounds.Center.X, bounds.Center.Y),
        Color = Color.Green,
      };

      _animatableSpriteC = new AnimatableSprite("SpriteC", SpriteBatch, Logo)
      {
        Position = new Vector2(bounds.Center.X, 3.0f * bounds.Center.Y / 2.0f),
        Color = Color.Blue,
      };

      // Create a looping color key-frame animation.
      ColorKeyFrameAnimation colorAnimation = new ColorKeyFrameAnimation
      {
        TargetProperty = "Color",
        EnableInterpolation = true,
      };
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(0.0), Color.Red));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(0.5), Color.Orange));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(1.0), Color.Yellow));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(1.5), Color.Green));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(2.0), Color.Blue));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(2.5), Color.Indigo));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(3.0), Color.Violet));
      colorAnimation.KeyFrames.Add(new KeyFrame<Color>(TimeSpan.FromSeconds(3.5), Color.Red));
      AnimationClip<Color> loopedColorAnimation = new AnimationClip<Color>(colorAnimation)
      {
        TargetObject = "SpriteB",
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Create a oscillating from/to animation for the position.
      Vector2FromToByAnimation vector2Animation = new Vector2FromToByAnimation
      {
        TargetProperty = "Position",
        From = new Vector2(bounds.Left + 100, _animatableSpriteC.Position.Y),
        To = new Vector2(bounds.Right - 100, _animatableSpriteC.Position.Y),
        Duration = TimeSpan.FromSeconds(2),
        EasingFunction = new HermiteEase { Mode = EasingMode.EaseInOut },
      };
      AnimationClip<Vector2> oscillatingVector2Animation = new AnimationClip<Vector2>(vector2Animation)
      {
        LoopBehavior = LoopBehavior.Oscillate,
        Duration = TimeSpan.MaxValue,
      };

      // Create a timeline group that contains both animations.
      TimelineGroup spriteCAnimation = new TimelineGroup { TargetObject = "SpriteC", };
      spriteCAnimation.Add(loopedColorAnimation);
      spriteCAnimation.Add(oscillatingVector2Animation);

      // Create a timeline group that contains the animations for SpriteB and SpriteC.
      TimelineGroup allSpriteAnimations = new TimelineGroup();
      allSpriteAnimations.Add(loopedColorAnimation);
      allSpriteAnimations.Add(spriteCAnimation);

      // There are several ways to apply animations to animatable objects and properties:
      //
      // Method 1: Apply to an IAnimatableProperty directly.
      // We either have direct access to a IAnimatableProperty or we can ask the IAnimatableObject
      // to give us a named IAnimatableProperty. 
      // For example:
      //     AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteB.GetAnimatableProperty<Color>("Color"));
      //     AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteC.GetAnimatableProperty<Color>("Color"));
      //     AnimationService.StartAnimation(oscillatingLeftRightAnimation, _animatableSpriteC.GetAnimatableProperty<Vector2>("Position"));
      // In this case, the "TargetObject" and the "TargetProperty" values of the timelines/animations do not matter. 
      //
      // Method 2: Apply to an IAnimatableObject directly.
      // For example: 
      //     AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteB);
      //     AnimationService.StartAnimation(spriteCAnimation, _animatableSpriteC);
      // The animation service checks the TargetProperty value of the animations to see which
      // IAnimatableProperty of the IAnimatableObjects should be animated by the animation.
      // The "TargetObject" values of the timelines are ignored.
      // 
      // Method 3: Apply a timeline to a collection of IAnimatableObjects.
      // For example: 
      var animationController = AnimationService.StartAnimation(allSpriteAnimations, new[] { _animatableSpriteA, _animatableSpriteB, _animatableSpriteC });
      // The "TargetObject" and "TargetProperty" values are used to check which objects and
      // properties must be animated by which animation.
      // combinedSpriteAnimation is a "tree" of timelines:
      // 
      //                                  Type                         TargetObject   TargetProperty
      // --------------------------------------------------------------------------------------------------
      // allSpriteAnimations              TimelineGroup                -              -
      //   loopedColorAnimation           AnimationClip<Color>         "SpriteB"      -
      //     colorAnimation               ColorKeyFrameAnimation       -              "Color"
      //   spriteCAnimation               TimelineGroup                "SpriteC"      -
      //     loopedColorAnimation         AnimationClip<Color>         "SpriteB"      - 
      //       colorAnimation             ColorKeyFrameAnimation       -             "Color"
      //     oscillatingVector2Animation  AnimationClip<Vector2>       -             -
      //       vector2Animation           FromToByAnimation            -             "Position"
      //
      // No animation specifies "SpriteA" as its TargetObject, therefore no animation
      // are applied to SpriteA.
      //
      // The first loopedColorAnimation is applied to "SpriteB". And the contained 
      // colorAnimation is applied to the Color property of SpriteB.
      //
      // The spriteCAnimation is applied to "SpriteC". Therefore, all "children" of 
      // spriteCAnimation are also applied to this object! The TargetObject property of
      // the second loopedColorAnimation is ignored! The second loopedColorAnimation is 
      // applied to SpriteC!

      animationController.UpdateAndApply();
    }
Пример #23
0
    // The following code contains two helper methods to animate the opacity and offset
    // of a group of UI controls. The methods basically do the same, they animate the 
    // properties from/to a specific value. However the methods demonstrate two different 
    // approaches.
    //
    // The AnimateFrom method uses a more direct approach. It directly starts an 
    // animation for each UI control in list, thereby creating several independently 
    // running animations.
    //
    // The AnimateTo method uses a more declarative approach. All animations are 
    // defined and assigned to the target objects by setting the name of the UI control
    // in the TargetObject property. Then all animations are grouped together into
    // a single animation. When the resulting animation is started the animation system
    // creates the required animation instances and assigns the instances to the correct
    // objects and properties by matching the TargetObject and TargetProperty with the
    // name of the UI controls and their properties.
    //
    // Both methods achieve a similar result. The advantage of the first method is more
    // direct control. The advantage of the seconds method is that only a single animation
    // controller is required to control all animations at once.

    /// <summary>
    /// Animates the opacity and offset of a group of controls from the specified value to their 
    /// current value.
    /// </summary>
    /// <param name="controls">The UI controls to be animated.</param>
    /// <param name="opacity">The initial opacity.</param>
    /// <param name="offset">The initial offset.</param>
    private void AnimateFrom(IList<UIControl> controls, float opacity, Vector2F offset)
    {
      TimeSpan duration = TimeSpan.FromSeconds(0.8);

      // First, let's define the animation that is going to be applied to a control.
      // Animate the "Opacity" from the specified value to its current value.
      var opacityAnimation = new SingleFromToByAnimation
      {
        TargetProperty = "Opacity",
        From = opacity,
        Duration = duration,
        EasingFunction = new CubicEase { Mode = EasingMode.EaseOut },
      };

      // Animate the "RenderTranslation" property from the specified offset to its
      // its current value, which is usually (0, 0).
      var offsetAnimation = new Vector2FFromToByAnimation
      {
        TargetProperty = "RenderTranslation",
        From = offset,
        Duration = duration,
        EasingFunction = new CubicEase { Mode = EasingMode.EaseOut },
      };

      // Group the opacity and offset animation together using a TimelineGroup.
      var timelineGroup = new TimelineGroup();
      timelineGroup.Add(opacityAnimation);
      timelineGroup.Add(offsetAnimation);

      // Run the animation on each control using a negative delay to give the first controls
      // a slight head start.
      var numberOfControls = controls.Count;
      for (int i = 0; i < controls.Count; i++)
      {
        var clip = new TimelineClip(timelineGroup)
        {
          Delay = TimeSpan.FromSeconds(-0.04 * (numberOfControls - i)),
          FillBehavior = FillBehavior.Stop,   // Stop and remove the animation when it is done.
        };
        var animationController = AnimationService.StartAnimation(clip, controls[i]);

        animationController.UpdateAndApply();

        // Enable "auto-recycling" to ensure that the animation resources are recycled once
        // the animation stops or the target objects are garbage collected.
        animationController.AutoRecycle();
      }
    }
Пример #24
0
        public void GetSelfAndAncestors()
        {
            var animationA = new TimelineGroup();
              var animationB = new SingleFromToByAnimation();
              var animationC = new SingleFromToByAnimation();
              var animationD = new TimelineGroup();
              var animationE = new TimelineGroup();
              var animationF = new SingleFromToByAnimation();
              var animationG = new TimelineGroup();
              animationA.Add(animationB);
              animationA.Add(animationC);
              animationA.Add(animationD);
              animationD.Add(animationE);
              animationD.Add(animationF);
              animationE.Add(animationG);

              Assert.That(() => AnimationHelper.GetSelfAndAncestors(null), Throws.TypeOf<ArgumentNullException>());

              var animationInstance = animationA.CreateInstance();
              var ancestors = animationInstance.Children[2].Children[0].GetSelfAndAncestors().ToArray();
              Assert.AreEqual(3, ancestors.Length);
              Assert.AreEqual(animationInstance.Children[2].Children[0], ancestors[0]);
              Assert.AreEqual(animationInstance.Children[2], ancestors[1]);
              Assert.AreEqual(animationInstance, ancestors[2]);
        }
Пример #25
0
        public void GetSubtreeDepthFirst()
        {
            var animationA = new TimelineGroup();
              var animationB = new SingleFromToByAnimation();
              var animationC = new SingleFromToByAnimation();
              var animationD = new TimelineGroup();
              var animationE = new TimelineGroup();
              var animationF = new SingleFromToByAnimation();
              var animationG = new TimelineGroup();
              animationA.Add(animationB);
              animationA.Add(animationC);
              animationA.Add(animationD);
              animationD.Add(animationE);
              animationD.Add(animationF);
              animationE.Add(animationG);

              Assert.That(() => AnimationHelper.GetSubtree(null), Throws.TypeOf<ArgumentNullException>());

              var animationInstance = animationA.CreateInstance();
              var descendants = animationInstance.Children[2].GetSubtree().ToArray();
              Assert.AreEqual(4, descendants.Length);
              Assert.AreEqual(animationInstance.Children[2], descendants[0]);
              Assert.AreEqual(animationInstance.Children[2].Children[0], descendants[1]);
              Assert.AreEqual(animationInstance.Children[2].Children[0].Children[0], descendants[2]);
              Assert.AreEqual(animationInstance.Children[2].Children[1], descendants[3]);
        }
Пример #26
0
        public AnimatableObjectSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            Rectangle bounds = GraphicsService.GraphicsDevice.Viewport.TitleSafeArea;

            // ----- Create three named AnimatableSprite instances.
            _animatableSpriteA = new AnimatableSprite("SpriteA", SpriteBatch, Logo)
            {
                Position = new Vector2(bounds.Center.X, bounds.Center.Y / 2.0f),
                Color    = Color.Red,
            };

            _animatableSpriteB = new AnimatableSprite("SpriteB", SpriteBatch, Logo)
            {
                Position = new Vector2(bounds.Center.X, bounds.Center.Y),
                Color    = Color.Green,
            };

            _animatableSpriteC = new AnimatableSprite("SpriteC", SpriteBatch, Logo)
            {
                Position = new Vector2(bounds.Center.X, 3.0f * bounds.Center.Y / 2.0f),
                Color    = Color.Blue,
            };

            // Create a looping color key-frame animation.
            ColorKeyFrameAnimation colorAnimation = new ColorKeyFrameAnimation
            {
                TargetProperty      = "Color",
                EnableInterpolation = true,
            };

            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(0.0), Color.Red));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(0.5), Color.Orange));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(1.0), Color.Yellow));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(1.5), Color.Green));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(2.0), Color.Blue));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(2.5), Color.Indigo));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(3.0), Color.Violet));
            colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(3.5), Color.Red));
            AnimationClip <Color> loopedColorAnimation = new AnimationClip <Color>(colorAnimation)
            {
                TargetObject = "SpriteB",
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            // Create a oscillating from/to animation for the position.
            Vector2FromToByAnimation vector2Animation = new Vector2FromToByAnimation
            {
                TargetProperty = "Position",
                From           = new Vector2(bounds.Left + 100, _animatableSpriteC.Position.Y),
                To             = new Vector2(bounds.Right - 100, _animatableSpriteC.Position.Y),
                Duration       = TimeSpan.FromSeconds(2),
                EasingFunction = new HermiteEase {
                    Mode = EasingMode.EaseInOut
                },
            };
            AnimationClip <Vector2> oscillatingVector2Animation = new AnimationClip <Vector2>(vector2Animation)
            {
                LoopBehavior = LoopBehavior.Oscillate,
                Duration     = TimeSpan.MaxValue,
            };

            // Create a timeline group that contains both animations.
            TimelineGroup spriteCAnimation = new TimelineGroup {
                TargetObject = "SpriteC",
            };

            spriteCAnimation.Add(loopedColorAnimation);
            spriteCAnimation.Add(oscillatingVector2Animation);

            // Create a timeline group that contains the animations for SpriteB and SpriteC.
            TimelineGroup allSpriteAnimations = new TimelineGroup();

            allSpriteAnimations.Add(loopedColorAnimation);
            allSpriteAnimations.Add(spriteCAnimation);

            // There are several ways to apply animations to animatable objects and properties:
            //
            // Method 1: Apply to an IAnimatableProperty directly.
            // We either have direct access to a IAnimatableProperty or we can ask the IAnimatableObject
            // to give us a named IAnimatableProperty.
            // For example:
            //     AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteB.GetAnimatableProperty<Color>("Color"));
            //     AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteC.GetAnimatableProperty<Color>("Color"));
            //     AnimationService.StartAnimation(oscillatingLeftRightAnimation, _animatableSpriteC.GetAnimatableProperty<Vector2>("Position"));
            // In this case, the "TargetObject" and the "TargetProperty" values of the timelines/animations do not matter.
            //
            // Method 2: Apply to an IAnimatableObject directly.
            // For example:
            //     AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteB);
            //     AnimationService.StartAnimation(spriteCAnimation, _animatableSpriteC);
            // The animation service checks the TargetProperty value of the animations to see which
            // IAnimatabelProperty of the IAnimtableObjects should be animated by the animation.
            // The "TargetObject" values of the timelines are ignored.
            //
            // Method 3: Apply a timeline to a collection of IAnimatableObjects.
            // For example:
            var animationController = AnimationService.StartAnimation(allSpriteAnimations, new[] { _animatableSpriteA, _animatableSpriteB, _animatableSpriteC });

            // The "TargetObject" and "TargetProperty" values are used to check which objects and
            // properties must be animated by which animation.
            // combinedSpriteAnimation is a "tree" of timelines:
            //
            //                                  Type                         TargetObject   TargetProperty
            // --------------------------------------------------------------------------------------------------
            // allSpriteAnimations              TimelineGroup                -              -
            //   loopedColorAnimation           AnimationClip<Color>         "SpriteB"      -
            //     colorAnimation               ColorKeyFrameAnimation       -              "Color"
            //   spriteCAnimation               TimelineGroup                "SpriteC"      -
            //     loopedColorAnimation         AnimationClip<Color>         "SpriteB"      -
            //       colorAnimation             ColorKeyFrameAnimation       -             "Color"
            //     oscillatingVector2Animation  AnimationClip<Vector2>       -             -
            //       vector2Animation           FromToByAnimation            -             "Position"
            //
            // No animation specifies "SpriteA" as its TargetObject, therefore no animation
            // are applied to SpriteA.
            //
            // The first loopedColorAnimation is applied to "SpriteB". And the contained
            // colorAnimation is applied to the Color property of SpriteB.
            //
            // The spriteCAnimation is applied to "SpriteC". Therefore, all "children" of
            // spriteCAnimation are also applied to this object! The TargetObject property of
            // the second loopedColorAnimation is ignored! The second loopedColorAnimation is
            // applied to SpriteC!

            animationController.UpdateAndApply();
        }
Пример #27
0
        public void GetRoot()
        {
            var animationA = new TimelineGroup();
              var animationB = new SingleFromToByAnimation();
              var animationC = new SingleFromToByAnimation();
              var animationD = new TimelineGroup();
              var animationE = new TimelineGroup();
              var animationF = new SingleFromToByAnimation();
              var animationG = new TimelineGroup();
              animationA.Add(animationB);
              animationA.Add(animationC);
              animationA.Add(animationD);
              animationD.Add(animationE);
              animationD.Add(animationF);
              animationE.Add(animationG);

              Assert.That(() => AnimationHelper.GetRoot(null), Throws.TypeOf<ArgumentNullException>());

              var animationInstance = animationA.CreateInstance();
              Assert.AreEqual(animationInstance, animationInstance.GetRoot());
              Assert.AreEqual(animationInstance, animationInstance.Children[2].Children[0].GetRoot());
        }