PanoSalado integrated in Flex application

Hi all!

First of all I want to thank the creators of this panoramic viewer! It is really great!

But I ran into some trouble, and I am hoping someone can please help me out!

I created a panoramic image that works in a browser. This works oke. But I want it to be shown from whitin a Flex application. I am relative new to Flex and AS3. I tried to include the 'ModuleLoader.swf' by means of the Flex SWFLoader component.

This works. But I can not resize it correctly. It seems to mess up the hotspot features (I see hotspot, but is not clickable). And It doesn't respect the width/height of the Titlewindow it is placed in.

I have created an example on my own website: http://www.mennocornelissen.nl/panotest/Test.html
At first the hotspot will work. But when you move the TitleWindow a little you will notice that the hotspot stops working. (Hotspot should do a fade in, nothing fancy)

Maybe someone has a Working example ? Or maybe I am looking at this from a wrong angle ?

Have you tried merging the

Have you tried merging the ModuleLoader code with the code of your main application? That might work. (and you might find it easier to rename your main application to ModuleLoader, since PanoSalado looks for ModuleLoader's class by name.

Zephyr

Hi zephyr, Thanks for the

Hi zephyr,

Thanks for the response! I tried the following code before.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">
        <mx:Script>
                <![CDATA[
        import flash.display.*;
        import flash.net.*;
        import flash.events.Event;
        import flash.utils.Dictionary;
        import flash.system.ApplicationDomain;
        import flash.system.LoaderContext;
        import zephyr.BroadcastEvent;
       
       
                private var settings:XML;
                private var itemsToLoad:int = 0;
                private var itemsLoaded:int = 0;
                private var layerByDepth:Array = new Array();
                public var layerByName:Dictionary = new Dictionary(true);
                public var xmlByName:Dictionary = new Dictionary(true);
               
                public function init():void
                {
                        var xmlLoader:URLLoader = new URLLoader();
                        xmlLoader.dataFormat = URLLoaderDataFormat.BINARY;
                        xmlLoader.load( new URLRequest( loaderInfo != null && loaderInfo.parameters.xml?loaderInfo.parameters.xml:"PanoSalado.xml" ) );
                        xmlLoader.addEventListener(Event.COMPLETE, onXMLLoaded);
                }
               
                private function onXMLLoaded(e:Event):void
                {
                        settings = XML( e.target.data );
                        for each (var layer:XML in settings.* )
                        {
                                xmlByName[layer.@id.toString()] = layer;
                               
                                var loader:Loader = new Loader();
                                loader.load( new URLRequest( layer.@url.toString() ), new LoaderContext( false, ApplicationDomain.currentDomain) );
                                loader.name = layer.@id.toString();
                                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, layerLoaded);
                               
                                itemsToLoad++
                        }
                }
               
                private function layerLoaded(e:Event):void
                {
                        itemsLoaded++;
                       
                        var name:String = e.target.loader.name.toString();
                        var layer:DisplayObject = e.target.content;
                        //layer.name = name;
                        layerByDepth[settings.*.(@id == name ).@depth || 0] = layer;
                       
                        layerByName[ name.toString() ] = layer;
                       
                        addChild( layer );
                       
                        if (itemsLoaded == itemsToLoad)
                        {
                                for (var i:int=0; i < layerByDepth.length; i++)
                                {
                                        var displayObject:DisplayObject = layerByDepth[i];
                                        if (displayObject)
                                        {
                                                addChild( displayObject );
                                        }
                                }
                                dispatchEvent( new BroadcastEvent(BroadcastEvent.ALL_LAYERS_LOADED) );
                        }
                }
       
                       
                ]]>
        </mx:Script>
</mx:Application>

But I get the following error:

TypeError: Error #1034: Type Coercion failed: cannot convert PanoSalado@251720c1 to mx.core.IUIComponent.
        at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\Container.as:3251]
        at mx.core::Container/addChildAt()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\Container.as:2200]
        at mx.core::Container/addChild()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\Container.as:2140]
        at ModuleLoader/layerLoaded()[/Development/Workspaces3.3/flexgrails/Panosalado Test/src/ModuleLoader.mxml:56]

Hmmm.... Right, all

Hmmm....

Right, all Children of a Flex Application class object have to extend UIComponent.

What if you edit PanoSalado.as, and in the class declaration:

public class PanoSalado extends Sprite

change that to:

public class PanoSalado extends UIComponent

Then re-compile.

I am very curious if that will do it.

Zephyr

I can't get it to work...

I can't get it to work... And besides that it will destroy the plugin capabilities. All other plugins have to be changed and compiled as well....

There are in SVN files called 'FlexInterface.mxml' and 'Main.mxml' what are those for ? Isn't there a simple example of how to do this ? Or am I the first to try ?

There is no simple example

There is no simple example of how to do this yet. Take a look at FlexInterface.xml. It is a Flex Interface for PanoSalado that I have been working on. However, it is simply a Flex application child of ModuleLoader that is stacked on top of the PanoSalado layer, with the Flex Application's background made transparent.

What you are trying to do is actually put PanoSalado's display into a Flex component.

l will be looking at how to do this, and will let you know as soon as I've got an answer.

Zephyr

How to put PanoSalado in a Flex UIComponent

Hi,

