Using unsetProperty With Script Animations

A common theme lately has been confusion about the unsetProperty API used by scripts in HD DVD, but it's actually quite simple once you know the rules. One complication is the behaviour of the state properties, which act slightly differently than the style properties, and this behaviour was not clearly specified in the original version of the HD DVD specification. If you only have version 1.0 of the spec, it won't be very clear, but if you have 1.01 or access to the supplemental updates, it should be clearer.

Anyway, the rules you need to know are:

1) There is a hierarchy of control for animatable properties -- script has the highest priority, the navigation manager / markup engine has medium priority, and the loaded XML DOM has the lowest priority -- and each priority level is managed independently

2) ...except for state:focused and state:value, which maintain a single value across all three levels

These rules might seem weird, but they serve a good purpose. Let's start by looking at a simple example such as the style:x property of a button. When the markup document is first loaded, the initial value of style:x is read from the XML DOM (or inferred by a style reference, etc.) and this is where the button will sit "at rest"; i.e., when no animations are acting on it. Let's say this value is 100px.

Then at some point in time, the user might take an action that will cause a markup-based animation to fire, changing the position of the button by animating its style:x property. For example, the user may open a sub-menu by activate a button which causes the style:x property to be animated from 100px to 500px, and then to stay there until the menu is closed.

So now the current value of style:x is 500px, but the XML DOM still remembers the original value of 100px. If the user closes the sub-menu -- and in doing so terminates the animation block that moved the button to 500px -- the button will return to its at-rest value of 100px, awaiting further orders. The sub-menu can be opened and closed repeatedly, changing the value from 100px to 500px and back again.

Now imagine that the user has the sub-menu open -- so the button is at 500px -- and then they invoke one of the functions in the sub-menu by clicking another button. This causes some script code to run that needs to temporarily animate all the buttons off-screen, so it animates the style:x property to 1920px so that it slides off the right-hand-side. The script over-rides both the XML DOM value and the markup-animated value because it is assumed that the script is performing some important actions, versus the markup which may just be there for eye-candy.

So now the button will stay at 1920px until the script relinquishes control, but the player still remembers the at-rest value of 100px and the markup-animated value of 500px (which may or may not expire whilst script still has control). When the script is done with its high-priority actions, it calls unsetProperty on style:x and that releases control back to the markup engine (500px) or the XML DOM value (100px) if no markup animations are active.

Note that script control of a property is very localised: if script has control of a property P on an element E, all other properties of E and the P property of all other elements are still animatable by markup. So if script has control of style:x on the button with id "Play", markup can still animate style:y of "Play" and style:x of another button, "Chapters".

Whilst this model works well for the style properties, it doesn't work so well with the state properties. The fly in the ointment here is you, the user. The state properties are all about dealing with user input, and that happens at the navigation manager level (ie, the middle priority level), but every now and then you also want to be able to explicitly set things like the focused button or the initial value of an input box in script. So script still has ultimate control over the state:value and state:focused properties, but when control is relinquished back to the user via unsetProperty, the value of the property doesn't change because there is only one value shared by all three priority levels (DOM, markup, and script). The same is true for markup animations -- you can change the focus or the value of an input with a simple set animation, and the value will remain even after the animation expires.

Without this special-casing of state properties, the system would be mostly unusable. Note that state:actioned and state:pointer cannot be manipulated by script or markup; only the user can change those values (although there is a bug in iHDSim that will let you set state:actioned... ooops).

The example zip file shows graphically what happens with the hierarchy of control for style:x. The two top buttons are used to toggle a markup-based animation and a script-based animation. The grey circle and the white circle have identical initial DOM values for style:x, and they have identical markup animations when you click the "Animation" button. Additionally, the white circle can be animated by script when you click the "Script" button. The graphic at the bottom of the screen (which initially says "At Rest") tells you who is in control of the white circle. Basically you can click the "Animate" and "Script" buttons in various different combinations and see how it affects the white circle versus the grey circle. There is no example of animating state properties because, well, that's boring ;-)

unsetPropertyBlog.zip