Flash AS3 List Component Labels Cropping? - actionscript-3

For some reason, when I add a selectable list the labels in each cell keep getting cropped when the row height is increased. I believe this may happen because the original row height is 20, so the list automatically crops anything that goes outside of a box with row height of 20; so, my question would be: is there anyway to change this functionality?
Here is a screenshot of what it looks like:
http://s7.postimg.org/6wqxfb1qz/Screen_Shot_2013_10_10_at_8_31_49_PM.png
Here is my code:
list = new List();
list.rowHeight = 50;
list.setRendererStyle("contentPadding", 5);
var myTextFormat:TextFormat = new TextFormat();
myTextFormat.size = 20;
myTextFormat.font = "Microsoft Sans Serif";
list.setRendererStyle("textFormat", myTextFormat);
list.width = 118;
list.height = stage.stageHeight - 60;
list.focusEnabled = false;
list.setStyle("contentPadding", 5);
addCategories();
list.move(0, 50);
addChild(list);

You can use the variableRowHeight property to make the height of List control rows variable based on their content
Here is the documentation explaining this,
you should add list.variableRowHeight="true"

Related

AS3 custom TextField text is being drawn outside its textWidth

So this one is a little hard to explain. I have a custom Text class that automatically resizes and sets the width of the text when you change its value. I then take that Text and draw it on a Bitmap to scale it up to make the text look pixelated.
I have a property called maxWidth that allows you to restrict the width of the text if you want it to maintain a certain width. By default the maxWidth is the width of the text's parent so that it doesn't get cut off or expand the parent's boundaries unexpectedly.
So unfortunately when I draw the text it sometimes gets cut off on the right side. Now I've checked all the values and the width and textWidth are showing up as within their maxWidth values, but when I take a look myself through screenshots I see the text is actually about 3 pixels wider than it should be.
Here's an image to better explain what I mean:
I turned on borders so you can easily see what I mean. The word "and" on the first line gets drawn outside its border. Here is the line of code that handles resizing text when you change its bounds.
override protected function checkResize(value:String):void {
var bufferWidth:uint = Math.floor(Number(defaultTextFormat.size) / bufferDivisor) + bufferMin;
var maxWidth:Number = this.maxWidth;
x = y = 0;
if (parent is Stage) {
var stageParent:Stage = Stage(parent);
super.width = stageParent.stageWidth;
super.height = stageParent.stageHeight;
if (maxWidth == 0) maxWidth = stageParent.stageWidth;
}
else {
super.width = parent.width;
super.height = parent.height;
if (maxWidth == 0) maxWidth = parent.width;
}
maxWidth = maxWidth / scale;
text = value;
if (textWidth + bufferWidth <= maxWidth) super.width = textWidth + bufferWidth;
else super.width = maxWidth;
super.height = textHeight + 4;
if (textSnapshot) updateSnapshot();
if (alignRelation) Align.alignTo(textSprite, alignRelation, alignDirection, alignXOffset, alignYOffest);
}
And for this text specifically the width value states it's 512, which is correct since that's the maxWidth. However if you notice the top line in the text, it goes beyond the 512 width border, it actually goes all the way to 515 even though it says its width is 512. Even more bizarre is the textWidth states it's 510.4 even though the first line goes well beyond that amount. I just want to know if I'm doing anything wrong or if there's a way to get a true textWidth value.
This seems to be related to embedding fonts, at least it was when I had the same problem. A workaround is to set the right margin of the text field, like so
var tf:TextFormat = new TextFormat();
tf.rightMargin = 10; // or whatever fixes your problem, e.g. relate it to font size
textField.setTextFormat(tf);

Libgdx scene2dui column sizing issue

