How to get the size of an embedded image / swf? - actionscript-3

Normally if you were loading an image from a URL you would do the following:
m_image = new Image();
m_image.addEventListener(Event.COMPLETE, image_completeHandler, false, 0, true);
m_image.source = "http://www.example.com/image.jpg";
private function image_completeHandler(event:Event):void
{
// Image content has now loaded, we need to wait for it to validate it's size
m_image.addEventListener(FlexEvent.UPDATE_COMPLETE, image_updateCompleteHandler, false, 0, true);
}
private function image_updateCompleteHandler(event:FlexEvent):void
{
// Do stuff with width / height
}
But, if you set the source to an embedded image class, the complete event doesn't appear to fire. So my question is, how can you get the width / height of an embedded image / swf?

The instatiation of any embedded asset is syncronous (I think the only exception is Loader.loadBytes), so as soon as you do it you can access all its properties:
image = new EmbeddedImage();
trace(image.width, image.height);

Related

Optimize ItemRenderer For Flex Mobile Application

I made this class, which is an ItemRenderer class, used in a DataGroup ( mobile application ),
and I am not entirely sure if I did the right thing or not, my issues are :
Is there a better way to show the image, which is 80x80 and directly loaded from the server;
How to make the height of the row dynamic, I mean, depending on the height of the 3 StyleableTextFeild
Is this the right way to add the listener on the image, that will trigger a simple HTTPService,
Here is the functions from the class, Any help would be much appreciated !!
Image
Declared it as a simple image :
var logo:Image;
On override createChildren
logo = new Image();
addChild(logo);
And I added on set Data
logo.source = "http://192.168.0.15:3000/"+value.logo_thumb_url;
Size
override protected function measure():void {
measuredWidth = measuredMinWidth = stage.fullScreenWidth;
measuredHeight = measuredMinHeight = 100;
}
Listener
override public function set data(value:Object):void {
tel.text = String(value.Tel);
description.text = String(value.Descricao);
nome.text = String(value.Nome);
logo.addEventListener(MouseEvent.CLICK, function():void{
var service:HTTPService = new HTTPService();
service.url = value.targer;
service.method = "GET";
// setting headers and other variables ...
service.send();
});
}
You can use URLLoader or Loader for loading the image if you are planning to cache the image on the client side, if you cache the image, it wil help you not load the image again when the users scrolls through the list. (What you have done is Ok, but you will hit performance issues)
For variable row height, if Datagroup does not work, use List. find it here Flex 4: Setting Spark List height to its content height
There should be a buttonMode property for some items, make it buttonMode for the logo, for variable row height, find something related to wordWrap and variableRowHeight properties on the datagroup.
There are a few suggestions, what you have coded is good, but, instead of adding the listeners on set data, add it in creation complete, as it is more appropriate. Also, the event listeners has to be weak referenced, http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener()

Scaling AVM1Movie for using with BitmapData in as3

I have a actionscript 2 SWF that I am wanting to export into a PNG, however the fact that it is loaded as a AVM1Movie in as3 is proving quite troublesome.
When you load the as2 swf in just the normal standalone flash player, you can right click -> zoom in and it scales well since its redrawing the vector data at the size. But when i'm trying to make the Loader object (that contains the loaded as2 swf) scale, whenever i draw it to a BitmapData object, i just get the original size of the swf with blank space around it, rather then having the swf scale to the new dimensions.
My code looks like this:
var theFile:File = File(event.target);
var dis:DisplayObject = this.mLoader.content;
dis.width *=2;
dis.height *=2;
var bd:BitmapData = new BitmapData(dis.width, dis.height, true, 0x00000000);
trace("display object height and width is " + dis.width + " " + dis.height);
bd.draw(dis);
var stream:FileStream = new FileStream();
stream.open(theFile, FileMode.WRITE);
stream.writeBytes(PNGEncoder.encode(bd)); // needs as3corelib
stream.close();
Alert.show("saved to " + theFile.nativePath );
But when I open up the resulting PNG File, I get this (red shows the transparent background):
Is there any way to make it so that when I draw the as2 swf to BitmapData, it scales it like it would in the flash player?
I believe you should be able to simply use scaleX and scaleY properties instead of attempting to multiple the height and width values.
var dis:DisplayObject = this.mLoader.content;
//dis.width *=2;
dis.scaleX = 2;
//dis.height *=2;
dis.scaleY = 2;
EDIT
Alternatively since the above isn't working for you try to use a matrix argument for the draw call.
var mat:Matrix = new Matrix();
mat.scale(2,2);
bd.draw(dis,mat);

AS3 As3IsoLib Adding Sprite

