Embedding FPP panoramas in another Flash container (Embed Pano 101)

OK!

So, you want to make a Flash container with all your own graphics and buttons and load your Flash Panorama Player presentation into it? Here you go... a quick "embed pano 101". Smile

What you'll end up with is a "skinned" player which displays your FPP panorama with an irregular outline (not a rectangle!) -- including buttons to load panoramas, buttons to pan/tilt/zoom, and a button to "go fullscreen".

Topping it all off you'll be able to go fullscreen and leave some of your buttons & graphics behind, then leave fullscreen and get your buttons back. This allows you to display what you want when you want it. The FPP XML in this example will show some thumbnails in fullscreen, which display larger photos.

As a bonus in this example, we will load lower resolution panoramas into the player when not in fullscreen; then, when going fullscreen, we will load higher resolution panoramas. Once loaded, these higher resolution panoramas will stay in the cache and be seen in fullscreen and not fullscreen. So, there's a lot packed into this 'little' example!

I'll go through the basics of setting up the project and go through the Actionscript code line-by-line. At the end of this post you'll find all the Actionscript in one block for easy copying. Note that I used the "embedPano.fla" which comes with Flash Panorama Player as a starting point, so you can also find that in your FPP download and use it as reference. The code for going fullscreen and back was informed by Denis of FPP fame and others in the forums, and the "go fullscreen" button is from the FPP download.

This tutorial assumes you're using Flash CS3 or newer, Actionscript 3, and have a basic knowledge of creating and placing MovieClips, buttons, graphics, etc. onto the pasteboard in a Flash CS3 doc. Advanced users can pull MovieClips and other items directly from the Library and so on.

Here's a link to a working example, and here's an image of the final presentation:

the final layout

The first thing to do is lay out your presentation in Flash. This presentation uses:

  • An irregularly shaped graphic which will mask the panoramas (MovieClip "theMask")
  • A MovieClip "left_sidebar" which contains buttons that load panoramas "on click" ('view1', 'view2', 'view3', etc)
  • Buttons to control panning, tilting and zooming ('left', 'right', 'up', 'down', etc)
  • A fullscreen button "full_btn"
  • Other graphical items as you see fit to include
  • A working set of FPP XML, panoramas, and whatever plugins/hotspots you include in the XML

You can use the Property Inspector in Flash to assign a name to each of your Buttons and/or MovieClips.

Here's an image of my Flash project humming along on my Mac; Windows users should see a similar setup:

the Flash layout

So, now we've got all our MovieClips, graphics and other layout elements on the pasteboard/stage in our Flash project. Let's get to coding!

stop();

Always a good idea to stop the timeline from moving along. It's a habit, and maybe unnecessary. Wink

import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.*;
import flash.net.URLRequest;
import fl.transitions.Tween;
import fl.transitions.*;
import fl.transitions.easing.*;

The above import statements set up Flash so it can deal with things like loading external data, Sprites & Sprite events, and tweening elements. We won't use tweening in this example, but I'm planning ahead... Smile

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

Let's get our stage to play nice when going to and leaving fullscreen mode.

var panorama:MovieClip;
var loader:Loader = new Loader();
loader.load(new URLRequest("base/pano.swf"));
addChild(loader);

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);

var thePanoToLoad = "panos/small/pano_1/_bracketed_1";
var theCurrentPano = "1";

OK, now we're getting to fun stuff. We set up a MovieClip var called panorama: This is where we'll ultimately put the loaded FPP "pano.swf", and what we'll target when we want to make the panorama 'do things'.

loader is the actual Loader Object which handles getting "pano.swf", and we add it to the Stage (Display List) once we get it started loading.

We also give loader an EventListener called loadComplete. So, loader can check the load progress of "pano.swf" and call the loadComplete function when "pano.swf" is done loading.