I was making a level table in libgdx using scroll pane. here there are different tables with specific level on a particular scroll pane. Is there any way to preset a particular table to be the first one I see, becuase it would be stupid if I have more than 50 level and I have to scroll through all of them to go to a particular level at end.
A brief details about my tables and scrollpane.
I have a arraylist of table called as column table, which is used as to store different level details in different columns. then this column table is added to another table which is called as levleTable.
The level table is added to scrollpane which is added to main table.
public void setScrollPane() {
scrollPane = new ScrollPane(levelTable, getScrollPaneStyle());
// scrollPane = new ScrollPane(levelTable, skin);
//scrollPane.setFlickScroll(true);
scrollPane.setFadeScrollBars(false);
scrollPane.setScrollingDisabled(false, true);
scrollPane.setScrollX(300);
scrollPane.updateVisualScroll();
//scrollPane.setSmoothScrolling(true);
mainTable.add(scrollPane).expand();
}
and in constructor`
mainTable = new Table();
mainTable.setFillParent(true);
levelTable = new Table();
setScrollPane();
columnTable = new ArrayList<Table>();
levelSelectionButton = new ArrayList<TextButton>();
makeLevelMenu();
//adding main table to stage
stage.addActor(mainTable);`
For the the better idea (when using mechanism like this) i to scroll the scrollPane automatically to the current object (which could be the table with your next level for example).
You can easily achieve it using:
scrollPane.setScrollY(y);
where the y should be
y = (total height of scroll Pane content) - ( (desired element Y position inside scrollPane) - (element height) )
I mean that if your scrollPane content has 100px height and there are 5 elements every with 20px height then scrolling to the third is:
y = 100 - (3 * 20px - 20px) = 100 - 40px = 60px
The same will work if your scrollPane is arranged horizontally - you just need to use scrollPane.setScrollX(x) and calculates all width instead of heights
UPDATE: before using setScrollX / setScrollY you have to call .layout() method on the scrollPane
The example:
#Override
public void show()
{
//creating stage and viewport
viewport = new FillViewport(1280, 800);
stage = new Stage(viewport);
Gdx.input.setInputProcessor(stage);
//creating levelTable
Table levelTable = new Table();
levelTable.setSize(2000, 500);
//filling levelTable with fake actors (it can be labels of your levels numbers)
for(int i = 0; i < 100; i++)
{
Actor a = new Actor();
a.setSize(80, 200);
//set debug to see the outline
a.debug();
levelTable.add(a).pad(150, 10, 150, 10);
}
//set debug to see the outline
levelTable.debug();
//defining scroll
ScrollPane scrollPane = new ScrollPane(levelTable, skin);
scrollPane.setSize(800, 600); //your custom size
scrollPane.setPosition(50, 50); //your custom position
scrollPane.setFadeScrollBars(false);
scrollPane.setScrollingDisabled(false, true);
//important!! you have to call it before setScrollX
scrollPane.layout(); //that's the thing!
//the number of column you want to go to
int numberOfColumn = 10;
//now move to column no numberOfColumn
scrollPane.setScrollX( levelTable.getWidth() - ( levelTable.getColumns() - numberOfColumn - 1 ) * 100 ); //100, because column width is 100 - actor = 80 + 2 * 10 pad
//set debug to see the outline
scrollPane.debug();
this.stage.addActor(scrollPane);
}

AS3 image rotate within / scale to fit sprite