I'm trying to add an image to a sprite then add it to the grid. The original size of the image is 276x202. However when it's been added to the grid it increases in size.
http://i.imgur.com/P1Jlq.png
The result is
http://i.imgur.com/0UPBH.png
public class main extends MovieClip
{
public function main()
{
var view:IsoView = new IsoView();
view.setSize((stage.stageWidth), stage.stageHeight);
view.clipContent = true;
addChild(view);
var gridHolder:IsoScene = new IsoScene();
view.addScene(gridHolder);
var scene:IsoScene = new IsoScene();
view.addScene(scene);
graphics.beginFill(0x000000, 1);
graphics.drawRect(0, 0, 800, 600);graphics.endFill();
var grid:IsoGrid = new IsoGrid();
grid.cellSize = 40;
grid.setGridSize(20, 20, 0);
gridHolder.addChild(grid);
gridHolder.render();
//var box:IsoBox = new IsoBox();
//box.setSize(40, 40, 40);
//box.moveTo(80, 80, 0);
//scene.addChild(box);
var player:IsoSprite;
var myLoader:Loader;
myLoader=new Loader();
myLoader.load(new URLRequest('imgs/DesertTankNE.png'));
//myLoader.width = 5; //Makes image disappear no matter what value is set.
//myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, OnComplete); //Doesn't change anything if we say on completion of loading image add it to the sprite.
player = new IsoSprite();
player.sprites = [myLoader];
//player.setSize(1,1,0); //Doesn't seem to affect anything no matter what size specified.
//player.width = 2; //Same as above
scene.addChild(player);
scene.render();
}
}
I've tried setting the width and height of the image when loading it and also tried setting the size of the sprite. The former makes the image not appear no matter what value is set and the latter doesn't seem to affect anything.
There is absolutely nothing wrong with your as3isolib code, and the image is not being resized in any way by code. Compare the tank image to the size of the grid cells (which should be 20 pixels width by 20 pixels height) and you should see that their relative sizes are ok.
The only problem there is that the whole flash stage is being resized. Are you testing your flash movie on the browser perhaps? Make sure you aren't setting the flash movie's width and height as 100% of its container in the HTML. If the flash movie is in a div and flash is told to be a width and height of 100%, it will stretch out to whatever size the div is.
Seeing your code I think you want your stage size to be 800x600; set your flash movie to those dimensions using the metatag SWF, for example:
[SWF(width="800", height="600", frameRate="30", backgroundColor="#FFFFFF")]
If you are using Flash Builder, you might need to clean your project a couple of times (Project -> Clean) to clear the previous compiler settings. Test your SWF movie outside of the broswer (double click the SWF file to open it on your local flash player) and make sure it has the proper dimensions. You should see the tank and the grid cells the right size now.
If you want to test it in the browser, don't use the HTML wrapper generated by Flash Builder (or Flash Pro). Make your own html using swfobject and set the correct width and height, for example:
<script type="text/javascript">
swfobject.embedSWF("myIsoTank.swf", "flash_container_div", "800", "600", "10", "expressInstall.swf");
</script>
This should get rid of your problem.

How can I load a Papervision/Flex application (SWF) as a material on a Papervision plane?

I am trying to build a portfolio application similar to the used by Whitevoid. I am using Flex 4 and Papervision3D 2. I have everything working except for one issue. When I try to load an external SWF as a material on one of the planes, I can see any native Flex or Flash components in their correct positions, but the papervision objects are not being rendered properly. It looks like the viewport is not being set in the nested swf. I have posted my code for loading the swf below.
private function loadMovie(path:String=""):void
{
loader = new Loader();
request = new URLRequest(path);
loader.contentLoaderInfo.addEventListener(Event.INIT, addMaterial);
loader.load(request);
}
private function addMaterial(e:Event):void
{
movie = new MovieClip();
movie.addChild(e.target.content);
var width:Number = 0;
var height:Number = 0;
width = loader.contentLoaderInfo.width;
height = loader.contentLoaderInfo.height;
//calculate the aspect ratio of the swf
var matAR:Number = width/height;
if (matAR > aspectRatio)
{
plane.scaleY = aspectRatio / matAR;
}
else if (matAR < aspectRatio)
{
plane.scaleX = matAR / aspectRatio;
}
var mat:MovieMaterial = new MovieMaterial(movie, false, true, false, new Rectangle(0, 0, width, height));
mat.interactive = true;
mat.smooth = true;
plane.material = mat;
}
Below I have posted two pictures. The first is a shot of the application running by itself. The second is the application as a MovieMaterial on a Plane. You can see how the button created as a spark object in the mxml stays in the correct position, but papervision sphere (which is rotating) is in the wrong location. Is there something I am missing here?
Man. I haven't seen that site in a while. Still one of the cooler PV projects...
What do you mean by:
I cannot properly see the scene rendered in Papervision
You say you can see the components in their appropriate positions, as in: you have a plane with what looks like the intended file loading up? But I'm guessing that you can't interact with it.
As far as I know, and I've spent a reasonable amount of time trying to make something similar work, the MovieMaterial (which I assume you're using) draws a Bitmap of whatever contents exist in your MovieClip, and if you set it to animated=true, then it will render out a series of bitmaps - equating animation. What it's not doing, is displaying an actual MovieClip (or SWF) on the plane. So you may see your components, but this is how:
MovieMaterial.as line 137
// ______________________________________________________________________ CREATE BITMAP
/**
*
* #param asset
* #return
*/
protected function createBitmapFromSprite( asset:DisplayObject ):BitmapData
{
// Set the new movie reference
movie = asset;
// initialize the bitmap since it's new
initBitmap( movie );
// Draw
drawBitmap();
// Call super.createBitmap to centralize the bitmap specific code.
// Here only MovieClip specific code, all bitmap code (maxUVs, AUTO_MIP_MAP, correctBitmap) in BitmapMaterial.
bitmap = super.createBitmap( bitmap );
return bitmap;
}
Note in the WhiteVoid you never actually interact with a movie until it "lands" = he's very likely swapping in a Movie on top of the bitmap textured plane.
The part that you are interacting with is probably another plane that holds the "button" that simply becomes visible on mouseover.
I think PV1.0 had access to real swfs as a material but this changed in 2.0. Sadly. Hopefully Molehill will.
cheers