Lastly we set up two variables to hold information about our various panoramas. thePanoToLoad is our FPP "panoName" equivalent. We'll use theCurrentPano to track which panorama is currently being viewed; this is so we can load the proper high-resolution panorama when in fullscreen.

full_btn.visible = false;
left_sidebar.view1.alpha = left_sidebar.view2.alpha = left_sidebar.view3.alpha = left_sidebar.view4.alpha = left_sidebar.view5.alpha = left_sidebar.view6.alpha = 0.5;
//
var theBL:int = 0;
var theBT:int = 0;
var thePL:int = 0;
//
function loadComplete(e:Event) {
        swapChildren(loader, full_btn);
        panorama = loader.content as MovieClip;
        panorama.mask = theMask;
        panorama.setArea(150,20,570,380);

        panorama.loadPanorama("panoName="+thePanoToLoad+"&xml_file=base/_setup.xml");

        left.addEventListener(MouseEvent.MOUSE_DOWN, doLeft);
        right.addEventListener(MouseEvent.MOUSE_DOWN, doRight);
        up.addEventListener(MouseEvent.MOUSE_DOWN, doUp);
        down.addEventListener(MouseEvent.MOUSE_DOWN, doDown);
        zoomin.addEventListener(MouseEvent.MOUSE_DOWN, doZoomin);
        zoomout.addEventListener(MouseEvent.MOUSE_DOWN, doZoomout);

        stage.addEventListener(MouseEvent.MOUSE_UP, reset);

        if (stage.hasOwnProperty("displayState")) {// check fullscreen feature is accessible or not
                stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullscreenHandler);
                full_btn.addEventListener(MouseEvent.CLICK, doFullscreen);
        } else {
                full_btn.visible=false;
        }

        addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
}

There's a lot going on above, and in our loadComplete function.

Firstly, we set the alpha of our various buttons to 50 percent, and hide our full screen button. This is to indicate to the user that they can't use the buttons (ie, a panorama hasn't fully loaded). We'll "watch" for a panorama to be loaded fully later on in the code. To that end, we set up theBL, theBT, and thePL to hold values for (respectively) our panorama's bytes loaded, bytes total, and percent loaded.

swapChildren basically tells Flash that we want loader (that is, "pano.swf") to be visually above our Button full_btn. If you had a different graphic element which you wanted to layer behind your pano, this is where you would say so. So, rather than full_btn, you could say something like swapChildren(loader, myCoolBackgroundGraphic);.

The next three lines get our panorama MovieClip ready for its job as a container for our panoramas:

  • We tell panorama to accept what loader has just loaded ("pano.swf")
  • We give panorama our irregularly shaped graphic theMask as a Mask
  • We tell panorama to have a position of 150 pixels from the left, 20 pixels from the top, and be 570 pixels wide by 380 pixels tall

Now that panorama is set up, we can target it as a MovieClip. Targeting panorama is basically targeting "pano.swf". Our first task, using FPP's special loadPanorama function, is to... load our first panorama! Smile ...thePanoToLoad already holds the "panoName" of our first panorama. We plug this in to the loadPanorama function, and add our FPP XML file to the end of the function.

Next we set up "Mouse Down" Event Listeners for each of our pan, tilt and zoom buttons. So, for example, in left.addEventListener(MouseEvent.MOUSE_DOWN, doLeft); we are saying WhichButton.addEventListener(WhatTypeOfEvent, WhatFunctiontoCall);. We also set up a "Mouse Up" Event Listener on the stage; this gets us around setting up a special "Mouse Up" Event Listener on each of our buttons.

And now, our "go fullscreen" Event Listener.
First we check to see if we even have the ability to go fullscreen. If we can't "go fullscreen", then why bother showing the button for going fullscreen? So, we check first if we can change the "Display State"; If so, then add the Event Listener fullscreenHandler to the stage, and the "Mouse Click" Event Listener doFullscreen to our Button full_btn. If not, then we set full_btn's visibility to false (hidden).

