AS3 Setting width and height of a Sprite Container - actionscript-3

Ok, my mind is boggling over this issue im having. I know this might seem like such an easy issue and I can't understand why I cant figure it out but none the less I can't and I've just about given up. Here's the issue:
I have a sprite container which is supposed to hold a bunch of thumbnails to videos. I am able to populate the container with all the videos and the whole works but obviously if I add a bunch of videos its going to exceed the size of the flash document so I need to add a UIScrollBar (which I did) now the scrollbars target is set to the container but isnt allowing me to scroll and if im correct this is because the container doesnt have a set height. So Im trying to set the height of this container but the second I try setting the height or even width all my thumbnails I used to be able to see are gone! It's as if the size is being set to 0 when its not I've even tried to set it to a specified size just to test and nothing. Anyways heres my code if anyone can help out I'd really appreciate it! Thanks in advance!
import fl.controls.UIScrollBar;
var videoList:XMLList;
var numVideos:Number;
var current_Video:Number = 0;
var video_position:Number;
var video_paused:Boolean;
var xmlPlaylist:String;
//XML File setup
var playlist_xml:XML;
var myLoader:URLLoader = new URLLoader();
//Playlist setup
var thumb_width:Number;
var thumb_height:Number;
var thumbs_x:Number;
var thumbs_y:Number;
var main_container:Sprite;
var thumbs:Sprite;
var scrollbar:UIScrollBar;
//Loader Data
this.loaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
function loaderComplete(e:Event):void
{
var myQueryStrings = this.loaderInfo.parameters;
xmlPlaylist = myQueryStrings.pList;
myLoader.load(new URLRequest(xmlPlaylist + "?uniq=" + new Date().getTime()));
}
myLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void {
playlist_xml = new XML(e.target.data);
numVideos = playlist_xml.video.length();
videoList = playlist_xml.video;
thumb_width = playlist_xml.#thumb_width;
thumb_height = playlist_xml.#thumb_height;
thumbs_x = playlist_xml.#thumbs_x;
thumbs_y = playlist_xml.#thumbs_y;
current_Video = Math.round(Math.random()*(numVideos-1))+1;
current_Video--;
startPlayer();
}
function startPlayer()
{
makeContainers();
callThumbs();
setVideo(current_Video);
}
function makeContainers():void
{
main_container = new Sprite();
addChild(main_container);
thumbs = new Sprite();
thumbs.addEventListener(MouseEvent.CLICK, playVideo);
thumbs.addEventListener(MouseEvent.MOUSE_OVER, onOver);
thumbs.addEventListener(MouseEvent.MOUSE_OUT, onOut);
thumbs.x = thumbs_x;
thumbs.y = thumbs_y;
This is where the Issue is: (If i comment out this code it displays the thumbnails)
thumbs.width = thumb_width;
thumbs.height = (thumb_height + 11) * 3;
thumbs.buttonMode = true;
main_container.addChild(thumbs);
scrollbar = new UIScrollBar();
scrollbar.x = thumbs_x + thumb_width + 2;
scrollbar.y = thumbs_y;
scrollbar.setSize(25, (thumb_height + 11) * 3);
scrollbar.visible = true;
scrollbar.scrollTarget = thumbs;
main_container.addChild(scrollbar);
}
function callThumbs():void
{
for (var i:Number = 0; i (less than) numVideos; i++) //For some reason Stack Overflow isnt allowing me to put the symbol less than so i just typed it in...
{
var thumb_url = videoList[i].#thumb;
var thumb_loader = new Loader();
thumb_loader.name = i;
thumb_loader.load(new URLRequest(thumb_url));
thumb_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, thumbLoaded);
thumb_loader.y = (thumb_height + 11) * i;
}
}
function thumbLoaded(e:Event):void
{
var my_thumb:Loader = Loader(e.target.loader);
thumbs.addChild(my_thumb);
}
function playVideo(e:MouseEvent):void
{
setVideo(e.target.name);
}
function onOver (e:MouseEvent):void
{
var my_thumb:Loader = Loader(e.target);
my_thumb.alpha = 0.5;
}
function onOut (e:MouseEvent):void
{
var my_thumb:Loader = Loader (e.target);
my_thumb.alpha = 1;
}
function setVideo(current_Video)
{
var display:String = videoList[current_Video].#title;
var video:String = videoList[current_Video].#url;
txt_Display.text = display;
flvPlayer.source = video;
}
stop();

