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:

Actionscript:
  1. viewport = new Viewport3D(vpWidth, vpHeight);

Swap it for this line:

Actionscript:
  1. 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:

Actionscript:
  1.    import org.papervision3d.materials.BitmapFileMaterial;
  2.     import org.papervision3d.objects.DisplayObject3D;
  3.     import org.papervision3d.events.InteractiveScene3DEvent;
  4.     import org.papervision3d.objects.primitives.Plane;

Now, add the following declarations under "public class Main extends PaperBase {" :

Actionscript:
  1.       private var ourMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front.jpg");
  2.        private var ourOverMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front_over.jpg");
  3.        private var yawspeed:Number = 5;
  4.        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:

Actionscript:
  1.       override protected function init3d():void {
  2.          ourMaterial.interactive = true; // You need to set the interactive property of the materal to true.
  3.          ourMaterial.doubleSided = true; // We want to be able to see both sides of the plane
  4.          ourOverMaterial.interactive = true; // Same for the mouseover material
  5.          ourOverMaterial.doubleSided = true;
  6.          
  7.          plane = new Plane(ourMaterial, 1000, 1000, 4, 4); // Create a new plane
  8.          default_scene.addChild(plane); // Add it to the scene
  9.          
  10.          // These lines add event listeners to the plane which will trigger the functions on the event specified.
  11.          plane.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress ); // Will trigger "onPress" when the object is pressed (clicked)
  12.          plane.addEventListener( InteractiveScene3DEvent.OBJECT_OVER, onOver ); // Will trigger "onOver" when the mouse rolls over the object
  13.          plane.addEventListener( InteractiveScene3DEvent.OBJECT_OUT, onOut ); // Will trigger "onOut" when the mouse rolls out of the object
  14.        }

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.

Actionscript:
  1.       private function onOver ( e:InteractiveScene3DEvent ):void {
  2.          plane.material = ourOverMaterial; // Change the material to "ourOverMaterial"
  3.        }
  4.       
  5.        private function onOut ( e:InteractiveScene3DEvent ):void {
  6.          plane.material = ourMaterial; // Change the material back to "ourMaterial"
  7.        }
  8.       
  9.        private function onPress( e:InteractiveScene3DEvent ):void {
  10.          yawspeed *= -1; // Reverse the yaw speed
  11.        }

Finally, we need to add the processFrame code, to rotate the plane by the angle "yawspeed".

Actionscript:
  1.       override protected function processFrame():void {
  2.          plane.yaw(yawspeed);
  3.        }

Done! Run the project and you should see the result like above. Here's the complete code:

Actionscript:
  1. package  {
  2.     import org.papervision3d.materials.BitmapFileMaterial;
  3.     import org.papervision3d.objects.DisplayObject3D;
  4.     import org.papervision3d.events.InteractiveScene3DEvent;
  5.     import org.papervision3d.objects.primitives.Plane;
  6.     
  7.     public class Main extends PaperBase {
  8.       
  9.        private var ourMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front.jpg");
  10.        private var ourOverMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front_over.jpg");
  11.        private var yawspeed:Number = 5;
  12.        private var plane :DisplayObject3D;
  13.       
  14.        public function Main() {
  15.          init();
  16.        }
  17.       
  18.        override protected function init3d():void {
  19.          ourMaterial.interactive = true;
  20.          ourMaterial.doubleSided = true;
  21.          ourOverMaterial.interactive = true;
  22.          ourOverMaterial.doubleSided = true;
  23.          
  24.          plane = new Plane(ourMaterial, 1000, 1000, 4, 4);
  25.          default_scene.addChild(plane);
  26.          
  27.          plane.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress );
  28.          plane.addEventListener( InteractiveScene3DEvent.OBJECT_OVER, onOver );
  29.          plane.addEventListener( InteractiveScene3DEvent.OBJECT_OUT, onOut );
  30.        }
  31.       
  32.        private function onOver ( e:InteractiveScene3DEvent ):void {
  33.          plane.material = ourOverMaterial; // Change the material to "ourOverMaterial"
  34.        }
  35.       
  36.        private function onOut ( e:InteractiveScene3DEvent ):void {
  37.          plane.material = ourMaterial; // Change the material back to "ourMaterial"
  38.        }
  39.       
  40.        private function onPress( e:InteractiveScene3DEvent ):void {
  41.          yawspeed *= -1; // Reverse the yaw speed
  42.        }
  43.       
  44.        override protected function processFrame():void {
  45.          plane.yaw(yawspeed);
  46.        }
  47.     }
  48. }