Remember, if you set an item's visible to false, it disables any Mouse Events on that item; If you simply set an item's alpha to 0 (zero), it will be hidden from view -- but you can still use your mouse to interact with it.

Lastly, we add an Event Listener to the Stage, which happens once per each frame at whatever the frame rate is for your Flash project. Even though we aren't 'physically' moving down a timeline with multiple frames, this panoLoadWatcher function will fire off once per frame until we tell it to stop. We'll go over the panoLoadWatcher function at the very end, but it will basically tell us how much of the panorama has loaded, and when done loading it will set visibility and alpha of our buttons back to full visibility and alpha.

Make sense? Below, I'll go over the actual functions for each of these Mouse Events.

left_sidebar.view1.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view2.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view3.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view4.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view5.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view6.addEventListener(MouseEvent.CLICK,loadPanoFunction);

function loadPanoFunction(event:Event) {
        var obj:Object = event.target;
        var whichButton = obj.name;

        switch (whichButton) {
                case "view1" :
                        thePanoToLoad = "panos/small/pano_1/_bracketed_1";
                        theCurrentPano = "1";
                        break;
                case "view2" :
                        thePanoToLoad = "panos/small/pano_2/_bracketed_1a";
                        theCurrentPano = "2";
                        break;
                case "view3" :
                        thePanoToLoad = "panos/small/pano_3/bracketed_1-flat";
                        theCurrentPano = "3";
                        break;
                case "view4" :
                        thePanoToLoad = "panos/small/pano_4/_bracketed_1";
                        theCurrentPano = "4";
                        break;
                case "view5" :
                        thePanoToLoad = "panos/small/pano_5/_bracketed_1a";
                        theCurrentPano = "5";
                        break;
                case "view6" :
                        thePanoToLoad = "panos/small/pano_6/_bracketed_1";
                        theCurrentPano = "6";
                        break;
                default :
                        thePanoToLoad = "panos/small/pano_1/_bracketed_1";
                        theCurrentPano = "1";
                        break;
        }
        if (thePL == -1) {
                if (panorama.externals.hotspots!=null) {
                        if (panorama.externals.hotspots.panoName == thePanoToLoad) {

                        } else {
                                panorama.externals.hotspots.loadPano(["pano.swf?panoName="+thePanoToLoad]);
                                addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                        }
                } else {
                        panorama.pano.remove();
                        panorama.loadPanorama("pano.swf?panoName="+thePanoToLoad);
                        addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                }
        }
}

The above block of code does a lot! First, we set up "Mouse Click" Event Listener on each of our buttons inside left_sidebar. Now when our "view1", "view2", "view3", etc, button is clicked it will call on the loadPanoFunction which will (drum roll please) load a new panorama! This loadPanoFunction will need to get the new "panoName" and then tell FPP to load it. loadPanoFunction will also begin tracking which panorama we are currently viewing so that we can switch to a higher resolution of it when we go fullscreen.

loadPanoFunction takes the Mouse Event, finds the target of the Event (that is, which button was clicked), gets the button's name (as set in the Property Inspector) and assigns the name to the whichButton variable.

Using whichButton, we check it against our list inside our switch code block. When we have a match (ie, "view3"), then we assign the new "panoName" to thePanoToLoad, and give our arbitrary number assignment of this particular panorama to theCurrentPano. We'll need this information in just a second...