This is easy. You are creating Sprite, adding listeners, setting coordinates. The sprite is still empty. Then you set width and height, which are translating to scaleX and scaleY. On empty sprite this messes up transformation matrix and sprite will never show up. Set width, height, or scaleX/Y only on non-empty sprites.

Related

How to get index of a Bitmap Image from bitmapdata(from an Array)?

I am wondering if i have an Array that push content that is Bitmap, how do i get index of a specific image when clicked. I tried to use indexOf but no luck, my codes are below.
Thanks for your time!
Code:
//First Part is where i add the URLRequest and add the image into contentHolder then onto Stage
function loadImage():void {
for(var i:int = 5; i < somedata.length; i++){
if(somedata[i]){
var loader:Loader = new Loader();
loader.load(new URLRequest("http://www.rentaid.info/rent/"+somedata[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
}
}
}
function onImageLoaded(e:Event):void {
loadedArray.push(e.target.content as Bitmap);
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
currentY1 += e.currentTarget.loader.content.height +300;
_contentHolder.mouseChildren = false; // ignore children mouseEvents
_contentHolder.mouseEnabled = true; // enable mouse on the object - normally set to true by default
_contentHolder.useHandCursor = true; // add hand cursor on mouse over
_contentHolder.buttonMode = true;
_contentHolder.addChild(loadedArray[i]);
addChild(_contentHolder);
_contentHolder.addEventListener(MouseEvent.CLICK, gotoscene);
}
}
// then the part where i try to get the index
function gotoscene(e:MouseEvent):void {
var index:Number;
index = loadedArray.indexOf(e.target);
trace(index);
}
Edit:
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
Your first question has very simple answer:
var image:Bitmap = new Bitmap();
var images:Array = new Array(image);
for (var i:uint = 0; i < images.length; i++) {
// images[i].bitmapData is the original image in your array
// image.bitmapData is searched one
if (images[i].bitmapData == image.bitmapData) {
// found
}
}
But your problem is bigger than this. I see you keep wandering around..
You should add listener to each child, not the content holder as one. I usually don't use Loaders, but get their Bitmaps and wrap them in Sprites or something, that I add into the scene. You should store either this Sprite or your Loader into that array, not the Bitmap. Then add listener to each of them (Sprite or Loader, not Bitmap) and get the target. Depending on what you've stored in the array, you can easily get it as:
function gotoscene(e:MouseEvent):void {
var index:uint = loadedArray(indexOf(e.target));
}
But it's important to store one specific type that will actually be clickable. Don't think about the Bitmap - it's only a graphic representation, and doesn't do much in the code.
**EDIT:
Okay I'm adding the code you need but it's important to understand what you are doing and not just rely on someone else's answer :)
function onImageLoaded(e:Event):void {
var bitmap:Bitmap = e.target.content as Bitmap; // get the Bitmap
var image:Sprite = new Sprite();
image.addChild(bitmap); // wrap it inside new Sprite
// add listener to Sprite!
image.addEventListener(MouseEvent.CLICK, gotoscene);
// gets url of current image (http://website.com/images/image1.jpg)
var url:String = e.target.loaderURL;
// get only the number from that url by replacing or by some other way
// this removes the first part and results in "1.jpg"
var name:String = url.replace("http://website.com/images/image", "");
// this removes the extension and results in number only - 1, 2, 3
// it's important to change this depending on your naming convention
name = name.replace(".jpg", "");
image.name = "button" + name; // results in "button1", "button2", "button3"
// store object, name, or whatever (not really needed in your case, but commonly used)
loadedArray.push(image.name);
image.x = counter * 100; // position so you can see them, at 100, 200, 300, etc.
_contentHolder.addChild(image); // add newly created Sprite to content
}
function gotoscene(e:MouseEvent):void {
var name:String = e.target.name;
// strips down "button" from "button1", and only the number remains,
// which is 1, 2, 3, etc. the number of the scene :)
var scene:uint = name.replace("button", "");
// you're the man now :)
}

Multiple sprites added in loop, but only last sprite clickable

I have multiple bitmap images added into sprites(each image added into 1 sprite) in a loop, then all the sprites added to 1 _contentHolder(Sprite) then that is added to a viewport.
What the problem is, the multiple sprites that are added inside the loop, everything displays with no problem but only the last sprite added is clickable. None of the sprite added before it is clickable. Wondering what the problem is, they are not overlapping and when i hover the mouse over the top of all the sprites, it turns into the mouse clicker but it just won't click.
Thanks for your time!
My code:
function onImageLoaded(e:Event):void {
loadedArray.push(e.target.content as Bitmap);
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
var image: Sprite= new Sprite;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
image.mouseChildren = true; // ignore children mouseEvents
image.mouseEnabled = true; // enable mouse on the object - normally set to true by default
image.useHandCursor = true; // add hand cursor on mouse over
image.buttonMode = true;
image.addChild(loadedArray[i]);
_contentHolder.addChild(image);
}
newArray.push(image);
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
var scroller:TouchScroller = new TouchScroller();
scroller.width = 300;
scroller.height = 265;
scroller.x = 10;
scroller.y = 100;
scroller.viewport = viewport;
addChild(scroller);
image.addEventListener(MouseEvent.CLICK, gotoscene);
}
loadImage();
Edit:
function gotoscene(e: MouseEvent):void{
var index:Number;
index = newArray.indexOf(e.target);
trace(index);
blackBox.graphics.beginFill(0x000000);
blackBox.graphics.drawRect( -1, -1, stage.width, stage.height);
blackBox.alpha = 0.7;
addChild(blackBox);
var originalBitmap : BitmapData = loadedArray[index].bitmapData;
var duplicate:Bitmap = new Bitmap(originalBitmap);
duplicate.width = stage.width;
_contentHolder1.addChild(duplicate);
// Use counter here to only add _contentHolder1 once
//Assuming that `samedata` is a class member (I can't see the rest of your code)
addChild(_contentHolder1);
}
Edit2:
private var image:Array = new Array;
//In the For loop
image[i] = new Sprite();
image[i].addChild(loadedArray[i]);
image[i].addEventListener(MouseEvent.CLICK, gotoscene);
function gotoscene(e:MouseEvent):void{
index = image.indexOf(e.target);
trace(index);
}
You should move image.addEventListener(MouseEvent.CLICK, gotoscene); statement into the loop where you add child sprites. Once you do, the listener will be added to all of the sprites, not just the last one that's currently stored in image variable, and is the only one that responds to your clicks.
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
var image: Sprite= new Sprite;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
image.mouseChildren = true; // ignore children mouseEvents
image.mouseEnabled = true; // enable mouse on the object - normally set to true by default
image.useHandCursor = true; // add hand cursor on mouse over
image.buttonMode = true;
image.addEventListener(MouseEvent.CLICK, gotoscene); // <-- THIS
image.addChild(loadedArray[i]);
_contentHolder.addChild(image);
}
And for all that is holy, learn to indent your code, so that you will be able to visually find the start and end of your loops and see if a certain statement is within the loop or not.
I did work for a few years in AS3 and this was a weird an usual problem. I used to solve it with a function that adds the event to each clip:
function someFunction():void {
for (...) {
var image:Sprite = new Sprite();
addSceneListener(image);
}
}
function addSceneListener(mc:Sprite):void {
mc.addEventListener(MouseEvent.CLICK, gogoscene);
}

