9. Basic Interactivity
In this tutorial, we're going to learn how to handle "interactive scene3d events", in particular the events which occur when your mouse moves over an object, out of an object and clicks an object. We're going to make something like this:
When you place your mouse over the plane, the material will change. When you click it, it will spin in the opposite direction.
Unfortunately we have to edit the base class.. again.. All we need to do is change one line so that the viewport becomes interactive when we initialise it.
Open up PaperBase.as, and find this line:
-
viewport = new Viewport3D(vpWidth, vpHeight);
Swap it for this line:
-
viewport = new Viewport3D(vpWidth, vpHeight, false, true);
This will make the viewport interactive, which means it can trigger events.
Now that you've updated the base class, create a new project. Make the Main class extend PaperBase as usual and then add the following imports:
-
import org.papervision3d.materials.BitmapFileMaterial;
-
import org.papervision3d.objects.DisplayObject3D;
-
import org.papervision3d.events.InteractiveScene3DEvent;
-
import org.papervision3d.objects.primitives.Plane;
Now, add the following declarations under "public class Main extends PaperBase {" :
-
private var ourMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front.jpg");
-
private var ourOverMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front_over.jpg");
-
private var yawspeed:Number = 5;
-
private var plane :DisplayObject3D;
ourMaterial is the material that we'll put onto the plane.
ourOverMaterial is the material that will be activated on mouse over.
We'll load both of these materials from files on my server.
yawspeed will be how much we're going to yaw() the plane by each frame
and "plane" will be the plane.
This next function will show you how to make the material interactive, and how to add an event listener to the stage:
-
override protected function init3d():void {
-
ourMaterial.interactive = true; // You need to set the interactive property of the materal to true.
-
ourMaterial.doubleSided = true; // We want to be able to see both sides of the plane
-
ourOverMaterial.interactive = true; // Same for the mouseover material
-
ourOverMaterial.doubleSided = true;
-
-
plane = new Plane(ourMaterial, 1000, 1000, 4, 4); // Create a new plane
-
default_scene.addChild(plane); // Add it to the scene
-
-
// These lines add event listeners to the plane which will trigger the functions on the event specified.
-
plane.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress ); // Will trigger "onPress" when the object is pressed (clicked)
-
plane.addEventListener( InteractiveScene3DEvent.OBJECT_OVER, onOver ); // Will trigger "onOver" when the mouse rolls over the object
-
plane.addEventListener( InteractiveScene3DEvent.OBJECT_OUT, onOut ); // Will trigger "onOut" when the mouse rolls out of the object
-
}
I've commented the code so it should be easy to understand.
Now we need to add the "on..." functions. You can do whatever you want in these functions, but in this tutorial we're going to make the effect like above.
-
private function onOver ( e:InteractiveScene3DEvent ):void {
-
plane.material = ourOverMaterial; // Change the material to "ourOverMaterial"
-
}
-
-
private function onOut ( e:InteractiveScene3DEvent ):void {
-
plane.material = ourMaterial; // Change the material back to "ourMaterial"
-
}
-
-
private function onPress( e:InteractiveScene3DEvent ):void {
-
yawspeed *= -1; // Reverse the yaw speed
-
}
Finally, we need to add the processFrame code, to rotate the plane by the angle "yawspeed".
-
override protected function processFrame():void {
-
plane.yaw(yawspeed);
-
}
Done! Run the project and you should see the result like above. Here's the complete code:
-
package {
-
import org.papervision3d.materials.BitmapFileMaterial;
-
import org.papervision3d.objects.DisplayObject3D;
-
import org.papervision3d.events.InteractiveScene3DEvent;
-
import org.papervision3d.objects.primitives.Plane;
-
-
public class Main extends PaperBase {
-
-
private var ourMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front.jpg");
-
private var ourOverMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front_over.jpg");
-
private var yawspeed:Number = 5;
-
private var plane :DisplayObject3D;
-
-
public function Main() {
-
init();
-
}
-
-
override protected function init3d():void {
-
ourMaterial.interactive = true;
-
ourMaterial.doubleSided = true;
-
ourOverMaterial.interactive = true;
-
ourOverMaterial.doubleSided = true;
-
-
plane = new Plane(ourMaterial, 1000, 1000, 4, 4);
-
default_scene.addChild(plane);
-
-
plane.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress );
-
plane.addEventListener( InteractiveScene3DEvent.OBJECT_OVER, onOver );
-
plane.addEventListener( InteractiveScene3DEvent.OBJECT_OUT, onOut );
-
}
-
-
private function onOver ( e:InteractiveScene3DEvent ):void {
-
plane.material = ourOverMaterial; // Change the material to "ourOverMaterial"
-
}
-
-
private function onOut ( e:InteractiveScene3DEvent ):void {
-
plane.material = ourMaterial; // Change the material back to "ourMaterial"
-
}
-
-
private function onPress( e:InteractiveScene3DEvent ):void {
-
yawspeed *= -1; // Reverse the yaw speed
-
}
-
-
override protected function processFrame():void {
-
plane.yaw(yawspeed);
-
}
-
}
-
}