Next up is where we actually tell FPP to load a new panorama.What this code block is saying then is: if we aren't currently loading a panorama (ie, if thePL isn't somewhere between 0 and 100 percent), then check to see if FPP's hotspots plugin is available*. If the hotspots plugin is available, then use it to load a new panorama; else, remove the current pano object using FPP's internal remove() function (so we don't end up with two panos in there) and load a new panorama into a fresh "pano.swf". In either case, we start the Event Listener function panoLoadWatcher, which monitors the load progress of our panorama.

panorama.pano.remove is important to look at. See the additional piece of targeting in there? pano is FPP's internal Object for the current panorama which we can access, and  remove is FPP's hook to its "remove" function. If we just targeted panorama.remove we'd get an error (or nothing). So, we target the "actual" pano and hook onto its remove function.

* Somewhere in an email or a forum post far far away, Denis of FPP fame let us know that it is more efficient to use the hotspots plugin to handle loading, than it is to forcibly remove and reintroduce panoramas.

function doLeft(e:Event) {
        panorama.pano.panKey = -1;
}
function doRight(e:Event) {
        panorama.pano.panKey = 1;
}
function doUp(e:Event) {
        panorama.pano.tiltKey = 1;
}
function doDown(e:Event) {
        panorama.pano.tiltKey = -1;
}
function doZoomin(e:Event) {
        panorama.pano.zoomKey = 1;
}
function doZoomout(e:Event) {
        panorama.pano.zoomKey = -1;
}
function reset(e:Event) {
        panorama.pano.panKey = 0;
        panorama.pano.tiltKey = 0;
        panorama.pano.zoomKey = 0;
}

We're more than halfway done here, really. Wink

The above block of code should bring back some memories... We've already added Event Listeners to each of our pan, tilt and zoom buttons. These are the functions they call on. Again make note of how we're targeting pano, and using the standard FPP syntax to tell the panorama to move left, right, up, down, in or out a la the functions doLeft, doRight, doUp, etc, and the FPP hooks of panKey, tiltKey, zoomKey.

The reset function is what the stage calls on when the user lifts the mouse ("Mouse Up"), and simply tells FPP to stop panning, tilting or zooming.

function doFullscreen(e:Event) {
        if (stage.hasOwnProperty("displayState")) {
                if (stage.displayState == StageDisplayState.FULL_SCREEN) {
                        stage.displayState = StageDisplayState.NORMAL;
                } else {
                        stage.displayState = StageDisplayState.FULL_SCREEN;
                        switch (theCurrentPano) {
                                case "1" :
                                        thePanoToLoad = "panos/large/pano_1/pano_1";
                                        break;
                                case "2" :
                                        thePanoToLoad = "panos/large/pano_2/pano_2";
                                        break;
                                case "3" :
                                        thePanoToLoad = "panos/large/pano_3/pano_3";
                                        break;
                                case "4" :
                                        thePanoToLoad = "panos/large/pano_4/pano_4";
                                        break;
                                case "5" :
                                        thePanoToLoad = "panos/large/pano_5/pano_5";
                                        break;
                                case "6" :
                                        thePanoToLoad = "panos/large/pano_6/pano_6";
                                        break;
                                default :
                                        thePanoToLoad = "panos/large/pano_1/pano_1";
                                        break;
                        }
                        if (thePL == -1) {
                                if (panorama.externals.hotspots!=null) {
                                        if (panorama.externals.hotspots.panoName == thePanoToLoad) {

                                        } else {
                                                panorama.externals.hotspots.loadPano(["pano.swf?panoName="+thePanoToLoad]);
                                                addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                                        }
                                } else {
                                        panorama.pano.remove();
                                        panorama.loadPanorama("pano.swf?panoName="+thePanoToLoad);
                                        addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                                }
                        }
                }
        }
}

The above code is a meaty function. This is the function which our full_btn calls on. Finally, we can go fullscreen!

The first thing we do is double-check that we can go fullscreen (via "displayState"). If so, and we already are in Full Screen mode, then take us out of Full Screen Mode. Else, if we're not in Full Screen Mode then "go fullscreen".

This is also where we load a higher resolution panorama to show in glorious full screen. Smile Remember theCurrentPano? We gave it a number which corresponds to the current low-resolution panorama. We check this number, and then set thePanoToLoad with our hi-res panoName.

After getting the panoName of our hi-res image, we make sure we aren't already in the middle of loading a panorama (thePL). We again check that the hotspots plugin is present, and reach an important juncture.

Our tour initially loads using a low resolution panorama. When we first go fullscreen, we load the high resolution version of the current panorama. Since this new hi-res panorama is now loaded into memory, it makes no sense to continue switching between lo- and hi-res versions of it. Sooo...

We take this new "panoName" (thePanoToLoad) and check it against the current panoName which FPP has. If they match, then we tell FPP to not reload the panorama (that is by doing nothing). Else, if thePanoToLoad and FPP's "panoName" (panorama.externals.hotspots.panoName) don't match, then go ahead and load the hi-res panorama.

Got it? Smile

The second to last little block of code is below. Almost done!

function fullscreenHandler(e:FullScreenEvent) {
        if (e.fullScreen) {
                theMask.visible = left_sidebar.visible = bottom_bar.visible = left.visible = right.visible = up.visible = down.visible = zoomin.visible = zoomout.visible = false;
                panorama.setArea(0,0,stage.stageWidth,stage.stageHeight);
                panorama.mask = null;
                full_btn.x = stage.stageWidth-22;
                full_btn.y = 22;
        } else {
                left_sidebar.visible = bottom_bar.visible = left.visible = right.visible = up.visible = down.visible = zoomin.visible = zoomout.visible = true;
                panorama.setArea(150,20,570,380);
                panorama.mask = theMask;
                full_btn.x = 672;
                full_btn.y = 406;
        }
}

Up near the top we added an Event Listener to the stage: stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullscreenHandler);. Every time the user clicks the fullscreen button (or uses the esc key when in Full Screen Mode) and changes us from one Full Screen Mode to another, the stage runs this function.