How can I access the width of a JPG loaded inside a movieclip in AS3?

i'm trying to reproduce the bookshelf similar the one in this site: http://www.callis.com.br/
The books are PNG files that comes in several different sizes.
What I'm trying to accomplish is, after loading in several different movieclips (book0, book1, book2, ...) read their widths, calculate the gap necessary to push it, and then arrange the x value of each book.
Every time I try to access the width value, it says it's 0.
Here's a portion of my code, that's trying to do the trick.
Thanks in advance.
for (j=0; j < dados.livro.length(); j++){
if(j<8){
targetLivro = MovieClip(MovieClip(root).livros.getChildByName("livro"+(j)));
}else{
targetLivro = MovieClip(MovieClip(root).getChildByName("livro"+(j)));
}
preparaLivro(targetLivro,dados.livro[j].imagem.text(),dados.livro[j].link.text());
//larguraTotalLivrosSup += targetLivro.width;
//trace(larguraTotalLivrosSup);
trace("livro"+j+": ");
trace("título:"+dados.livro[j].titulo.text());
trace("imagem:"+dados.livro[j].imagem.text());
trace("link:"+dados.livro[j].link.text());
}
//organiza a primeira estante
//
/*
for (i=0; i<largurasArray.length; i++){
trace(largurasArray[i]);
}*/
var offset:Number = 20;
for (j=0; j<livros.numChildren; j++){
//targetLivro = MovieClip(livros).getChildByName("livro"+(j));
trace(livros.getChildAt(j).width);
}
function preparaLivro(livro:MovieClip, capa:String, url:String){
var capaLoader:Loader = new Loader();
var capaImageRequest:URLRequest = new URLRequest(capa);
var capaBitmapData:BitmapData;
var capaBitmap:Bitmap;
var capaLargura:Number = 0;
capaLoader.load(capaImageRequest);
capaLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void{
capaBitmapData = new BitmapData(e.target.content.width, e.target.content.height);
capaBitmapData.draw(capaLoader);
capaBitmap = new Bitmap;
capaBitmap.bitmapData = capaBitmapData;
livro.y -= e.target.content.height;
trace(e.target.content.width, e.target.content.height);
livro.buttonMode = true;
livro.addChild(capaBitmap);
livro.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void{
navigateToURL(new URLRequest(url), "_blank");
});
//trace(e.target.content.width);
});
}
Instantiate bitmap from LoaderInfo(event.target).content like:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("http://www.google.com/images/srpr/logo4w.png"));
function onComplete(event:Event):void
{
var bitmapData:BitmapData =
Bitmap(LoaderInfo(event.target).content).bitmapData;
}
Tracing bitmapData.width and bitmapData.height outputs:
width: 550, height: 190
Otherwise, if you want width / height from the loader, access loader's contentLoaderInfo:
var width:Number = loader.contentLoaderInfo.width;
var height:Number = loader.contentLoaderInfo.height;