48 Comments

  1. Comment by Dustin on February 10, 2008 2:25 am

    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.

  2. Comment by milo on February 11, 2008 1:28 pm

    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

  3. Comment by Luke on February 14, 2008 12:07 am

    Hi Mike,

    There is a solution, I'm going to work on getting an example ready (it's fairly complex).

    -Luke

  4. Comment by milo on February 14, 2008 1:44 pm

    COOL!

    I cannot wait to see it. :)

    Mike

  5. Comment by milo on February 14, 2008 4:49 pm

    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

  6. Comment by Pete on February 15, 2008 7:28 pm

    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?

  7. Comment by HomerJay on February 15, 2008 8:27 pm

    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

  8. Pingback by Papervision 2 » 10. Advanced Interactivity on February 17, 2008 10:07 pm

    [...] you haven't read it already, I strongly suggest that you read the Basic Interactivity tutorial first or you'll probably miss [...]

  9. Comment by Gelwin on February 26, 2008 6:38 am

    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?

  10. Comment by Gelwin on February 26, 2008 6:43 am

    Oh well. You can move the mouse diagonally slowly as well over the animated plane above and still notice the flicker. Awaiting your feedback.

  11. Comment by Luke on February 26, 2008 11:35 am

    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

  12. Comment by Gelwin on February 26, 2008 11:56 am

    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.

  13. Comment by Luke on February 26, 2008 11:59 am

    Hrmm, I think I know why..

    Are you using the events OBJECT_OVER and OBJECT_OUT, or the OBJECT_MOVE event?

    -Luke

  14. Comment by Gelwin on February 26, 2008 12:11 pm

    Yes ofcourse. And whenever you move the mouse to the center area of the plane. It happens almost instantly.

  15. Comment by Gelwin on February 26, 2008 12:12 pm

    Sorry. These are the events I am using and not OBJECT_MOVE event

    OBJECT_PRESS
    OBJECT_OVER
    OBJECT_OUT

  16. Comment by Luke on February 26, 2008 12:18 pm

    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!

  17. Comment by Gelwin on February 26, 2008 12:18 pm

    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?

  18. Comment by Luke on February 26, 2008 12:22 pm

    Ok I'll take a look..

  19. Comment by Gelwin on February 26, 2008 12:22 pm

    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.

  20. Comment by Luke on February 26, 2008 12:36 pm

    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

  21. Comment by Gelwin on February 26, 2008 12:42 pm

    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?

  22. Comment by Luke on February 26, 2008 12:46 pm

    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

  23. Comment by Gelwin on February 26, 2008 12:47 pm

    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.

  24. Comment by Gelwin on February 26, 2008 12:54 pm

    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. :)

  25. Comment by Romu on February 29, 2008 6:15 pm

    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

  26. Comment by Gelwin on March 1, 2008 11:22 am

    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

  27. Comment by Romu on March 3, 2008 9:31 am

    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.

  28. Comment by danny on March 14, 2008 8:48 pm

    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!

  29. Comment by João Cunha on March 17, 2008 11:53 am

    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 ?

  30. Comment by Rich Lowenberg on March 22, 2008 6:45 pm

    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!

  31. Comment by Rich Lowenberg on March 22, 2008 9:05 pm

    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!

  32. Comment by Nikos on March 26, 2008 7:34 pm

    I am not getting the over image to display upon mouse over

  33. Comment by Michiel van der Ros on March 28, 2008 4:09 pm

    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!

  34. Comment by rondog on March 31, 2008 10:04 pm

    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.

  35. Comment by halaszlo on April 5, 2008 10:21 pm

    Hi,
    How could I have different image on the back side of the plane?

  36. Comment by rony on April 6, 2008 2:18 pm

    like rondog.
    is it a bug in papervision?

  37. Comment by Thomas Langhagel on April 6, 2008 9:00 pm

    Thanks a lot to Michiel van der Ros,

    the hint with the "material.copy" was really a great help!

  38. Comment by Gano on April 7, 2008 4:56 pm

    Same problem as rondog:

    onOver works with "plane.material.copy", but onOut doesn't..

  39. Comment by Barbara on April 16, 2008 1:48 pm

    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!

  40. Comment by Peter on May 1, 2008 6:36 am

    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!

  41. Comment by seb on May 3, 2008 10:27 pm

    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!

  42. Comment by Felix on May 19, 2008 6:53 pm

    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?

  43. Comment by Jackson on June 10, 2008 2:29 pm

    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.

  44. Comment by marcus on June 15, 2008 9:32 pm

    you have to set the interactivity property of the viewport:
    ...
    viewport = new Viewport3D(vpWidth, vpHeight);
    viewport.interactive = true;
    ...

  45. Comment by Neil Glenister on June 17, 2008 8:01 pm

    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

  46. Comment by Todd on July 3, 2008 1:00 am

    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

  47. Comment by suBi on July 12, 2008 4:31 am

    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).

  48. Comment by jared on July 22, 2008 8:45 pm

    @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!

Comments RSS TrackBack Identifier URI

Leave a comment


Papervision 2 is proudly powered by WordPress and themed by Mukka-mu