Animation Annoyances
Subtitle for this entry: A tale of two callbacks (by Ethel the Aardvark)
The Second Life grid is down right now. I had been kinda hanging out at the Shelter, hovering around, half there.
Earlier in the day I had a brief chat with Danielle Ferguson. She is partnered with Erbo Evans whom I may have mentioned here before - a Shelter regular nowadays and an amusing person to chat with. Danielle was admiring tiny Dolmere's keyboard and asked for a copy. When I get some time I will make a copy for her and pass it along.
Anyway, the discussion got me thinking about my tiny Dolmere again and how I've been meaning to post about the animation override work I did on it. I did finally get a semblance of an anim override going. I'm probably done messing with it at this point since it's almost working. The system for managing animations really stinks, imho.
Tiny Dolmere sits on my shoulder. If you read any earlier entries about him then you know that he has a little laptop that pops up for him to fake-type on when my avatar starts typing. To drive the "tiny-Dolmere-pulls-the-strings" point home I thought it would be great to override the typing animation with a marionette style animation. I already had the trigger points for start/stop typing from Max Case's freebie keyboard script posted to the wiki and that was working fine.
Later on, after I had set aside the typing override idea, Roenik made me some nice animations to use when I host Payment Podium. I'm referring to the recent work done for my quiz cards. One of the animations is a loop that makes my hands simply stick out in front of me. With cards in my hands it looks like I'm simply holding them - with no cards it makes it almost look like my main avatar is paralyzed awaiting input from tiny Dolmere. So I figured I could get started on a good typing anim override using that.
I thought I would apply my knowledge of seating scripts to this project. With a seating script you can use the function llUnSit to kick someone out of the chair, you can use llSitTarget to define where on the object in question the avatar attempting to sit will actually place its posterior, and the real magic in seat scripting is llAvatarOnSitTarget which can be used to determine if someone actually has their posterior firmly planted on the object with the script.
- In seating script examples that I have it basically goes like this:
- Watch for callback telling me that something has changed (The wiki calls these callbacks "events")
- Verify that the item changed was "CHANGED_LINK" - which includes "when an avatar sits on an object." and "when a sitting avatar stands up from the object."
- Get permission to animate avatar sitting on sit target.
- Stop standard 'sit' animation
- Start non-standard 'my_custom_sit' animation
- Watch for another CHANGED_LINK callback to unsit them by stopping out 'my_custom_sit' animation
So let's try to emulate this by watching for a change to the typing state. Oh wait, we can't do that! Why, you ask? Because there is no CHANGED_BASIC_ANIMATION or CHANGED_ANIMATION or other flag in the changed event to track for my avatar. There is no callback/event at all to tell me a basic animation has started or stopped.
For the heck of it I changed my keyboard script to stop the "type" animation. I figured that if I just held my arms at my sides instead of typing it would be clear who the real controller in the Dol/mini Dol relationship is. OMGosh! What a mistake that is. Effectively I broke Max's keyboard script by doing so. See, the keyboard only knows that it should be shown by checking to see if the avatar is typing - therefore it checks for the "type" animation! Once I stop the type animation... well, you get the point. Something triggers the "type" animation in the first place, but other than checking to see if it's actively playing I see no way to see if my avatar is actively working on some offensive comment or another.
I hear you asking - if that's true, if there is no notification that primary animations are starting or stopping, then how do animation overrides work? 20 or more percent of any gathering of avatars typically have some form of override running! I'm glad you asked - I asked the same thing when I got to this point in my voyage of discovery.
A quick note on animations: Animations are badged with a priority code - they can be stacked on top of each other and anims with higher priority will override animations of a lower priority. Animations affect a certain part of the avatar's body - as each tick of the animation rolls by the differences on the affected body parts are computed against the priority codes of other playing animations. This way we can flap our arms while flying or type while standing, etc. The "type" aniimation has a priority of 2, by the way.
The thing to do, then, is to discover how the overriders work. Frnacis Chung's work or some derivitive thereof would do for reseach since they contain freely available code to review. It's rather complex code actually. In looking it over it becomes apparent to me that it's a work around for the missing callback.
One might be able to use the llGetAnimation function to tell us if the avatar's state is typing to avoid some of the programmatic research, but the function returns only "basic animations states" - Typing is not one of them! So instead one has to use llGetAnimationList which contains a list of animations by name that are currently playing against your avatar. You then search through that list or use llListFindList to search through the list for you.
So let's review: we want to know if our avatar is typing (or some other default triggered state/animation). To discover this do we listen for a callback/event "changed" and look for a trigger "ANIMATION_CHANGE" or perhaps a callback of "animation_triggered" and look to see which animation was stopped/started? No, none of the above.
What is the semi-working solution? Edit Max's keyboard script to watch for the "type" animation then play another animation over the top of it. Roenik's card holding script is a higher priority than 2 so I was able to use it as a looping animation to play OVER the typing animation. The problem is that there is lag inherent in telling a script to poll for animation changes, etc. So my stupid avatar puts his hands up, types a few licks of his novel "how to look stupid", and then his hands stick out in front of him motionless. Not exactly the affect I was going for, but it semi-works so I'm calling it a day on that front :)
So basically what we have are a bunch of aggressive timers firing off, grabbing a complete animation list, searching through it and reacting to changes for every avatar who wants a custom pose. All in a system with limited cycles. I can't help but imagine how much more efficient proper callbacks would be and how many scripting cycles would be saved for other scripts on the sim.
One last review. Let's lay out what IS happening and what COULD be happening.
- IS
- Set a timer script to fire every .2 seconds, .5 seconds, whatever (any which way it's not often enough and still allows odd behaviors to sneak through)
- Ask for a list of all running animations our avatar has.
- Find the animation you care about in the animations list. Do not stop it.
- Play a custom animation ensuring it's higher in the priority list than the default.
- Watch in your timer code for another change.
- COULD BE
- No timer. Instead a callback function would be triggered on each avatar body animation change triggered by SL movement/actions.
- Review a trigger code in our callback to see if it's an animation change we care about at all.
- Stop the default animation if desired - if you're getting callbacks on changes then the presence of the default animation is irrelevant.
- Play your custom animation and wait for a callback to tell you it's time to stop.
To boil down the argument it would be why waste resources checking a list of animations to know that my avatar was told to type? Why not just have a start_typing and stop_typing function I can choose to override? (etc. ad infinitum)
One last thing - I asked Travis to review this entry before posting for a sanity check. He mentioned this forum post which discusses the idea of the new physical avatar. While it may introduce some new fun interactions I don't think it addresses this issue. New avatar capabilities don't give me a cleaner scripting implementation - nor do the specific items mentioned there seem to address the lack of callbacks for today's basic built in avatar animations/emotes.
Comments
Hey Dol, I'm OK and busy--hands just hurt a lot but I wanted to come here and acknowledge I read this!
Mini-Dol is so cute. :) I almost misspelled it as "MinIdol" once. ;)
Also, I'm going to let our developers know about this, including some who specialize in this area.
What other avenues have you also explored about this? Since it sounds like undesirable behavior that could be improved; would it be worth your time to put in the Feature Voting Tool? :)
Posted by: Torley Linden | July 16, 2006 03:45 PM
Torley, thanks much for taking the time to read this entry.
Rather than post a long reply here I'm posting a new blog entry as a reponse :)
Posted by: dolmere | July 17, 2006 12:11 AM