Thomas Joos | mobile application developer

(re)create your thoughts and expand your limits.

3D: Papervision: Plane Events

with 34 comments

We all have heard of pv3D: Papervision 3D. I have been playing with this stunning api for a while and I have noticed some problems when you want to go just a bit further than a quick demo. When you are making a project using pvd3D you obviously would like to use your plane object and make it clickable for example. Those who have been playing with papervision know that it is not possible to add an event listener directly to your plane.

There is a great tutorial on rockonflash which guides you through this proces using an interactiveSceneManager. Basically this manager handles an OBJECT_CLICK event and makes it possible to see which object (for example a plane ) has been clicked on. But there are some things that bother me. You can’t add a buttonMode to your plane so users do not see their mouse change to notify them that an object is clickable. It also is not possible to add some animation onto you pv3D object when using a MOUSE_OVER event for example.

But here you can download a fla that shows you a way to implement plane events in your project and handles these problems like buttonMode and for example an alpha change on a mouse over. Let’s get a quick view at the code:

First of all we configure our scene, import our pv3D classes etc.. we are going to make 50 icons so a nice icon is used for a bitmapassetmaterial. (yeah that’s right, it’s mike chambers! )

import org.papervision3d.scenes.*;
import org.papervision3d.cameras.*;
import org.papervision3d.objects.*;
import org.papervision3d.materials.*;
import caurina.transitions.Tweener;
//container
var container:Sprite=new Sprite();
container.x=stage.stageWidth*0.5;
container.y=stage.stageHeight*0.5;
addChild(container);
//een 3D scene maken
var scene:Scene3D=new MovieScene3D(container);
//camera aanmaken
var camera:Camera3D=new Camera3D();
//initial zoomin eigenlijk, default better view, achteraf makkelijk adjusten
//camera.zoom=5;
camera.zoom=4;
//bitmap asset material BAM
var bam:BitmapAssetMaterial = new BitmapAssetMaterial("Mike");
//show both sides, default one side
bam.oneSide=false;
//smooth true=> smoothing
bam.smooth=true;

So far so good, nothing special really. But here comes the new part, we are going to use a dictionary, this is something like an array but instead of using integers to reference as an index to our stored plane objects; we are going to use sprites. Because we are using a MovieScene3D, every 3D object we create, has an sprite property, you could say it is the object’s bounding box.

we make an instance of a dictionary and we use the sprite propertie of the plane to store our plane into the dictionary
//dictionary
var myPlaneDictionary:Dictionary=new Dictionary();
var p:Plane=new Plane(bam,128,128,2,2);
//HERE IT COMES!
var myPlaneContainer:Sprite = p.container;//we use the container sprite propertie of the plane
myPlaneDictionary[myPlaneContainer]=p;//here we have container as key and plane as value

Now we have stored our plane into a dictionary by using it’s sprite container, but now comes the cool part, we are going to use this container to add event listeners, and then we can use our dictionary to know which plane we need. We can configure this container’s buttonMode to true, so the users see their mouse change and know they can click on the object. We also use this container’s alpha property to have a plane alpha change when we have a mouseover.

