views:

740

answers:

1

I'm moving 3d camera like this:

    Point3DAnimation pa;

    // Triggered by user click
    void MoveCamera(object sender, EventArgs e)
    {

        pa = new Point3DAnimation(myPoint3D, TimeSpan.FromMilliseconds(2000));
        pa.Completed += new EventHandler(pa_Completed);
        Camera.BeginAnimation(PerspectiveCamera.PositionProperty, pa); // anim#1
    }

    // we're in place. do some idle animation
    void pa_Completed(object sender, EventArgs e)
    {
        pa = new Point3DAnimation(myPoint3Ddz, TimeSpan.FromMilliseconds(5000));
        Camera.BeginAnimation(PerspectiveCamera.PositionProperty, pa); // anim#2
    }
  1. User clicks.
  2. Camera moves to choosen position (anim#1).
  3. When anim#1 ends anim#2 is played.

Everything is ok... until user triggers MoveCamera when previous anim#1 is not finished.

In that case:

  1. New anim#1 is starting.
  2. Completed event of old anim#1 is triggered.
  3. anim#2 is started instatntly (overlapping new anim#1).

2 & 3 are wrong here. How i can avoid that?

I think that pa_Completed() should detect that new anim#1 is already playing, or MoveCamera() should unregister Complete event from old anim#1. But what the right way to do it?

A: 

If the goal is to chain two animations together, let WPF do the heavy lifting by using the Point3DAnimationUsingKeyFrames class.

First, build the key frame animation in XAML (it's a bear to do it in code):

  <Window.Resources>
    <Point3DAnimationUsingKeyFrames x:Key="CameraMoveAnimation" Duration="0:0:7">
      <LinearPoint3DKeyFrame KeyTime="28%" />
      <LinearPoint3DKeyFrame KeyTime="100%" />
    </Point3DAnimationUsingKeyFrames>
  </Window.Resources>

Next, consume it and set the actual Point3D values (using your code names):

private void MoveCamera(object sender, EventArgs e) {
    Point3DAnimationUsingKeyFrames cameraAnimation = 
        (Point3DAnimationUsingKeyFrames)Resources["CameraMoveAnimation"];
    cameraAnimation.KeyFrames[0].Value = myPoint3D;
    cameraAnimation.KeyFrames[1].Value = myPoint3dz;
    Camera.BeginAnimation(PerspectiveCamera.PositionProperty, cameraAnimation);
}
Adrian