AS3 removing dynamically created child movieclips

I'm fairly new to AS3. Anyways, I'm try to remove a dynamically created child movieclip when clicked on. When a dirt block is clicked on, which is a child movieclip of 'world' I want to remove it.
I've tried various ways of removing it using removeChild. I've also tried moving the function inside/outside of the for loop that creates the movieclips.
var blockCount:Number = 0;
var blockArray:Array = [];
var world:MovieClip = new World();
world.x = 50;
world.y = 50;
world.name = "world";
addChild(world);
for(var i:Number=1;i<=100;i++){
blockCount++;
var tempGrassBlock:MovieClip = new GrassBlock();
tempGrassBlock.x = i*16;
tempGrassBlock.y = 256;
tempGrassBlock.name = "b"+blockCount;
world.addChild(tempGrassBlock);
tempGrassBlock.addEventListener(MouseEvent.CLICK, removeBlock);
function removeBlock(event:Event){
world.removeChild(getChildByName(event.target.name));
}
}
Thanks for the help.
Try this
function removeBlock(event:Event){
world.removeChild(event.currentTarget as DisplayObject);
}
No function definition should be inside a for. I changed that in your code and rewrited a little below:
var blockCount:Number = 0;
var blockArray:Array = [];
var world:MovieClip = new World();
world.x = 50;
world.y = 50;
world.name = "world";
addChild(world);
for(var i:Number=1;i<=100;i++){
blockCount++;
var tempGrassBlock:MovieClip = new GrassBlock();
tempGrassBlock.x = i*16;
tempGrassBlock.y = 256;
tempGrassBlock.name = "b"+blockCount;
world.addChild(tempGrassBlock);
tempGrassBlock.addEventListener(MouseEvent.CLICK, removeBlock);
}
function removeBlock(event:MouseEvent){
trace("Is click really working? This target name is " + event.currentTarget.name);
world.removeChild(event.currentTarget));
}

TextField breaking MOUSE_OVER after moving it

