package org.flixel { import flash.display.BitmapData; import flash.text.TextField; import flash.text.TextFormat; /** * Extends FlxSprite to support rendering text. * Can tint, fade, rotate and scale just like a sprite. * Doesn't really animate though, as far as I know. * Also does nice pixel-perfect centering on pixel fonts * as long as they are only one liners. * * @author Adam Atomic */ public class FlxText extends FlxSprite { /** * Internal reference to a Flash TextField object. */ protected var _textField:TextField; /** * Whether the actual text field needs to be regenerated and stamped again. * This is NOT the same thing as FlxSprite.dirty. */ protected var _regen:Boolean; /** * Internal tracker for the text shadow color, default is clear/transparent. */ protected var _shadow:uint; /** * Creates a new FlxText object at the specified position. * * @param X The X position of the text. * @param Y The Y position of the text. * @param Width The width of the text object (height is determined automatically). * @param Text The actual text you would like to display initially. * @param EmbeddedFont Whether this text field uses embedded fonts or nto */ public function FlxText(X:Number, Y:Number, Width:uint, Text:String=null, EmbeddedFont:Boolean=true) { super(X,Y); makeGraphic(Width,1,0); if(Text == null) Text = ""; _textField = new TextField(); _textField.width = Width; _textField.embedFonts = EmbeddedFont; _textField.selectable = false; _textField.sharpness = 100; _textField.multiline = true; _textField.wordWrap = true; _textField.text = Text; var format:TextFormat = new TextFormat("system",8,0xffffff); _textField.defaultTextFormat = format; _textField.setTextFormat(format); if(Text.length <= 0) _textField.height = 1; else _textField.height = 10; _regen = true; _shadow = 0; allowCollisions = NONE; calcFrame(); } /** * Clean up memory. */ override public function destroy():void { _textField = null; super.destroy(); } /** * You can use this if you have a lot of text parameters * to set instead of the individual properties. * * @param Font The name of the font face for the text display. * @param Size The size of the font (in pixels essentially). * @param Color The color of the text in traditional flash 0xRRGGBB format. * @param Alignment A string representing the desired alignment ("left,"right" or "center"). * @param ShadowColor A uint representing the desired text shadow color in flash 0xRRGGBB format. * * @return This FlxText instance (nice for chaining stuff together, if you're into that). */ public function setFormat(Font:String=null,Size:Number=8,Color:uint=0xffffff,Alignment:String=null,ShadowColor:uint=0):FlxText { if(Font == null) Font = ""; var format:TextFormat = dtfCopy(); format.font = Font; format.size = Size; format.color = Color; format.align = Alignment; _textField.defaultTextFormat = format; _textField.setTextFormat(format); _shadow = ShadowColor; _regen = true; calcFrame(); return this; } /** * The text being displayed. */ public function get text():String { return _textField.text; } /** * @private */ public function set text(Text:String):void { var ot:String = _textField.text; _textField.text = Text; if(_textField.text != ot) { _regen = true; calcFrame(); } } /** * The size of the text being displayed. */ public function get size():Number { return _textField.defaultTextFormat.size as Number; } /** * @private */ public function set size(Size:Number):void { var format:TextFormat = dtfCopy(); format.size = Size; _textField.defaultTextFormat = format; _textField.setTextFormat(format); _regen = true; calcFrame(); } /** * The color of the text being displayed. */ override public function get color():uint { return _textField.defaultTextFormat.color as uint; } /** * @private */ override public function set color(Color:uint):void { var format:TextFormat = dtfCopy(); format.color = Color; _textField.defaultTextFormat = format; _textField.setTextFormat(format); _regen = true; calcFrame(); } /** * The font used for this text. */ public function get font():String { return _textField.defaultTextFormat.font; } /** * @private */ public function set font(Font:String):void { var format:TextFormat = dtfCopy(); format.font = Font; _textField.defaultTextFormat = format; _textField.setTextFormat(format); _regen = true; calcFrame(); } /** * The alignment of the font ("left", "right", or "center"). */ public function get alignment():String { return _textField.defaultTextFormat.align; } /** * @private */ public function set alignment(Alignment:String):void { var format:TextFormat = dtfCopy(); format.align = Alignment; _textField.defaultTextFormat = format; _textField.setTextFormat(format); calcFrame(); } /** * The color of the text shadow in 0xAARRGGBB hex format. */ public function get shadow():uint { return _shadow; } /** * @private */ public function set shadow(Color:uint):void { _shadow = Color; calcFrame(); } /** * Internal function to update the current animation frame. */ override protected function calcFrame():void { if(_regen) { //Need to generate a new buffer to store the text graphic var i:uint = 0; var nl:uint = _textField.numLines; height = 0; while(i < nl) height += _textField.getLineMetrics(i++).height; height += 4; //account for 2px gutter on top and bottom _pixels = new BitmapData(width,height,true,0); frameHeight = height; _textField.height = height*1.2; _flashRect.x = 0; _flashRect.y = 0; _flashRect.width = width; _flashRect.height = height; _regen = false; } else //Else just clear the old buffer before redrawing the text _pixels.fillRect(_flashRect,0); if((_textField != null) && (_textField.text != null) && (_textField.text.length > 0)) { //Now that we've cleared a buffer, we need to actually render the text to it var format:TextFormat = _textField.defaultTextFormat; var formatAdjusted:TextFormat = format; _matrix.identity(); //If it's a single, centered line of text, we center it ourselves so it doesn't blur to hell if((format.align == "center") && (_textField.numLines == 1)) { formatAdjusted = new TextFormat(format.font,format.size,format.color,null,null,null,null,null,"left"); _textField.setTextFormat(formatAdjusted); _matrix.translate(Math.floor((width - _textField.getLineMetrics(0).width)/2),0); } //Render a single pixel shadow beneath the text if(_shadow > 0) { _textField.setTextFormat(new TextFormat(formatAdjusted.font,formatAdjusted.size,_shadow,null,null,null,null,null,formatAdjusted.align)); _matrix.translate(1,1); _pixels.draw(_textField,_matrix,_colorTransform); _matrix.translate(-1,-1); _textField.setTextFormat(new TextFormat(formatAdjusted.font,formatAdjusted.size,formatAdjusted.color,null,null,null,null,null,formatAdjusted.align)); } //Actually draw the text onto the buffer _pixels.draw(_textField,_matrix,_colorTransform); _textField.setTextFormat(new TextFormat(format.font,format.size,format.color,null,null,null,null,null,format.align)); } //Finally, update the visible pixels if((framePixels == null) || (framePixels.width != _pixels.width) || (framePixels.height != _pixels.height)) framePixels = new BitmapData(_pixels.width,_pixels.height,true,0); framePixels.copyPixels(_pixels,_flashRect,_flashPointZero); } /** * A helper function for updating the TextField that we use for rendering. * * @return A writable copy of TextField.defaultTextFormat. */ protected function dtfCopy():TextFormat { var defaultTextFormat:TextFormat = _textField.defaultTextFormat; return new TextFormat(defaultTextFormat.font,defaultTextFormat.size,defaultTextFormat.color,defaultTextFormat.bold,defaultTextFormat.italic,defaultTextFormat.underline,defaultTextFormat.url,defaultTextFormat.target,defaultTextFormat.align); } } }