as3 video full screen mode

I have created a video player, but need to add a button that, when clicked, puts the video into full-screen viewing mode. I don't want to scale everything on the stage - just the video. I can't seem to find how to do this - I thought it would be easy.
See if this works:
stage.displayState = StageDisplayState.FULL_SCREEN;
videoPlayer.x = 0;
videoPlayer.y = 0;
//save the width and height in temp vars
//for restoring them later.
videoPlayer.width = stage.fullScreenWidth;
videoPlayer.height = stage.fullScreenHeight;
My understanding is that you can only set the entire stage to full screen, not elements selectively, as you are effectively scaling up the stage object at the root of the display tree. The best way to accomplish the effect that you are looking for would be to arrange/hide/show any objects that you don't want to be visible in a FullScreenEvent.FULL_SCREEN event handler.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/FullScreenEvent.html
Also, a relevant tidbit from the Stage docs, displayState section:
The scaling behavior of the movie in full-screen mode is determined by the scaleMode setting (set using the Stage.scaleMode property or the SWF file's embed tag settings in the HTML file). If the scaleMode property is set to noScale while the application transitions to full-screen mode, the Stage width and height properties are updated, and the Stage the resize event.
Came across this problem recently and this worked like charm. So putting it up here in case it helps anyone.
Flex Client code:
private function startFullScreen(event:MouseEvent):void
{
videoHolder.removeChild(vid); //videoHolder is an spark VideoDisplay
Component
this.stage.addChild(vid);
this.stage.displayState = StageDisplayState.FULL_SCREEN;
oldWidth = vid.width; //store old values required while going back
oldHeight = vid.height;
vid.width = this.stage.width;
vid.height = this.stage.height;
this.stage.addEventListener(FullScreenEvent.FULL_SCREEN,fullScreenHandler);
}
}
/* handler for Fullscreen */
private function fullScreenHandler(event:FullScreenEvent):void
{
//This function is called when user presses Esc key
//on returning to normal state, add the video back
if(!event.fullScreen)
{
this.stage.removeChild(vid);
videoHolder.addChild(vid);
vid.width = oldWidth;
vid.height = oldHeight;
this.stage.removeEventListener(FullScreenEvent.FULL_SCREEN,fullScreenHandler )
}
}
If elements on the stage are scaling it sounds as though you're using the fullScreenRect property rather than simply instructing the stage object to go into fullscreen mode.
Amarghosh has the right approach, but it can be made more flexible by attaching a listener:
stage.addEventListener(Event.RESIZE, _onStageResize, false, 0, true);
stage.displayState = StageDisplayState.FULL_SCREEN;
private function _onStageResize(event:Event):void
{
if(stage.displayState == StageDisplayState.FULL_SCREEN)
{
// Proportionally resize your video to the stage's new dimensions
// i.e. set its height and width such that the aspect ratio is not distorted
}
else
{
// Restore the normal layout of your elements
}
}
To Enter Full Screen Mode
var fullScreenButton:Button = new Button();
...
addChild(fullScreenButton);
fullScreenButton.addEventListener(MouseEvent.CLICK, fullScreenButtonHandler);
...
private function fullScreenButtonHandler(event:MouseEvent)
{
var screenRectangle:Rectangle = new Rectangle(video.x, video.y, video.width, video.height);
stage.fullScreenSourceRect = screenRectangle;
stage.displayState = StageDisplayState.FULL_SCREEN;
}
To Leave Full Screen Mode
...
stage.displayState = StageDisplayState.NORMAL;
...
Note: You can also press escape.
Source: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS44B1892B-1668-4a80-8431-6BA0F1947766.html