
Page 3 of 5
What is the mouse doing over the image?
Let's find out! Open up your qtvr Movie Clip and select the driver Movie Clip. We're going to find out what our driver Movie Clip can do with the mouse. Let's do some testing.
Enter this code on the driver Movie Clip:
onClipEvent (enterFrame) {
trace(_xmouse);
}
The trace command will write out its arguments (the bits in the parenthesis) to the Output window when you preview Flash MX movies. So: preview that (Ctrl+Enter) now. Notice that the _xmouse variable returns the x position of the mouse (left-right value) in relation to the Movie Clip that the code sits on (in this case it's the driver clip).

The reason we're doing this is that we want to somehow convert the position of the mouse to one of our QTVR movie frames (1 through to 36 for us). Our approach was to scale the driver movie. No matter how wide or narrow you make the driver clip, _xmouse will always return 0 to 100 when you move the mouse across it (because we made it with a shape that had a width of 100). Try stretching the driver clip and previewing the movie.
If we think of _xmouse as a percentage of rotation that we want the QTVR movie to go through, then the area of screen that we stretch it over will give us a visual indication of how much mouse movement we are expecting users to make to get a full rotation of the object.
Now we need to convert the 0 to 100 percentage to a fraction by dividing _xmouse by 100. If we multiply this by 36 (the number of frames we have ? yours will be different) we will have the frame that we want to show. Try this new code and preview it:
onClipEvent (enterFrame) {
trace(_xmouse / 100 * 36);
}
The Output window will show the frame that we should be displaying according to where the mouse is. Unfortunately, we are not getting exact frame numbers, so let's convert the number to an integer. Here's the code:
onClipEvent (enterFrame) {
trace(int(_xmouse / 100 * 36));
}
That's better, but there's still some weirdness. The 1 to 36 is good: we have those frames. Anything out of that range is no use to us at all.
Time to roll out the modulo operator (%). When you use modulo, you get a remainder as a result. 4 % 2 gives remainder 0. 3 % 2 gives remainder 1. If we take our _xmouse calculation and do a modulo 36 we should get a remainder between 0 and 35. Add 1 and we have a good range of 1 to 36. Try it:
onClipEvent (enterFrame) {
trace(int(_xmouse / 100 * 36) % 36 + 1);
}
Here are the formulas that we have been playing with so far (the box header in the table indicates the "invisible box" shape we made, and the shaded areas show where our 36 frames are repeating):

You can try them out in a trace ActionScript statement to see how they perform as you move your mouse over the QTVR movie to the right.
If you're interested, you can read more about the modulo operator here "ActionScript Dictionary > Symbols > % (modulo)", and the int function here "ActionScript Dictionary > G-L > int" in the contents of your online help. (I know int has been deprecated since Flash 5 in favour of the Math.round method, but round doesn't do what int does so I'm going to use it anyway!)
If you want to see how this will spin the movie, try this code:
onClipEvent (enterFrame) {
_parent.gotoAndStop(1 + (int(_xmouse / 100 * 36) % 36));
}
We make use of the _parent object to do this. It refers to the parent of the Movie Clip in which the code is running. In other words, the parent Movie Clip of our driver clip is our qtvr clip. Have a look in the Movie Explorer (Alt+F3) to see how things relate to each other.
We are using _parent with the gotoAndStop method because without it, gotoAndStop would try to move the playhead of the driver Movie Clip, and that would be pointless 'cos the QTVR movie is in the qtvr Movie Clip (and that's just where we want it).
The info for gotoAndStop is here "ActionScript Dictionary > M > MovieClip.gotoAndStop" in the contents of your online help.
Moving to the left of the image
Now it's not really working when it goes below 0, so we need to adjust our formula when the mouse pointer moves to the left of our box. Our first problem is that as we are moving to the left our range is starting at -1, and we would like it to start at 0. (It actually does start at 0, but unfortunately it overlaps with the code we have already written: that's where the funkiness is creeping in.)
To correct this, we need to add 1 to our _xmouse calculation before we perform the modulo. That gets us closer to what we want, but we still have negative numbers. Since we don't have any negative frames, we finally need to correct this by adding 36.
This may be seen in the following table (the red area shows the bit that we already have working, the grey areas show where the 36 frames to the left of the box are repeating):