Alright I've done some research on this, and I have a the theory on how to do this and a general code example of how to put a Papervision Viewport into a flex component. Basically you use a Canvas object in flex and then add your viewport to it ( canvasObject.addChild(viewportObject) ):

Here is the code example (just view the source and look at the mxml file and the Canvas3D class:

http://the.fontvir.us/b10g/?id=103

So to do this in PanoSalado, you are going to have to "reach" into PanoSalado and grab the viewports and addChild them into a Canvas object. This is the code to get a reference to a viewport in PanoSalado:

viewport = panosalado.getSpaceByName(panosalado.currentSpace).viewport as Viewport3d;

canvas3d.addChild( viewport );

Of course, you will have to do this for each new viewport each time a new spaces is created. So a BroadcastEvent will have to be dispatched. In fact, a special purpose broadcast event could be dispatched with a reference to the viewport in it, and then you wouldn't even have to use the first line of code above.

I will work on an actual PanoSalado specific example of this for everyone.

Zephyr

Better, simpler version of the same

Ok, instead of grabbing the viewports individually and adding them to your Canvas3D, instead just add panosalado.viewports to the Canvas3D and you shouldn't have to worry about managing the individual viewports at all.

I put together an example of this very soon.

Zephyr

This sounds

This sounds promising!
Thanks a lot for looking into this. I am looking forward for your example!

Menno

Example posted to repository

Hi Menno,

Alright, I just put the example together. It is in the repository. Look for FlexUserInterface.mxml in the src folder. (and com.fontvirus.Canvas3D, which is the tag you use to create a Flex UIComponent which contains Papervision viewports.)

It seems to be working great on my end. Let me know if you run into any troubles.

Zephyr

Hi zephyr, so close... I

Hi zephyr,

so close... I think.

I checked out the latest version from SVN. After that I compiled all files with flash (or is this wrong?). Then when I try to debug/run flex application I get the following error:

ReferenceError: Error #1065: Variable BroadcastEvent is not defined.
        at flash.system::ApplicationDomain/getDefinition()
        at FlexUserInterface/addedToStageHandler()[/Development/Workspaces3.3/flexgrails/PanoSaladoSource/src/FlexUserInterface.mxml:30]
        at FlexUserInterface/___FlexUserInterface_Application1_addedToStage()[/Development/Workspaces3.3/flexgrails/PanoSaladoSource/src/FlexUserInterface.mxml:9]
        at flash.display::DisplayObjectContainer/addChildAt()
        at mx.managers::SystemManager/preloader_preloaderDoneHandler()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\managers\SystemManager.as:2246]
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at mx.preloaders::Preloader/displayClassCompleteHandler()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\preloaders\Preloader.as:434]
        at mx.preloaders::Preloader/dispatchAppEndEvent()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\preloaders\Preloader.as:294]
        at mx.preloaders::Preloader/appCreationCompleteHandler()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\preloaders\Preloader.as:442]
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at mx.core::UIComponent/dispatchEvent()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\UIComponent.as:9051]
        at mx.core::UIComponent/set initialized()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\UIComponent.as:1167]
        at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:698]
        at Function/http://adobe.com/AS3/2006/builtin::apply()
        at mx.core::UIComponent/callLaterDispatcher2()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\UIComponent.as:8460]
        at mx.core::UIComponent/callLaterDispatcher()[E:\dev\3.0.x\frameworks\projects\framework\src\mx\core\UIComponent.as:8403]

Menno

What does the HTML file look

What does the HTML file look like? You should be embedding ModuleLoader.swf and passing along the path to the XML:

<script type="text/javascript">
          var so = new SWFObject("ModuleLoader.swf?xml=PanoSalado.xml", "pano", "100%", "100%", "9", "#FFFFFF");        
          so.addParam("allowFullScreen","true");
          so.addParam("allowScriptAccess","sameDomain");
          so.write("flashcontent");
          window.document["pano"].focus();
    </script>

Then the XML file should have layer tags for all the modules, especially amongst them, PanoSalado.swf. ModuleLoader contains the definition of BroadcastEvent, so the only reason I can think of that you would see that error is if you are not embedding ModuleLoader.swf.

Zephyr

Hmmm.... I assumed the

Hmmm....

I assumed the normal flex generated html could be used to start the custom application (FlexUserInterface.mxml). So there is no need to load the ModuleLoader. Is this not correct ?

I see that the FlexUserInterface.mxml should load the ModuleLoader.swf. Maybe here is the problem ?

You can ignore the Flash

You can ignore the Flash Compiler generated HTML. The compiler will generate HTML like that for everything. Unless you wish to compile ModuleLoader.swf (In which case you can use the ModuleLoader.swf HTML file, AS LONG AS the XML file is named PanoSalado.xml and in the same directory, because the compiler generated HTML won't know anything about the XML file, and so ModuleLoader will have to use the default address).

To use PanoSalado, you embed ModuleLoader.swf into the HTML, provide it with an XML file listing the layers to load in (and their settings), and ModuleLoader handles loading everything. And one of the layers should be PanoSalado.swf. And another should be your Flex User Interface .swf file. And any others you like. Cursor.swf maybe, or some custom layers that do whatever you build them for.

If you don't embed moduleloader.Swf, you will see that run-time error about broadcast event not being defined.