I'm having a really weird problem with the MOUSE_OVER event. I'm building dynamic tabs representing mp3 songs containing textfields with info and a dynamic image for the cover art. I am trying to get a simple MOUSE_OVER working over the whole tab, such that you can select the next song to play.
I am using a Sprite with alpha 0 that overlays my whole tab (incl. the textFields) as a Listener for MOUSE_OVER and _OUT... I've checked by setting the alpha to something visible and it indeed covers my tab and follows it around as I move it (just making sure I'm not moving the tab without moving the hotspot). Also, I only create it once my cover art is loaded, ensuring that it will cover that too.
Now, when the tab is in the top position, everything is dandy. As soon as I move the tab to make space for the next tab, the textFields break my roll behaviour... just like that noob mistake of overlaying a sprite over the one that you're listening for MouseEvents on. But... the roll area is still on top of the field, I've set selectable and mouseEnabled to false on the textFields... nothing.
It is as if the mere fact of moving the whole tab now puts the textField on top of everything in my tab (whereas visually, it's still in its expected layer).
I'm using pixel fonts but tried it with system fonts, same thing... at my wits end here.
public function Tab(tune:Tune) {
_tune = tune;
mainSprite = new Sprite();
addChild(mainSprite);
drawBorder();
createFormat();
placeArtist();
placeTitle();
placeAlbum();
coverArt();
}
private function placeButton():void {
_button = new Sprite();
_button.graphics.beginFill(0xFF000,0);
_button.graphics.drawRect(0,0,229,40);
_button.graphics.endFill();
_button.addEventListener(MouseEvent.MOUSE_OVER, mouseListener);
_button.addEventListener(MouseEvent.MOUSE_OUT, mouseListener);
_button.buttonMode = true;
mainSprite.addChild(_button);
}
private function mouseListener(event:MouseEvent):void {
switch(event.type){
case MouseEvent.MOUSE_OVER :
hilite(true);
break;
case MouseEvent.MOUSE_OUT :
hilite(false);
break;
}
}
private function createFormat():void {
_format = new TextFormat();
_format.font = "FFF Neostandard";
_format.size = 8;
_format.color = 0xFFFFFF;
}
private function placeArtist():void {
var artist : TextField = new TextField();
artist.selectable = false;
artist.defaultTextFormat = _format;
artist.x = 41;
artist.y = 3;
artist.width = 135;
artist.text = _tune.artist;
artist.mouseEnabled = false;
mainSprite.addChild(artist);
}
private function placeTitle():void {
var title : TextField = new TextField();
title.selectable = false;
title.defaultTextFormat = _format;
title.x = 41;
title.y = 14;
title.width = 135;
title.text = _tune.title;
title.mouseEnabled = false;
mainSprite.addChild(title);
}
private function placeAlbum():void {
var album : TextField = new TextField();
album.selectable = false;
album.defaultTextFormat = _format;
album.x = 41;
album.y = 25;
album.width = 135;
album.text = _tune.album;
album.mouseEnabled = false;
mainSprite.addChild(album);
}
private function drawBorder():void {
_border = new Sprite();
_border.graphics.lineStyle(1, 0x545454);
_border.graphics.drawRect (0,0,229,40);
mainSprite.addChild(_border);
}
private function coverArt():void {
_image = new Sprite();
var imageLoader : Loader = new Loader();
_loaderInfo = imageLoader.contentLoaderInfo;
_loaderInfo.addEventListener(Event.COMPLETE, coverLoaded)
var image:URLRequest = new URLRequest(_tune.coverArt);
imageLoader.load(image);
_image.x = 1.5;
_image.y = 2;
_image.addChild(imageLoader);
}
private function coverLoaded(event:Event):void {
_loaderInfo.removeEventListener(Event.COMPLETE, coverLoaded);
var scaling : Number = IMAGE_SIZE / _image.width;
_image.scaleX = scaling;
_image.scaleY = scaling;
mainSprite.addChild (_image);
placeButton();
}
public function hilite(state:Boolean):void{
var col : ColorTransform = new ColorTransform();
if(state){
col.color = 0xFFFFFF;
} else {
col.color = 0x545454;
}
_border.transform.colorTransform = col;
}
Fixed it. What was happening was that I didn't set the height of the textfield. That was overshooting the tab and hence lying over the previously instantiated tab, blocking MouseOver... don't even ask.