Once again, you can try them out in a trace ActionScript statement to see how they perform as you move your mouse left of the QTVR movie. And this is the code to spin the movie:
onClipEvent (enterFrame) {
_parent.gotoAndStop(36 + ((int(_xmouse / 100 * 36)+ 1) % 36));
}
Combining the formulas
We now have two formulas: one for zero and above, and the other for below zero. To combine these, we will make use of an if-else statement block. Also, a quick look at the formulas that we have been experimenting with shows that the int(_xmouse / 100 * 36) part gets used quite a bit (and we'll need to use it again in the if statement's condition test). Let's put that into a variable so that we don't have to calculate it over and over again. Here's the code for our driver Movie Clip:
onClipEvent (enterFrame) {
framePos = int(_xmouse / 100 * 36);
if (framePos < 0) {
_parent.gotoAndStop(36 + ((framePos + 1) % 36));
} else {
_parent.gotoAndStop(1 + (framePos % 36));
}
}
This is all very well if your QTVR movie is of an object rotating anticlockwise (as seen from above), but if your object rotates clockwise then you have a problem. What you end up with is an object that seems to rotate from right to left as you move your mouse from left to right. (If you have a look at the series of images that we had for the diving helmet, you can see that our QTVR movie rotated clockwise.)
The effect we are after is similar to the experience of running your hand across a prayer wheel: you expect the surface that you touch to move in the same direction.
The simple solution is to subtract our 1 to 36 value from 37. This will give us a range that runs in the other direction (36 to 1). This is what we needed for the "Western Australia: Land and People" exhibition, but your Object VR may well run in the other direction. Use what you need. Here's our code so far:
onClipEvent (enterFrame) {
framePos = int(_xmouse / 100 * 36);
if (framePos < 0) {
_parent.gotoAndStop(37 - (36 + ((framePos + 1) % 36)));
} else {
_parent.gotoAndStop(37 - (1 + (framePos % 36)));
}
}
Making the driver handle any movie length
Throughout all of our examples here, I have focussed on only one QTVR movie: the one supplied by the Western Australian Museum. It has 36 frames in it and runs at 1 fps. Your Object VR will inevitably have a different length and changing the magic numbers of 36 and 37 that we have used here to other magic numbers that relate to the number of frames in other movies will only lead to pain. So let's fix that.
The _parent object has a _totalframes property which lets us know how many frames are in the parent Movie Clip. In our case, when we use the code _parent._totalframes in our driver clip's enterFrame event handler, Flash MX looks at the qtvr clip and checks to see how many frames it has (36 for ours, yours will probably be different).
Replacing 36 with _parent._totalframes, and 37 with (_parent._totalframes + 1) gives us our new code:
onClipEvent (enterFrame) {
framePos = int(_xmouse / 100 * _parent._totalframes);
if (framePos < 0) { _parent.gotoAndStop(_parent._totalframes + 1 - (_parent._totalframes + ((framePos + 1) % _parent._totalframes)));
} else {
_parent.gotoAndStop(_parent._totalframes + 1 - (1 + (framePos % _parent._totalframes)));
}
}
This lets our driver clip handle any length QTVR movie as long as we have the same number of frames in the driver and mov layers. If the driver layer has more frames than the mov layer, the Object VR will disappear for some frames. If the mov layer has more frames than the driver layer, the Object VR will get stuck when it hits a frame where the driver doesn't exist.
Making the code simple
Those of you who can remember back to high school algebra will be able to see that these formulas can be simplified further by multiplying out and cancelling terms with opposite signs, resulting in our final clockwise code:
onClipEvent (enterFrame) {? //clockwise
framePos = int(_xmouse / 100 * _parent._totalframes);
if (framePos < 0) {
_parent.gotoAndStop(1 - ((framePos + 1) % _parent._totalframes));
} else {
_parent.gotoAndStop(_parent._totalframes - (framePos % _parent._totalframes));
}
}
And applying the same process to our anticlockwise code gives:
onClipEvent (enterFrame) {? //anticlockwise
framePos = int(_xmouse / 100 * _parent._totalframes);
if (framePos < 0) {
_parent.gotoAndStop(_parent._totalframes + ((framePos + 1) % _parent._totalframes));
} else {
_parent.gotoAndStop(1 + (framePos % _parent._totalframes));
}
}
This makes it really easy to build an Object VR player for any QTVR movie of any length by simply grabbing the code that is appropriate for the rotation of your video file and pasting it on to your driver clip.
Time to wrap things up. Let's have a quick look at how to use our player.