In my presentation, I wanted to not show the pan, tilt, zoom, and view buttons in Full Screen (notice that when you go fullscreen in my presentation, you see some FPP image hotspots). This fullscreenHandler does the work of showing/hiding the various buttons -- and most importantly it removes and reintroduces theMask. Obviously, "going fullscreen" but keeping the little irregularly shaped "skin" would be counterintuitive. Wink

Note also that we call on setArea. Since we're using an "embedPano" style setup, we need to let Flash know that it's OK to resize the panorama to fill the screen. Once we leave Full Screen Mode, though, we need to tell Flash to put things back the way they were.

And, the last function, but not the least important one:

function panoLoadWatcher(e:Event=null) {
        if (panorama.externals.hotspots!=null) {

                if (full_btn.visible == true) {
                        full_btn.visible = false;
                }
                if (left_sidebar.view1.alpha > 0.5) {
                        left_sidebar.view1.alpha = left_sidebar.view2.alpha = left_sidebar.view3.alpha = left_sidebar.view4.alpha = left_sidebar.view5.alpha = left_sidebar.view6.alpha = 0.5;
                }
                //
                theBL = panorama.pano.bytesLoaded;
                theBT = panorama.pano.bytesTotal;
                thePL = panorama.pano.percentLoaded;
                trace("PANO bytesLoaded?: "+theBL);
                trace("PANO bytesTotal?: "+theBT);
                trace("PANO percentLoaded?: "+thePL);

                if (thePL >= 100) {
                        theBL = -1;
                        theBT = -1;
                        thePL = -1;
                        full_btn.visible = true;
                        left_sidebar.view1.alpha = left_sidebar.view2.alpha = left_sidebar.view3.alpha = left_sidebar.view4.alpha = left_sidebar.view5.alpha = left_sidebar.view6.alpha = 1.0;
                        removeEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                }
        }
}

FPP can get a little confused sometimes. Smile That is, it's possible to try to load a new panorama while we're still loading the first one. This can (when using an Embed Pano setup) lead to weird issues such as having two panoramas overlaying each other in the viewer window.

