Toggling Menus with the Menu button in 100% Markup

Toggling Menus with the Menu button in 100% Markup

  • Comments 6

Here's a quick one: How do you have an HD DVD menu that opens and closes when you click the Menu button, but doesn't require any script?

It's pretty easy, but it relies on using a dummy element to hold your state; in this case whether the menu "can open" or whether the menu "can close." For this example (which is incredibly ugly), we'll have a hidden div called "CurrentMenuState" that is at x=0px when the menu "can open", and at x=300px when the menu "can close". I chose those numbers rather arbitrarily.

Comments in the XML should make it clear what is happening:

<?xml version="1.0"?>

<root xml:lang="en" xmlns="http://www.dvdforum.org/2005/ihd" xmlns:style="http://www.dvdforum.org/2005/ihd#style" xmlns:state="http://www.dvdforum.org/2005/ihd#state">

  <head>

    <styling>

     

      <!--Default style for buttonson the menu; just something basic-->

      <style id="MenuButton"

        style:position="absolute"

        style:width="300px" style:height="100px"

        style:x="100px"

        style:opacity="0.5" />

     

    </styling>

    <timing clock="page">

      <defs>

 

        <!--Animations to slide the menu open and closed-->

        <animate id="OpenMenu" style:x="-500px;0px" />

        <animate id="CloseMenu" style:x="0px;-500px" />

       

        <!--Make something display-->

        <set id="Show" style:display="auto" />

 

        <!--Make something opaque-->

        <set id="MakeOpaque" style:opacity="1"/>

 

        <!--Two states the menu can be in-->

        <set id="STATE_MENU_CAN_OPEN" style:x="0px"/>

        <set id="STATE_MENU_CAN_CLOSE" style:x="300px"/>

      </defs>

 

      <par>

 

        <!--Dummy animation; highlight the menu buttons when clicked-->

        <cue begin="class('MenuButton')[state:actioned()]" dur="0.5s" use="MakeOpaque" />

       

        <!--Open the menu; begin when the button is clicked and state is CAN_OPEN.-->

        <!--end when the button is clicked and the state is CAN_CLOSE.-->

        <par begin="(id('ToggleMenu')[state:actioned()] and id('CurrentMenuState')[style:x()='0px'])"

          end="(id('ToggleMenu')[state:actioned()] and id('CurrentMenuState')[style:x()='300px'])">

         

          <!--Update state to CAN_CLOSE-->

          <cue select="id('CurrentMenuState')" dur="1s" fill="hold" use="STATE_MENU_CAN_CLOSE" />

         

          <!--Animate the menu open and hold it there-->

          <cue select="id('MenuContainer')" dur="1s" fill="hold" use="Show" />

          <cue select="id('MenuContainer')" dur="1s" fill="hold" use="OpenMenu" />

        </par>

 

        <!--Close the menu; begin when the button is clicked and state is CAN_CLOSE.-->

        <!--end when the menu has hit the end of its animation, or when the button is clicked again-->

        <par begin="(id('ToggleMenu')[state:actioned()] and id('CurrentMenuState')[style:x()='300px'])"

          end="(id('MenuContainer')[style:x()='-500px'] or (id('ToggleMenu')[state:actioned()] and id('CurrentMenuState')[style:x()='0px']))">

 

 

          <!--Update state to CAN_OPEN-->

          <cue select="id('CurrentMenuState')" dur="1s" fill="hold" use="STATE_MENU_CAN_OPEN" />

 

          <!--Animate the menu closed-->

          <cue select="id('MenuContainer')" dur="1s" fill="hold" use="CloseMenu" />

          <cue select="id('MenuContainer')" dur="1s" fill="hold" use="Show" />

        </par>

 

      </par>

 

    </timing>

  </head>

  <body>

 

    <div style:position="absolute" style:x="0px" style:width="1920px" style:y="0px" style:height="1080px" style:backgroundColor="black">

 

      <!--Button with access key of VK_MENU. Doesn't need to be visible, but it's there-->

      <!--so you can click it if you can't get the Menu button working (USB keyboard)-->

      <button id="ToggleMenu"

        style:position="absolute"

        style:width="100px" style:height="100px"

        style:x="600px" style:y="600px"

        style:backgroundColor="white"

        accessKey="VK_MENU"/>

 

      <!--Simple container to hold the menu buttons. This is what animates-->

      <!--Starts out hidden and off-screen, since that is its "at rest" location-->

      <div id="MenuContainer"

        style:position="absolute"

        style:x="-500px" style:y="0px"

        style:width="500px" style:height="1080px"

        style:backgroundColor="gray" style:display="none">

 

        <!--Some dummy buttons that don't do anything.-->

        <!--We hired them for their looks, not their ability-->

        <button id="Play"

          style="MenuButton" class="MenuButton"

          style:y="100px"

          style:backgroundColor="yellow" />

       

        <button id="Chapters"

          style="MenuButton" class="MenuButton"

          style:y="300px"

          style:backgroundColor="red" />

       

        <button id="Features"

          style="MenuButton" class="MenuButton"

          style:y="500px"

          style:backgroundColor="lime" />

       

      </div>

     

      <!--The hidden div we use to hold the menu's state-->

      <!--We could use an input and store information in it,-->

      <!--but that makes the sample harder because you need-->

      <!--to reference a font, put it in the right place, etc.-->

      <div id="CurrentMenuState"/>

    </div>

  </body>

</root>

 

  • Nice post ;)

    Very helpful.  I had a much more difficult time implementing this in the script.

  • You mentioned that you could have used an input vs. the hidden div.  But what about a button?  Then you use state:value to track the menu state.  

    Right?

    What would be the downsides of doing it that way?

  • Trouble is that the end is evaluated at the same time as the begin, so if you both begin and end when the button is clicked, the cue will never become active.

  • Hi Peter,

    Thanks for the sample code... everything makes perfect sense, however I can't get this example to work using Sonic's emulator.  Works great in iHDSim, but blows up Sonic with an 'Abnormal Program Termination', leaving no useful clue in the debug window or HDDVDValidator

    Any tips/advice to get this work outside of iHDSim?

    Thanks in advance!

  • It might be the boolean conditions they don't like.

    Try something like this instead (on all the XPaths):

    -----

    id('ToggleMenu')[state:actioned() and style:x(id('CurrentMenuState'))='300px']

    -----

    where instead of and-ing together two nodesets co-erced to booleans, the entire expression is put inside a predicate.

  • Thanks for the help Peter, the problem was in the XPath syntax.  In case anyone else is running into this problem, the open menu and close menu XPaths work when written like this:

    <par begin="id('ToggleMenu')[state:actioned() and (id('CurrentMenuState')[style:x()='0px'])]" end="id('ToggleMenu')[state:actioned() and (id('CurrentMenuState')[style:x()='300px'])]">

    <par begin="id('ToggleMenu')[state:actioned() and (id('CurrentMenuState')[style:x()='300px'])]"           end="id('MenuContainer')[style:x()='-500px' or (id('ToggleMenu')[state:actioned() and (id('CurrentMenuState')[style:x()='0px'])])]">

Page 1 of 1 (6 items)