animating a non-interpolated view property and totally confused

  • I'm trying to use Core/Cocoa Animation to coordinate
    animating a property that my view must interpolate
    itself. I want to animate whenever an enumeration
    property gets changed, eg setTypeOfObject:kSquare when
    it was a kCircle. So my view needs to know how far it
    is between two enum values and figure out how to draw
    something that is X% a kSquare and (1-X)% a kCircle on
    its own.

    My understanding is that in this case I need to
    implement animationForKey: in my NSView subclass,
    which must return an instance of CAAnimation. But it's
    NSAnimation that has all the features I'm after, and
    it's a subclass of NSObject that couldn't pose as a
    CAAnimation. So I guess the CAAnimation would have my
    view instance set as a delegate, and I'd need to make
    my view's animationDidStart: delegate method start an
    NSAnimation instance?

    If that weren't convoluted enough, NSAnimation doesn't
    use a delegate for something as basic as a progress
    update. The Animation Programming Guide for Cocoa says
    to subclass NSAnimation and override the
    setCurrentProgress: method. Since my NSView instance
    is the delegate anyway for the
    animationShouldStart:/DidStop: methods, I implemented
    this as:

    -
    (void)setCurrentProgress:(NSAnimationProgress)progress
    {
    [super setCurrentProgress:progress];
    id delegate = [self delegate];
    if ([delegate
    respondsToSelector:@selector(animation:didProgressTo:)])
      [delegate animation:self didProgressTo:progress];
    }

    However, to get the NSAnimation subclass to compile
    without warnings, my NSView subclass needs to make its
    animation:didProgressTo: method public. Even with the
    delegate instead of an outlet shortcut, this is
    getting very convoluted.

    To top this all off, I still don't know where I would
    look to get the property value I should be animating
    "towards". When I've called [[myView animator]
    setEnumerationValue:targetSetting], which object in
    this soup can tell my view what targetSetting is?

    Am I on the wrong track here? If I really have to
    subclass NSAnimation, instantiate (and subclass??)
    CAAnimation, and spaghetti everything together in a
    bunch of view delegate methods just to get a steady
    stream of progress values as a result of a property
    change, I'd be better off sticking with my own
    property accessors and an NSTimer.

    thanks for any pointers,
    -natevw

          ____________________________________________________________________________________
    ¡Capacidad ilimitada de almacenamiento en tu correo!
    No te preocupes más por el espacio de tu cuenta con Correo Yahoo!:
    http://correo.espanol.yahoo.com/
  • On Feb 13, 2008, at 6:07 PM, Nathan Vander Wilt wrote:

    > My understanding is that in this case I need to
    > implement animationForKey: in my NSView subclass,
    > which must return an instance of CAAnimation. But it's
    > NSAnimation that has all the features I'm after, and
    > it's a subclass of NSObject that couldn't pose as a
    > CAAnimation. So I guess the CAAnimation would have my
    > view instance set as a delegate, and I'd need to make
    > my view's animationDidStart: delegate method start an
    > NSAnimation instance?

    What you need to do is implement a "squareness" property on your view
    that basically says how far you are between Square and Circle. When
    you are asked to animate, you return a CABasicAnimation - you don't
    need to modify it at all, just let setTypeOfObject do the work for you
    to either say Square or Circle as the extreme of your "squareness"
    property.

    Then you will just be called periodically to draw, with "squareness"
    linearly interpolated between the starting and ending value. As long
    as you can draw the intermediate interpolations, you'll see your
    animation progress.
    --
    David Duncan
    Apple DTS Animation and Printing
    <david.duncan...>
  • --- David Duncan <david.duncan...> escribió:
    > What you need to do is implement a "squareness"
    > property on your view
    > that basically says how far you are between Square
    > and Circle. When
    > you are asked to animate, you return a
    > CABasicAnimation - you don't
    > need to modify it at all, just let setTypeOfObject
    > do the work for you
    > to either say Square or Circle as the extreme of
    > your "squareness"
    > property.

    Thanks much! With that direction I was able to figure
    it pretty much out. I added a +defaultAnimationForKey:
    method to my custom view,  and made my enumeration
    setter store the old value [there are actually more
    than two possible enumerated states, and I should come
    clean and say the property isn't really a C
    enumeration, but my own "state" class] and then call
    the "betweenness" setter through the animation proxy.
    This gets me the stream of redraw requests I was
    hoping for.

    Now that I've got the basics working, I do have two
    follow-up questions:

    1) I want to set my view instance as a delegate of the
    CABasicAnimation. It seems the only practical way to
    to this is to override the -animationForKey: method,
    but the NSAnimatablePropertyContainer protocol
    documentation for that says "Subclasses should not
    typically need to override this method." So long as I
    pass any keys I don't handle to super, is this okay to
    do?

    2) I'd really like the controller, not the view, to
    determine whether or not a property is animated.
    However, when I refactor the [[self animator]
    setBetweenness:1.0] call in the view's
    setTypeOfObject: to instead be a [[myView animator]
    setTypeOfObject:kTriangle] call in the controller, the
    animation system doesn't animate the view's internal
    [self setBetweenness:1.0] property change.
    How can I arrange things so that the controller can
    decide whether/not to use the proxy animator, but
    still access the property via the primary
    ("typeOfObject") key?

    thanks,
    -natevw

          ____________________________________________________________________________________
    ¡Capacidad ilimitada de almacenamiento en tu correo!
    No te preocupes más por el espacio de tu cuenta con Correo Yahoo!:
    http://correo.espanol.yahoo.com/