What panoLoadWatcher does is:

  • Check the visibility of the "go fullscreen" button; if it's visible, hide it. Thisis so someone can't take the presentation fullscreen while a lo-res pano is loading (thus trying to load a hi-res panorama).
  • Set the alpha of the "view" buttons to 50 percent, visually implying that they're not usable.
  • Monitor the percent/bytes loaded of the panorama.
  • When the panorama is done loading, change back the alpha of the "view" buttons, make the "go fullscreen" button visible, and reset the percent/bytes loaded variables to "-1" so that other functions know it's OK or not OK to load a new panorama.
  • Remove the Event Listener, so we aren't hogging resources.

Whew! I think that does it. I hope this helps! Smile

Please post errors, comments, questions below. I look forward to reading them!

Cheers,

Patrick

--------

The entire code sans commentary:

stop();
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.*;
import flash.net.URLRequest;
import fl.transitions.Tween;
import fl.transitions.*;
import fl.transitions.easing.*;

var panorama:MovieClip;
var loader:Loader = new Loader();
loader.load(new URLRequest("base/pano.swf"));
addChild(loader);

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
//
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//
var thePanoToLoad = "panos/small/pano_1/_bracketed_1";
var theCurrentPano = "1";
//
full_btn.visible = false;
left_sidebar.view1.alpha = left_sidebar.view2.alpha = left_sidebar.view3.alpha = left_sidebar.view4.alpha = left_sidebar.view5.alpha = left_sidebar.view6.alpha = 0.5;
//
var theBL:int = 0;
var theBT:int = 0;
var thePL:int = 0;
//
function loadComplete(e:Event) {
        swapChildren(loader, full_btn);
        panorama = loader.content as MovieClip;
        panorama.mask = theMask;
        panorama.setArea(150,20,570,380);

        panorama.loadPanorama("panoName="+thePanoToLoad+"&xml_file=base/_setup.xml");

        left.addEventListener(MouseEvent.MOUSE_DOWN, doLeft);
        right.addEventListener(MouseEvent.MOUSE_DOWN, doRight);
        up.addEventListener(MouseEvent.MOUSE_DOWN, doUp);
        down.addEventListener(MouseEvent.MOUSE_DOWN, doDown);
        zoomin.addEventListener(MouseEvent.MOUSE_DOWN, doZoomin);
        zoomout.addEventListener(MouseEvent.MOUSE_DOWN, doZoomout);
        stage.addEventListener(MouseEvent.MOUSE_UP, reset);

        if (stage.hasOwnProperty("displayState")) {// check fullscreen feature is accessible or not
                stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullscreenHandler);
                full_btn.addEventListener(MouseEvent.CLICK, doFullscreen);
        } else {
                full_btn.visible=false;
        }
        addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
}
//
left_sidebar.view1.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view2.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view3.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view4.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view5.addEventListener(MouseEvent.CLICK,loadPanoFunction);
left_sidebar.view6.addEventListener(MouseEvent.CLICK,loadPanoFunction);
//
function loadPanoFunction(event:Event) {
        var obj:Object = event.target;
        var whichButton = obj.name;

        switch (whichButton) {
                case "view1" :
                        thePanoToLoad = "panos/small/pano_1/_bracketed_1";
                        theCurrentPano = "1";
                        break;
                case "view2" :
                        thePanoToLoad = "panos/small/pano_2/_bracketed_1a";
                        theCurrentPano = "2";
                        break;
                case "view3" :
                        thePanoToLoad = "panos/small/pano_3/bracketed_1-flat";
                        theCurrentPano = "3";
                        break;
                case "view4" :
                        thePanoToLoad = "panos/small/pano_4/_bracketed_1";
                        theCurrentPano = "4";
                        break;
                case "view5" :
                        thePanoToLoad = "panos/small/pano_5/_bracketed_1a";
                        theCurrentPano = "5";
                        break;
                case "view6" :
                        thePanoToLoad = "panos/small/pano_6/_bracketed_1";
                        theCurrentPano = "6";
                        break;
                default :
                        thePanoToLoad = "panos/small/pano_1/_bracketed_1";
                        theCurrentPano = "1";
                        break;
        }
        /*if (panorama.pano.loadCompleted) {
        if (panorama.externals.hotspots!=null) {
        //panorama.externals.hotspots.loadPano(["pano.swf?panoName="+thePanoToLoad]);
        } else {
        panorama.pano.remove();
        panorama.loadPanorama("pano.swf?panoName="+thePanoToLoad);
        }
        }*/

        if (thePL == -1) {
                if (panorama.externals.hotspots!=null) {
                        if (panorama.externals.hotspots.panoName == thePanoToLoad) {

                        } else {
                                panorama.externals.hotspots.loadPano(["pano.swf?panoName="+thePanoToLoad]);
                                addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                        }
                } else {
                        panorama.pano.remove();
                        panorama.loadPanorama("pano.swf?panoName="+thePanoToLoad);
                }
        }
}
//
function doLeft(e:Event) {
        panorama.pano.panKey = -1;
}
function doRight(e:Event) {
        panorama.pano.panKey = 1;
}
function doUp(e:Event) {
        panorama.pano.tiltKey = 1;
}
function doDown(e:Event) {
        panorama.pano.tiltKey = -1;
}
function doZoomin(e:Event) {
        panorama.pano.zoomKey = 1;
}
function doZoomout(e:Event) {
        panorama.pano.zoomKey = -1;
}
function reset(e:Event) {
        panorama.pano.panKey = 0;
        panorama.pano.tiltKey = 0;
        panorama.pano.zoomKey = 0;
}
//
function doFullscreen(e:Event) {
        if (stage.hasOwnProperty("displayState")) {
                if (stage.displayState == StageDisplayState.FULL_SCREEN) {
                        stage.displayState = StageDisplayState.NORMAL;
                } else {
                        stage.displayState = StageDisplayState.FULL_SCREEN;
                        switch (theCurrentPano) {
                                case "1" :
                                        thePanoToLoad = "panos/large/pano_1/pano_1";
                                        break;
                                case "2" :
                                        thePanoToLoad = "panos/large/pano_2/pano_2";
                                        break;
                                case "3" :
                                        thePanoToLoad = "panos/large/pano_3/pano_3";
                                        break;
                                case "4" :
                                        thePanoToLoad = "panos/large/pano_4/pano_4";
                                        break;
                                case "5" :
                                        thePanoToLoad = "panos/large/pano_5/pano_5";
                                        break;
                                case "6" :
                                        thePanoToLoad = "panos/large/pano_6/pano_6";
                                        break;
                                default :
                                        thePanoToLoad = "panos/large/pano_1/pano_1";
                                        break;
                        }
                        if (thePL == -1) {
                                if (panorama.externals.hotspots!=null) {
                                        if (panorama.externals.hotspots.panoName == thePanoToLoad) {

                                        } else {
                                                panorama.externals.hotspots.loadPano(["pano.swf?panoName="+thePanoToLoad]);
                                                addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                                        }
                                } else {
                                        panorama.pano.remove();
                                        panorama.loadPanorama("pano.swf?panoName="+thePanoToLoad);
                                        addEventListener(Event.ENTER_FRAME, panoLoadWatcher);
                                }
                        }
                }
        }
}
function fullscreenHandler(e:FullScreenEvent) {
        if (e.fullScreen) {
                theMask.visible = left_sidebar.visible = bottom_bar.visible = left.visible = right.visible = up.visible = down.visible = zoomin.visible = zoomout.visible = false;
                panorama.setArea(0,0,stage.stageWidth,stage.stageHeight);
                panorama.mask = null;
                full_btn.x = stage.stageWidth-22;
                full_btn.y = 22;
        } else {
                left_sidebar.visible = bottom_bar.visible = left.visible = right.visible = up.visible = down.visible = zoomin.visible = zoomout.visible = true;
                panorama.setArea(150,20,570,380);
                panorama.mask = theMask;