Luke,
Thanks for the great tutorial, and released just in time! just yesterday at work I was struggling trying to get mouse events to fire in papervision.
HI Luke,
thanks for the turorial. I am wondering if there is a way to add events to a MovieClip (or button) inside the plane. I mean: Is it possible to load a MovieClip, which contains a button and add an event to this button, instead of adding an event to the plane?
Instead loading a picture, I load a movieClip. This works fine. But I cannot add functionality to the buttons of that movieclip, because I 1. don't know the name of the plane on stage (and the movieclip in it).
Is there an easy solution?
Mike
Hi Mike,
There is a solution, I'm going to work on getting an example ready (it's fairly complex).
-Luke
COOL!
I cannot wait to see it.
Mike
Hi,
I have a solution, how to grant a loaded (into a pane) MovieClip acccess to the main root. I had the problem, that I needed some variables of the main DocumentClass on stage and I had no chance to find out, if the movie is dynamically loaded into a pane, what the name of its instance is, to assign the needed values from the main DocumentClass to the loaded MovieClip instance.
Solution:
In the Library you can see the preferences of each MovieClip. I used for example a clip named startscreen in the library. To give access to the main root, I just created a new class named startcreen and add root to the first method (startscreen).
package
{
class startscreen extends MovieClip
{
public function startscreen(mainRoot):void
{
trace("Root from Main = "+mainRoot);
}
}
}
in my main class, connected to my main .fla, I have the following:
instancedMC = new startscreen(root);
Hopefully it helps someone.
Mike
I cannot get this to work with the effects branch of papervision, It seems that the material is not swapping out, I traced it out and the rollover and off events are being called.
any ideas / tips / suggestions?
Do I need to move some classes over from the Great White branch?
Hi Luke!
Great stuff, I really appreciate the work you put into these tutorials. Yours is the best out there.
It's a bit off topic here, but i'll ask...
1. I used getSprite in pv3d 1.5 to be able to chage the alpha of a display object, what's the equivalent of this method in the greatwhite?
2. Is there a way to set an object's cordinates? I mean i have a container with several objects in it. Calculating the world coordinates is easy, until i rotate the container... I know i could calculte it with trigonometry, but there has to be an easier way. I've found the sceneX, sceneY and sceneZ properties of the DO3D, and was happy for like 2 minutes, until I've found out that they're read only properties...
Cheers
[...] you haven't read it already, I strongly suggest that you read the Basic Interactivity tutorial first or you'll probably miss [...]
Hi,
I have tried out the above example on a static plane. And I found a strange flicker taking place when moving over certain areas of the plane especially the center. I rechecked this tutorial animation again at the top out here and when I moved the mouse fast over single area over it from one half to the other half. There was noticeable flickering. Please let me know if a solution exists for that and what should be done.
If you think that why should a user rapidly move the mouse over a plane just to find the flicker. I had to move it rapidly because the plane is rotating using yawspeed above. My plane requirement is static and as the user moves his mouse across he will see the flicker in a blink. And if I have half a dozen planes. Lots of flickers.
Is it just me or is something remaining to be added to solve this?
Oh well. You can move the mouse diagonally slowly as well over the animated plane above and still notice the flicker. Awaiting your feedback.
Hi Gelwin,
Sorry for the delay in getting back to you, I've been away for a few days..
Do you by any chance have more than one plane in the exact same position and rotation?
If you place two objects in exactly the same position, you'll get "Z-fighting" which is where papervision doesn't know which face is on top so it will often flicker them - this happens with pretty much all 3d engines, not just Papervision.
If you send me your code I'll take a look..
-Luke
Hi,
Regarding the planes. Nope. Right now I am using a single plane only. The only thing that I havent used from the example above is the yaw method. Please let me know where I should post you my code. However if you want to replicate the problem just remove the yaw from the above example and move your mouse around the plane. You should see the over function being called couple of times. Thanks for the reply and my apologies for the earlier post.
Hrmm, I think I know why..
Are you using the events OBJECT_OVER and OBJECT_OUT, or the OBJECT_MOVE event?
-Luke
Yes ofcourse. And whenever you move the mouse to the center area of the plane. It happens almost instantly.
Sorry. These are the events I am using and not OBJECT_MOVE event
OBJECT_PRESS
OBJECT_OVER
OBJECT_OUT
Hrmm, ok
Could you paste your code into a comment, wrap it in [ as ] tags without the spaces, so like this:
[as]
Your code here..
[/as]
Thanks!
Have you encountered the flicker as yet. I used the code straight out from the tutorial making the changes to the viewport as mentioned. Just comment out the statement
// plane.yaw(yawspeed);
and rerun the above project. Move the mouse near the center area slowly and you will see the over and out being called. Is the plane mesh formed of triangular surfaces or something because of which this is happening. Or is this a false alarm from my end only?
Ok I'll take a look..
I request you to please delete certain posts if they are taking up heightened space. Its not good to have so many similar posts on a blog I think. It may confuse others.
Ok I'm not getting any flicker but I think I know a way to fix it, or at least reduce the flicker.. (And I'll delete all these comments when we resolve this)..
Try adding this code, firstly with all the other "private var" lines, add this:
private var over:Number = 0;
Then, in your "onOver" function code, put this:
over = 1;
in "onOut", put this:
over = -1;
Finally in "processFrame", put this:
if (over == 1) {
plane.material = ourOverMaterial;
}else if (over == -1) {
over++;
}else{
plane.material = ourMaterial;
}
Tell me if you have any luck with that
I think it won't be -perfect- but it'll be better.
-Luke
Brilliant!!!
Yes it has reduced the flicker. No longer flickers when I hover on the center area but happens when I move the mouse diagonally sometimes.
But otherwise its a 70% improvement. I dont quite understand the change though. It seems to do similar functionality only that now we are using variables as a replacement. How do we reach zero tolerance system? Is Render being called immediately after changing the material which wasnt happening earlier or something?
Basically, all the code does is set a variable called "over" to -1 when your mouse leaves. If that variable is -1 on the next render then it's ignored for 1 frame.
Do "trace(over);" in processFrame and you should be able to work it out.
I'm not sure how to make it perfect, try following the advanced interactivity tutorials - one of the techniques in those might work better..
-Luke
Correction I retested again and everything is A perfect - No flicker. I suppose i might have moved the mouse out of plane area. No flickers any more.
Thanks so much Luke. It was mighty helpful to have to solve it right away. Strange though that you didnt encounter the flicker at all. But now that its solved. Great and thanks for the tutorial too.
Hi, great site.
Is that tutorial working on the last SVN/branch/effects or great white?
everything is working but the over and out, I trace the material in the set material function in DisplayObject3D, which is fine.
I just can't see the material change, any clue?
I paste your code, and still not working, no error in flash.
Romu
Romu have you checked this
viewport = new Viewport3D(vpWidth, vpHeight, false, true);
This will make the viewport interactive. If already done then it may be something else.
Regarding the example, it uses papervision2 alias codename greatwhite
yes, it is the parameters for the viewport3D are fine, I tried to make it work but it seems I can't change the material once assigned.
I'm actually seeing the same issue - I used to be able to swap materials and now I can't. When I trace out the material, its changed. But no visual change!
hi. is that possible to add a movieclip to a papervision2 scene? not as a material for planes or cubes or any other 3D object, but simple adding a 2D movieclip to the scene. i tryed to do that but without sucess. Blitz agency launch a way to do that but its work only in papervision 1 version http://labs.blitzagency.com/?p=377 personaly I think this is a very important point to use papervision as some projects can included 3d objects and also normal movieclips without having to draw complex objects to show the 2D object. any clues to implement this feature of adding MovieClips in papervision2 ?
I'm getting the same material issue. Did anyone get a fix for this? The materials don't swap visually and there's no error message.
Thanks for the great tutorials!
I found a fix for instances where all you need to do is change a bitmap:
myPlane.material.bitmap = myNewMaterial.bitmap;
That worked for me. material = newMaterial didn't update visually, but on tracing the material it showed it had updated.
Hope that helps someone!
I am not getting the over image to display upon mouse over
Having trouble making it work in Great White?
Does the object think the material has changed but you don't see it?
Here's the solution:
Instead of
plane.material = ourOverMaterial;
put:
plane.material.copy( ourOverMaterial );
My god, this has cost me too much time. I hope this will save it for others!
I am having the same issue of not being able to see the onOver/onOut effect too. The example above works only one way. Doesn't work for onOut.
Hi,
How could I have different image on the back side of the plane?
like rondog.
is it a bug in papervision?
Thanks a lot to Michiel van der Ros,
the hint with the "material.copy" was really a great help!
Same problem as rondog:
onOver works with "plane.material.copy", but onOut doesn't..
Hi guys!
Just a thought I want to share because maybe somebody else will have the same problem as me. Maybe it's stupid, I don't know, but I've just lost 2 hours trying to figure it out (note that I'm blonde, maybe this explains that
):
I thought that setting the material.interactive to true was done in this tutorial to allow the change of material when an event occurs...
So I didn't write this line, thinking: "I just want to trace a hello world to check that the event has been correctly dispatched. What a mistake!!!
In fact, you have to set your object's material interactive parameter to true in order for the events to be detected! It has nothing to do with the fact that the material changes in this tutorial!
Voila! I hope it can save somebody some time!
Hi Luke,
I'm trying to make some of your examples work, but I'm having a strange issue.
Everytime I click on a plane to make it move, the whole stage gets a few pixels
to the right... It onle happens for the first time in the run.
I've tried using stage.align from flash but didn't work, have you seen something
like this with the paperbase class?
Thanks!
Hi there, and thanks for this tutorial.
There something i don't understand:
why do we have to set the material interactive property to true since the events we listen to are dispatched by the plane?
see ya!
We have an issue and i also noticed it on the dice demo you have. When you click on a plane the other planes will not register a click event for their plane until you do a mouse move. Instead it continues to register a click for the first plane you click.
Example i have 4 planes that go in a carousel fashion. if i click on the first panel it will register correctly. If i dont move the mouse and i click the button it will not register the next plane until i move the mouse instead it just says you click item 1 again. I notice this in your 6 sided cube too. can you take a look and let me know what we can do to get around this? Maybe a call we can make to have it manually change targets or update its target to mouse droptarget?
I've copied the tutorial as and I have the image spinning, but the mouse interaction is no go.. so far on any pv apps I've done I can't get any mouse interaction. I'm using the OBJECT_OVER event and everything... help? keep in mind I am using the exact PaperBase from this site and exact Main class from this page.
you have to set the interactivity property of the viewport:
...
viewport = new Viewport3D(vpWidth, vpHeight);
viewport.interactive = true;
...
Hi, I have managed to get this working with a 3D interactive globe, however, as soon as I overlay the 3D elements with 2D elements (some stars etc) using your init2d function the interactivity no longer works. I don't think I am able to click through the 2D elements to the buttons underneath! Is there a fix for this? Cheers, Neil
Hi,
I have pv3d class packages loaded into flash, but errors say "packages cannot be nested". honestly, i don't know what that means, and i can't get it to do what the above tutorial does. Any suggestions or help? thanks!
Todd
Finally figured this thing out. I am running FlashCS3 on Mac. Thought the swf displays fine, and also the rollover, I get this warning message.
Warning: 1090: Migration issue: The onPress event handler is not triggered automatically by Flash Player at run time in ActionScript 3.0. You must first register this handler for the event using addEventListener ( 'mouseDown', callback_handler).
@marcus - thanks! making the viewport.interactive = true got this owkring for me! thanks again for posting your solution! and thanks for this great tutorial luke!