We're making bitmap data from a sprite where we want to take an image and rotate within / scale to fit. This is our code, which includes a rotation.
_rotation defines how much the user has input.
The problem is, we're getting an output file that is 100% white.
We think that the image is rotating about 0x0y therefore rotating the image outside the bounds of the sprite.
Furthermore, the image is not scaling to the child, instead is sort of "cropping" as it inherits.
What is the best way of doing this? Basically we want to take an image and rotate within / scale to fit
var sprite1:Sprite = new Sprite();
addChild(sprite1);
var photoBitmap:Bitmap = new Bitmap(_bitmapData);
sprite1.addChild(photoBitmap);
sprite1.rotation = _rotation;
var sprite2:Sprite = new Sprite();
addChild(sprite2);
sprite2.addChild(sprite1);
var bitmapData:BitmapData = new BitmapData(sprite2.width,sprite2.height,false,0xFFFFFF);
bitmapData.draw(sprite2);
The simple way to draw sprite with scaling/rotating is using Matrix in method bitmapData.draw().
Example:
var sourceImage:SomeSprite = new SomeSprite();
var matrix:Matrix = new Matrix();
matrix.scale(0.5, 0.5);
matrix.rotate(0.5 * Math.PI);
var newImage:BitmapData = new BitmapData(sourceImage.width/2, sourceImage.height/2);
newImage.draw(sourceImage, matrix);
Your issue is likely a cause of rotating around the top left corner (which can make the entire object left of or above the registration point (0 x and 0 y) and not get drawn.
An easy way you can account for this, is to move sprite1 after the rotation to account for the new size and position caused by rotating:
...
sprite2.addChild(sprite1);
var actualPosition:Rectangle = sprite2.getBounds(sprite2); //this gets the new position/dimensions of the object
sprite1.x = -actualPosition.x;
sprite1.y = -actualPosition.y;
var bitmapData:BitmapData = new BitmapData(sprite2.width,sprite2.height,false,0xFFFFFF);
...

Finding the actual text height AS3

How can I get the actual height of a text in AS3 TextField? It appears that TextField.textHeight reports some fixed value that doesn't depend on the contents of a TextField.
The example code below produces the following:
text=o p g y d j
textWidth=120.8
textHeight=**96**
text=o
textWidth=15
textHeight=**96**
text=oW
textWidth=43.3
textHeight=**96**
Obviously, the height should be different for "o" and "p", etc.
The AS3 code:
import flash.text.TextField;
var format : TextFormat = new TextFormat();
format.font = "Times New Roman";
format.size = 30;
format.align = TextFormatAlign.CENTER;
var textField1 : TextField = new TextField();
textField1.defaultTextFormat = format;
textField1.selectable = false;
textField1.sharpness = 0;
textField1.embedFonts = true;
textField1.multiline = false;
textField1.height = 50;
textField1.width = 200;
textField1.x = 10;
textField1.y = 10;
addChild(textField1);
textField1.text = "o p g y d j";
trace("text=" + textField1.text);
trace("textWidth=" + textField1.textWidth);
trace("textHeight=" + textField1.textHeight);
textField1.text = "o";
trace("\ntext=" + textField1.text);
trace("textWidth=" + textField1.textWidth);
trace("textHeight=" + textField1.textHeight);
textField1.text = "oW";
trace("\ntext=" + textField1.text);
trace("textWidth=" + textField1.textWidth);
trace("textHeight=" + textField1.textHeight);
stop();
I guess TextField.textHeight is not the right variable, but what should I use instead?
Mark Fox is right that textHeight doesn't represent the actual height of text - and that the classic TextField in Flash doesn't have any support for getting the actual pixel height of rendered text. What textHeight does represent is the line height - which is its ascent (font's height above baseline), descent (font's height below baseline) and leading (space between lines) combined. As implied, the height is constant, based on the font's ascent and descent, not the actual text's. (Bearing this in mind, see Adobe's overview of the terms here - and note that TextLineMetrics won't help you either).
The "new" Flash Text Engine (flash.text.engine) does include properties to get the actual height of text rendered using that technology (e.g. TextLine.totalHeight) - but then we're getting into low level text rendering. If you need to use "classic" TextFields, this won't help you measuring the text anyway, since the Flash Text Engine has its own renderer, which doesn't necessarily render text at the same height and width as "classic" text.
What you can do instead is render the TextField to BitmapData then measure the bounds of the text:
// Create a completely transparent BitmapData:
var bmd:BitmapData = new BitmapData(
textfield.width,
textfield.height,
true,
0x00ffffff);
// Note that some cases may require you to render a Sprite/MovieClip
// CONTAINING the TextField for anything to get drawn.
// For example, AntiAliasType.ADVANCED (antialias for readability) is known to
// not be renderable in some cases - other settings may cause nothing to be
// rendered too. In that case, simply wrap add the TextField as a child of an
// otherwise empty Sprite/MovieClip, and pass that to draw() instead:
bmd.draw(textfield);
// This gets the bounds of pixels that are not completely transparent.
// Param 1: mask = specifies which color components to check (0xAARRGGBB)
// Param 2: color = is the color to check for.
// Param 3: findColor = whether to bound pixels OF the specified color (true),
// or NOT OF the specified color (false)
//
// In this case, we're interested in:
// 1: the alpha channel (0xff000000)
// 2: being 00 (0x00......)
// 3: and want the bounding box of pixels that DON'T meet that criterium (false)
var rect:Rectangle = bmd.getColorBoundsRect(0xff000000, 0x00000000, false);
// Do remember to dispose BitmapData when done with it:
bmd.dispose();
trace("text height = " + rect.height);
trace("text width = " + rect.width);
Note on accuracy
This may be completely irrelevant, depending on what you're going to use this for, but it's worth bearing in mind:
This method will obviously always return a result in whole pixels - the actual rendering of the glyphs, however, uses sub-pixels.
In other words, if you add the results of measuring the width of a "V" and an "o", and then compare that to the result of "Vo", they may not be the same. You might get "40 + 35 = 74". Ignoring that kerning etc. may push the letters closer together, the rendering of each letter (placement, anti-aliasing etc.) may also be different, depending on its context.
Your question highlights a legacy of weak semantics in the Flash typographic APIs.
The textHeight property represents the relative size of the typeface in pixels, it doesn't account for the pixel representation of the particular glyphs (the individual letter shapes) in the TextField.
As far as I know there is no direct programatic way to measure a glyph with Flash. However, you could bitmap the textfield and use getPixel to guess:
var tf:TextField = …your textfield…
var wide:int = tf.width;
var tall:int = tf.height;
var bmpd:BitmapData = new BitmapData(wide, tall, true,0xFFFFFFFF);
bmpd.draw( tf );
var totalPixels:int = wide * tall;
var index:int = totalPixels + 1;
var useIndex:int;
var xPixel:int;
var yPixel:int;
while (--index > 0) {
useIndex = index - 1;
xPixel = useIndex % wide;
yPixel = int(useIndex / wide);
var pixelColor:uint = bmpd.getPixel(xPixel, yPixel);
// write some logic to find the y extremes where the pixelColor values are not white (or whatever background color specified when you created the BitmapData)
}
You can do that by "textHeight";
// Create TextField
var tf:TextField = new TextField();
tf.wordWrap = true;
tf.multiline = true;
tf.selectable = false;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.autoSize = TextFieldAutoSize.LEFT; // It's should not be "=TextFieldAutoSize.NONE;"
tf.embedFonts = true;
tf.text = "Your text here";
this.addChild(tf);
trace(tf.textHeight);
Hope it will help

Actionscript object colour change / tint

i am new to Actionscript and I need help changing the colour of an object which is called with add child, i need the colour to change once the user has selected the desired colour they want from a combo box:
//MY CODE
if (e.target.value == "blue")
{
//need to change to this (0x0000FF)
//enter code here
}
Any help much appreciated!
Try using the color transform object.
var redAmount:Number = 0;
var greenAmount:Number = 0;
var blueAmount:Number = 1;
var alphaAmount:Number = 1;
var redOffset:Number = 0;
var greenOffset:Number = 0;
var blueOffset:Number = 0;
var alphaOffset:Number = 0;
yourDisplayObject.transform.colorTransform = new ColorTransform(redAmount, greenAmount, blueAmount, alphaAmount, redOffset, greeenOffset, blueOffset, alphaOffset);
The first four variables are multipliers - they will take the existing color value and adjust it as if multiplying by that number. So to reduce a color by 1/2 use 0.5. To make black set all to 0. To change nothing make all 1's.
The second four variables will increase or decrease the color amount of all pixels by that amount. So to make a color hit a specific hex value, say 0xFFCC33, you would do this:
yourDisplayObject.transform.colorTransform = new ColorTransform(0, 0, 0, 1, 0xFF, 0xCC, 0x33, 0x00);
Here is a link to the adobe documentation if you need more help:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/ColorTransform.html
If you decide you want to change the color gradually instead of instantly take a look at TweenMax from greensock. The greensock tween classes are a widely used workhorse of actionscript programming.
To tint a display object with TweenMax the code would be:
TweenMax.to(yourDisplayObject, 1, {tint:0x0000FF});
This class applies a color transform to the object using that code, but it changes the values gradually over time
Here is a link to where you can get TweenMax.
http://www.greensock.com/tweenmax/
Here is the easiest to understand (as I see it anyway) way to accomplish this:
if (e.target.value == "blue")
{
var colorTransform:ColorTransform = yourObject.transform.colorTransform; //store the current color data for the object
colorTransform.color = 0x0000FF; //make it totally blue
yourObject.transform.colorTransform = colorTransform; //now assign it back to the object
}