myPlaneContainer.buttonMode = true;//we configure a button mode
//events koppelen aan plane container
myPlaneContainer.addEventListener( MouseEvent.ROLL_OVER, doRollOver );
myPlaneContainer.addEventListener( MouseEvent.CLICK, clicker );
myPlaneContainer.addEventListener( MouseEvent.ROLL_OUT, doRollOut );
//event functies
function doRollOver(evt:MouseEvent) {
var sprit:Sprite=evt.target as Sprite;
sprit.alpha = 0.5;
//we use the container sprite to do an alpha change

To check our performance we write a for loop that creates 50 of these objects with a listener, and it seems to run quite smoothly so lack of performance should not be an issue when trying to implement Plane Events ( or other pv3D objects ) like this.

Check it out and let me know what you think!

Advertisements

Written by vilebody

November 29, 2007 at 12:59 pm

Posted in 3D

34 Responses

Subscribe to comments with RSS.

  1. Hi Thomas,

    Looks pretty good. I’ll look into it later on, myself. Will tell you how this worked out. Was trying to figure out how to do this for a while now.

    EaZ

    November 29, 2007 at 7:30 pm

  2. Link (.fla) doesn’t work…

    Frederik

    December 4, 2007 at 8:29 pm

  3. thx frederik for letting me know, I just updated the link it should work. Enjoy exploring pvd3D! grtz

    vilebody

    December 4, 2007 at 9:41 pm

  4. Thanks for the file and this tutorial… Do you know any solutions to handle events from Movieclips/Sprites in the Plane itself? Cheers

    Frederik

    December 5, 2007 at 1:02 pm

  5. when you want to use a movieclip as a plane, you need to make a MovieMaterial instance. This object needs a movieclip or sprite to be created

    for instance:
    var myMovieMaterial:MovieMaterial = new MovieMaterial(mySprite);
    var myPlane:Plane=new Plane(myMovieMaterial,50,50,2,2)

    so to answer your question :) you can create a movieclip, add it to a moviematerial, use it to create a plane. adding EventListeners onto this movieclip will be ignored by the plane so we need to attach a listener to the plane itself. At the moment this is not possible so you need to use the interactive scene manager, or the trick with the dictionary (which is better when you want to make your project more user friendly )

    hope this was a bit helpfull :)

    grtz

    vilebody

    December 5, 2007 at 7:35 pm

  6. Yeah, it was quite helpfull, but the thing is… I have several movieclips in a plane… (all buttons) and I managed to give them events, but I don’t see my hand cursor anymore (and yes, buttonmode is on and the property mouseChildren is set to false).. Is it possible to fix this? This is the website by the way: my portfolio. Thanks for the help so far!

    Frederik

    December 6, 2007 at 2:42 pm

  7. I’m not familiar with this kind of problem. I have never tried to collect multiple movieclips in a container and use the container (moviematerial) on a plane. My guess is to make sure you set the buttonMode of the container to true, but also the buttonMode of all its submovieclips(buttons). I’m not sure this is going to make a difference but maybe it has slipped your mind. Configurating the mouseChildren property to false also seems the right thing to do.

    I’ll have a look at it in the weekend but let me know if you find a way to get it working. I took a look at your portfolio and noticed you studied Graphical and Digital Media. I’m a student Multimedia at Kortrijk :) Did you liked GDM and what are the courses you took in your last year of multimedia production?

    grtz ( of ne goeie belgischen salu! ^^ )

    vilebody

    December 6, 2007 at 11:10 pm

  8. Hey, yeah I got it working, check it out… still a few bugs though, but you get the picture. GDM was not that great… Bassicly I learned it all by myself. They give the basics from languages like Actionscript, Lingo, C# and Javascript (we didn’t see PHP, that was quite disappointing) . But now I’m studing Interactive Media in London to get an MA degree. And that’s a lot better. It’s not about the coding, but all about creating idea’s and stuff. I really like it. Do you know by any coincidence Jonas De Smet? He’s taking a master degree in your school. I had the change to work with him this summer. He learned me much about PHP and Smarty template engine.. really interesting guy :)
    grtzz ( en nen belgische salu terug :) )

    Frederik

    December 7, 2007 at 7:56 pm

  9. nope his name doesn’t ring a bell. Would you be so kind to email me some source code of your multiple movieclip in plane event handling ( what a title! :p ) I’d love to check it out :)

    Keep an eye on my blog because with the new pv3D 2.0 release some cool posts are attending :)

    grtz and good luck in London!

    vilebody

    December 8, 2007 at 12:43 pm

  10. Yeah, no problem, when I get all the bugs out, I will send you the code related to Papervision. I added your blog in my blogroll so that I’ll stay posted, I will certaintly keep an eye on your blog!

    Frederik

    December 9, 2007 at 11:05 pm

  11. Hi,
    Great tutorial – thanks! Just wondering if you could give me a hand in adding an event listener to a movieclip inside of the MovieMaterial clip. I can add mouse events to the main clip but not any clips inside of it. I’m guessing I add it somewhere here:

    var myPlaneContainer:Sprite = p.container;
    myPlaneDictionary[myPlaneContainer]=p;
    myPlaneContainer.buttonMode = true;

    Say for instance I want to talk to a clip called “btn” inside of the p.container clip, how could I go about doing that? Any help would be appreciated – thanks!!

    Jassa

    jassa

    January 9, 2008 at 1:04 pm

  12. Hi jassa, a while ago Frederik had a similar issue. I never tried to implement this kind of structured movieclip into pv3D but I’ll have a look at it and reply as soon as possible.

    My first guess though is that you trie to see if you can get a hand on the ”btn” movieclip. In my exaple above just trace myPlaneContainer.btn and see if this returns an object. If it does you could try to add the event listener onto this object like this..

    myPlaneContainer.btn.addEventListener(…)

    I’m not sure this is 100% working but it is worth trying :) I’ll check it out in a few days but as a result of my studies it is quite hard to find some extra time these days.

    good luck and talk to you soon :)

    vilebody

    January 9, 2008 at 1:35 pm

  13. Thanks vilebody, I appreciate your quick response. I’ll give that a try and let you know how I go. Cheers!

    Jassa

    jassa

    January 9, 2008 at 9:54 pm

  14. Hi again,

    Just an update on the btn issue. I can’t trace myPlaneContainer.btn but I can trace it when I’m creating MovieMaterial that I’m adding to the Plane. But when I add eventListeners to it there they don’t respond when I run the movie. I’ll keep trying ;)

    Jassa

    jassa

    January 9, 2008 at 10:37 pm

  15. Hi there,

    I have the same issue, I want some buttons to react inside the MovieMaterial plane. I don´t get it so far, so if there are any news about this, please post it here. Frederiks Portfolio site works … the buttons inside of it too. How did he make it?

    Manuel

    January 11, 2008 at 7:58 pm

  16. Hey guys,

    I have a super easy solution to getting the button mode to work only when you rollover the button and not the whole plane.

    just make button mode = to true inside your rollover fufunction.

    movieSkinContainer.addEventListener(MouseEvent.ROLL_OVER,handleRollOver);
    movieSkinContainer.addEventListener(MouseEvent.ROLL_OUT, handleRollOut);
    movieSkinContainer.addEventListener(MouseEvent.CLICK, handleClick);

    function handleRollOver(e:MouseEvent):void
    {
    container.buttonMode=true;
    trace(”rollover”);
    }
    function handleRollOut(e:MouseEvent):void
    {
    container.buttonMode=false;
    trace(”rollout”);
    }
    function handleClick(e:MouseEvent):void
    {
    trace(”rollClick”);
    }

    Hope that helps.

    Rex Raptor

    January 22, 2008 at 10:10 pm

  17. Rex Raptor you’re a freaking genius! That’s so simple yet it works so well.

    Matt Rix

    February 3, 2008 at 8:10 pm

  18. thanks for this great tutorial. but how could I target the camera to the plane I clicked? this is quite heavy to do…

    hossli

    March 11, 2008 at 1:05 pm

  19. Alright, this has been very useful to me. Thanks! :)

    Min Thu

    April 30, 2008 at 9:24 am

  20. I never really understood how to the dictionary class until I read this tutorial.

    Thanks for sharing mate

    dub

    May 8, 2008 at 8:04 am

  21. Hi there,

    Thanks for some really helpfull code, I am using this code as the basis for a group of cubes in rows and columns and using the following to move things around;

    this.addEventListener(Event.ENTER_FRAME,render);
    function render(e:Event):void {
    Tweener.addTween(camera,{x:-container.mouseX,time:2,transition:”easeoutquint”});
    Tweener.addTween(camera,{y:-container.mouseY,time:2,transition:”easeoutquint”});
    scene.renderCamera(camera);
    }

    All the cubes show in a grid but the z-layering or ordering doesnt work – it works in reverse – when the mouse moves to the right, the right hand column of cubes in the grid move closer to the camera and should be ‘at the forefront’. These cubes however appear to move behind the ones further away from the camera view.

    I hope this makes sense, am I using the wrong material type on container or scene.

    Any help greatly appreciated

    craig

    May 14, 2008 at 1:07 am

  22. Thanks for the tutorial.

    I’m trying to nest a series of planes like this inside a sphere and the references aren’t working for interactivity. Basically I create the sphere and addChild the planes to it. This works fine but I can’t get the interactions to work. I’ve tried getChildByName without success. The plane containers seem to be broken when not run in the root of MovieScene3D. Does this make sense? Anyone had similar issues?

    james

    June 9, 2008 at 1:50 pm

  23. Why not do it the easy way?

    var p:Plane = new Plane(..,..);
    p.container.buttonMode = true;
    p.addEventListener(MouseEvent.CLICK, yourClickHandler);

    Mr. K©

    June 26, 2008 at 5:30 pm

  24. Offcourse that last sentence had to be:
    p.container.addEventListener(..

    Mr. K©

    June 26, 2008 at 5:32 pm

  25. Great job!
    Works fine for me.

    Juan Zuluaga

    July 8, 2008 at 7:06 pm

  26. Hi, i have a question i have a movie clip that contains others, but i want to create a listener for everyone of them and i don’t know how to reference them, i also tried to create a plane and add the containers by code but it doesn’t work

    I have this code

    var simbolo:Simbolo = new Simbolo ()
    var rojo:subBoton = new subBoton ()
    var bam:MovieMaterial = new MovieMaterial(simbolo);
    bam.oneSide = false;
    bam.smooth = true;
    var p:Plane = new Plane(bam, 162, 230, 2, 2);
    p.x = 0
    p.z = 0

    var objeto = scene.addChild(p);
    p.container.addChild (rojo)
    objeto.x = p.x
    objeto.y = p.y
    objeto.z = p.z
    objeto.container.addEventListener(MouseEvent.CLICK, action);

    I tried the p.container.addChild (rojo) because i don’t know how to add clips to the plane and it seems to work in a weird way because i can click objeto and also the container, when i should only click objeto
    Simbolo and Rojo are movieclips

    Esteban A.M

    August 6, 2008 at 9:30 pm

  27. THANK YOU THANK YOU THANK YOU
    I was struggling for hours trying to do essentially what you did here. Still not sure what I did differently. Swear. but I got your example working and adapted what you did to my attack which basically required very little changes & it works. Thanks again for the help with PPV3D!

    Harold Faultermeyer

    August 28, 2008 at 2:49 am

  28. Cool tut… I hope you are still playing with PV3D! Great White offers better support for mouse events (with InteractiveScene3DEvents). When combined with Greensock’s TweenLite or TweenMax classes developing a serious 3D application in Flash becomes less of a hassle in PV3D. EventListeners can be added to DisplayObject3D’s (or classes that extend them) by setting their material to ‘interactive’. I am currently making an image viewer based on XML, in which:

    + My application promts the PV3D classes to spawn images.
    + My PV3D classes use callback functions to hand over custom events to the application.

    There you have it: interactivity, as if those cubes where on the display list themselves. It takes a bit of work to get your head around the concept, but in fact it’s faily easy with Great White!

    Fraanske

    September 6, 2008 at 8:18 pm

  29. Interesting article, i have bookmarked your blog for future referrence :)

    How to unlock a phone

    March 15, 2009 at 9:59 pm

  30. I love the idea in the article, however this approach doesnt seem to work with PV3D version 2. I have been trying (unsuccessfully) to get this type of functionality working for the new version however we now have the concept of useOwnContainer and can no longer get hold of the primitive.container object. Theres also a bug in the new version such that if we specify to useowncontainer (to apply effects etc) then the InteractiveScene3DEvent stops working.

    michael keating

    March 22, 2009 at 12:59 pm

  31. OK, so there is a solution to this, you need to reference the MovieClipAsset movie clip from inside the material. so materialname.movie.objectToInteractWith and then apply standard events. Although you will have to play with the viewport bottonMode to change the mouse to showHandCursor. VERY simple example at http://www.squibl.com/pp/form.html

    michael keating

    April 4, 2009 at 11:29 pm

  32. Looks like doesn’t work for cubes, the cube’s container property is always null…

    Marcelo

    May 12, 2009 at 2:54 pm

  33. Hi All,

    I managed to put the listener in the movie material, however I need to do more than that. The material which is a movie clip, has several other movie clip in it, which I need to move around, when people mouseover or click on the parent material. I cant seem to get it work. I know someone already asked this, is there yet any solution to this?

    Thx.

    Sami

    May 22, 2009 at 9:50 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: