API Docs for: 1.2.0
Show:

File: src/gameobjects/Textfield.ts

/**
* Kiwi - GameObjects
* @module Kiwi
* @submodule GameObjects 
* 
*/

module Kiwi.GameObjects {

	/**
	* Textfield is a GameObject that is used when you are wanting to render text onto the current State. The Textfield is not designed to have any interaction with other GameObjects and as such it does not have many (if any) components or even a width/height.
	*
	* @class Textfield
	* @namespace Kiwi.GameObjects
	* @extends Kiwi.Entity
	* @constructor
	* @param state {Kiwi.State} The state that this Textfield belongs to
	* @param text {String} The text that is contained within this textfield.
	* @param [x=0] {Number} The new x coordinate from the Position component
	* @param [y=0] {Number} The new y coordinate from the Position component
	* @param [color="#000000"] {String} The color of the text. 
	* @param [size=32] {Number} The size of the text in pixels.
	* @param [weight="normal"] {String} The weight of the text.
	* @param [fontFamily="sans-serif"] {String} The font family that is to be used when rendering.
	* @return {Textfield} This Game Object.
	*/
	export class Textfield extends Kiwi.Entity {

		constructor(state: Kiwi.State, text: string, x: number = 0, y: number = 0, color: string = "#000000", size: number = 32, weight: string = "normal", fontFamily: string = "sans-serif") {

			super(state, x,y);

			if (this.game.renderOption === Kiwi.RENDERER_WEBGL) {
				this.glRenderer = this.game.renderer.requestSharedRenderer("TextureAtlasRenderer");
			}

			this._text = text;
			this._fontWeight = weight;
			this._fontSize = size;
			this._fontColor = new Kiwi.Utils.Color( color );
			this._fontFamily = fontFamily;
			this._textAlign = "left";
			this._baseline = "top";
			
			this._tempDirty = true;

			// Create the canvas
			this._canvas = document.createElement("canvas");
			this._canvas.width = 2;
			this._canvas.height = 2;
			this._ctx = this._canvas.getContext("2d");

			// Add it to the TextureLibrary
			this.atlas = new Kiwi.Textures.SingleImage(this.game.rnd.uuid(), this._canvas);
			this.state.textureLibrary.add(this.atlas);
			this.atlas.dirty = true;

			// Track actual text width - not canvas width (which rounds up to powers of 2), necessary for proper alignment
			this._alignWidth = 0;

			// Setup components
			this.box = this.components.add(
				new Kiwi.Components.Box(
					this, x, y, this.width, this.height ) );
		}

		/**
		* Returns the type of object that this is
		* @method objType
		* @return {string} "Textfield"
		* @public
		*/
		public objType() {
			return "Textfield";
		}

		/**
		* The text that is to be rendered.
		* @property _text
		* @type string
		* @private
		*/
		private _text: string;
		
		/**
		* The weight of the font.
		* @property _fontWeight
		* @type string
		* @default "normal"
		* @private
		*/
		private _fontWeight: string;

		/**
		* The size of the font.
		* @property _fontSize
		* @type number
		* @default 32
		* @private
		*/
		private _fontSize: number;

		/**
		* The color of the text.
		* @property _fontColor
		* @type Kiwi.Utils.Color
		* @private
		*/
		private _fontColor: Kiwi.Utils.Color;

		/**
		* The font family that is to be rendered.
		* @property _fontFamily
		* @type string
		* @default "sans-serif"
		* @private
		*/
		private _fontFamily: string;

		/**
		* The alignment of the text. This can either be "left", "right" or "center"
		* @property _textAlign
		* @type string
		* @default "center"
		* @private
		*/
		private _textAlign: string;

		/**
		* The pixel width of the text. Used internally for alignment purposes.
		* @property _alignWidth
		* @type number
		* @default 0
		* @private
		* @since 1.1.0
		*/
		private _alignWidth: number;

		/**
		* The baseline of the text to be rendered.
		* @property _baseline
		* @type string
		* @private
		*/
		private _baseline: string; 

		/**
		* The text that you would like to appear in this textfield.
		* @property text
		* @type string
		* @public
		*/
		public set text(value: string) {
			this._text = value;
			this._tempDirty = true;
	  
		} 
		public get text(): string {
			return this._text;
		}

		/**
		* The color of the font that is contained in this textfield.
		* May be set with a string, or an array of any valid
		* Kiwi.Utils.Color arguments.
		* Returns a hex string prepended with "#".
		* @property color
		* @type string
		* @public
		*/
		public set color( val: any ) {
			if ( !Kiwi.Utils.Common.isArray( val ) ) {
				val = [ val ];
			}
			this._fontColor.set.apply( this._fontColor, val );
			this._tempDirty = true;

		}
		public get color(): any {
			return "#" + this._fontColor.getHex();
		}

		/**
		* The weight of the font.
		* @property fontWeight
		* @type string
		* @public
		*/
		public set fontWeight(val: string) {
			this._fontWeight = val;
			this._tempDirty = true;
		}
		public get fontWeight(): string {
			return this._fontWeight;
		}

		/**
		* The size on font when being displayed onscreen.
		* @property fontSize
		* @type number
		* @public
		*/
		public set fontSize(val: number) {
			this._fontSize = val;
			this._tempDirty = true;
		}
		public get fontSize(): number {
			return this._fontSize;
		}

		/**
		* The font family that is being used to render the text.
		* @property fontFamily 
		* @type string
		* @public
		*/
		public set fontFamily(val: string) {
			this._fontFamily = val;
			this._tempDirty = true;
		}
		public get fontFamily(): string {
			return this._fontFamily;
		}

		/**
		* A static property that contains the string to center align the text.
		* @property TEXT_ALIGN_CENTER
		* @type string
		* @static
		* @final
		* @public
		*/
		public static TEXT_ALIGN_CENTER: string = "center";

		/**
		* A static property that contains the string to right align the text.
		* @property TEXT_ALIGN_RIGHT
		* @type string
		* @static
		* @final
		* @public
		*/
		public static TEXT_ALIGN_RIGHT: string = "right";

		/**
		* A static property that contains the string to left align the text.
		* @property TEXT_ALIGN_LEFT
		* @type string
		* @static
		* @final
		* @public
		*/
		public static TEXT_ALIGN_LEFT: string = "left";

		/**
		* Alignment of the text. You can either use the static TEXT_ALIGN constants or pass a string.
		* @property textAlign
		* @type string
		* @public
		*/
		public set textAlign(val: string) {
			this._textAlign = val;
			this._tempDirty = true;
		}

		public get textAlign(): string {
			return this._textAlign;
		}

		/**
		* The canvas element which the text is rendered onto. 
		* @property _canvas
		* @type HTMLCanvasElement.
		* @private
		*/
		private _canvas: HTMLCanvasElement;

		/**
		* The context for the canvas element. Used whilst rendering text.
		* @property _ctx
		* @type CanvasRenderingContext2D
		* @private
		*/
		private _ctx: CanvasRenderingContext2D;

		/**
		* If the temporary canvas is dirty and needs to be re-rendered. Only used when the text field rendering is being optimised.
		* @property _tempDirty
		* @type boolean
		* @private
		*/
		private _tempDirty: boolean = true;

		/**
		* Hitbox component
		* @property box
		* @type Kiwi.Components.Box
		* @public
		* @since 1.2.0
		*/
		public box: Kiwi.Components.Box;


		/**
		* This method is used to render the text to an offscreen-canvas which is held in a TextureAtlas (which is generated upon the instanitation of this class). 
		* This is so that the canvas doesn't render it every frame as it can be costly and so that it can be used in WebGL with the TextureAtlasRenderer.
		*
		* @method _renderText
		* @private
		*/
		private _renderText() {

			//Get/Set the width
			this._ctx.font = this._fontWeight + " " + this._fontSize + "px " + this._fontFamily;


			// Get the size of the text.
			var _measurements: TextMetrics = this._ctx.measureText(this._text);   //when you measure the text for some reason it resets the values?! 
			var width = _measurements.width;
			var height = this._fontSize * 1.3; //Need to find a better way to calculate
			
			// Cache alignment width
			this._alignWidth = width;

			// Is the width base2?
			if (Kiwi.Utils.Common.base2Sizes.indexOf(width) == -1) {
				var i = 0;
				while (width > Kiwi.Utils.Common.base2Sizes[i]) i++;
				width = Kiwi.Utils.Common.base2Sizes[i];
			}

			// Is the height base2?
			if (Kiwi.Utils.Common.base2Sizes.indexOf(height) == -1) {
				var i = 0;
				while (height > Kiwi.Utils.Common.base2Sizes[i]) i++;
				height = Kiwi.Utils.Common.base2Sizes[i];
			}

			// Apply the width/height
			this._canvas.width = width;  
			this._canvas.height = height;

			// Clear the canvas
			this._ctx.clearRect(0, 0, width, height);

			// Reapply the styles....cause it unapplies after a measurement...?!?
			this._ctx.font = this._fontWeight + " " + this._fontSize + "px " + this._fontFamily;
			this._ctx.fillStyle = this.color.slice( 0, 7 );
			this._ctx.textBaseline = this._baseline;

			// Draw the text.
			this._ctx.fillText(this._text, 0, 0);

			// Update inherited properties
			this.width = this._alignWidth;
			this.height = this._canvas.height;


			//Update the cell and dirty/undirtyfiy
			this.atlas.cells[0] = {
				x: 0,
				y: 0,
				w: this._canvas.width,
				h: this._canvas.height,
				hitboxes: [ {
					x: this._textAlign === Kiwi.GameObjects.Textfield.TEXT_ALIGN_LEFT ? 0 :
						this._textAlign === Kiwi.GameObjects.Textfield.TEXT_ALIGN_CENTER ?
						-this._alignWidth * 0.5 : -this._alignWidth,
					y: 0,
					w: this.width,
					h: this.height
					} ] };
			this._tempDirty = false;
			this.atlas.dirty = true;
		}

		/**
		* Called by the Layer to which this Game Object is attached
		* @method render
		* @param {Kiwi.Camera}
		* @public
		*/
		public render(camera:Kiwi.Camera) {

			if (this.alpha > 0 && this.visible) {

				//render on stage
				var ctx: CanvasRenderingContext2D = this.game.stage.ctx;
				ctx.save();

				var t: Kiwi.Geom.Transform = this.transform;
				if (this.alpha > 0 && this.alpha <= 1) {
					ctx.globalAlpha = this.alpha;
				}

				//Does the text need re-rendering
				if (this._tempDirty) this._renderText();

				//Align the text
				var x = 0;
				switch (this._textAlign) {
					case Kiwi.GameObjects.Textfield.TEXT_ALIGN_LEFT:
						x = 0;
						break;
					case Kiwi.GameObjects.Textfield.TEXT_ALIGN_CENTER:
						x = this._alignWidth * 0.5;
						break;
					case Kiwi.GameObjects.Textfield.TEXT_ALIGN_RIGHT:
						x = this._alignWidth;
						break;
				}

				//Draw the Image
				var m: Kiwi.Geom.Matrix = t.getConcatenatedMatrix();

				ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
				ctx.drawImage(this._canvas, 0, 0, this._canvas.width, this._canvas.height, -t.rotPointX - x, -t.rotPointY, this._canvas.width, this._canvas.height);
				

				ctx.restore();
			}

		}

		/**
		* Renders the GameObject using WebGL. 
		* @method renderGL
		* @param {WebGLRenderingContext} gl
		* @param {Kiwi.Camera} camera
		* @param {Object} params
		* @public
		*/
		public renderGL(gl: WebGLRenderingContext, camera: Kiwi.Camera, params: any = null) {

			//Does the text need re-rendering
			if (this._tempDirty) this._renderText();

			//Set-up the xyuv and alpha
			var vertexItems = [];

			//Transform/Matrix
			var t: Kiwi.Geom.Transform = this.transform;
			var m: Kiwi.Geom.Matrix = t.getConcatenatedMatrix();

			//See where the text should be.
			var x = 0;
			switch (this._textAlign) {
				case Kiwi.GameObjects.Textfield.TEXT_ALIGN_LEFT:
					x = 0;
					break;
				case Kiwi.GameObjects.Textfield.TEXT_ALIGN_CENTER:
					x = -(this._alignWidth * 0.5);
					break;
				case Kiwi.GameObjects.Textfield.TEXT_ALIGN_RIGHT:
					x = -(this._alignWidth);
					break;
			}

			//Create the Point Objects.
			var pt1 = new Kiwi.Geom.Point(x - t.rotPointX, 0 - t.rotPointY);
			var pt2 = new Kiwi.Geom.Point(this._canvas.width + x - t.rotPointX , 0 - t.rotPointY);
			var pt3 = new Kiwi.Geom.Point(this._canvas.width + x - t.rotPointX , this._canvas.height - t.rotPointY);
			var pt4 = new Kiwi.Geom.Point(x - t.rotPointX, this._canvas.height - t.rotPointY);

			//Add on the matrix to the points
			pt1 = m.transformPoint(pt1);
			pt2 = m.transformPoint(pt2);
			pt3 = m.transformPoint(pt3);
			pt4 = m.transformPoint(pt4);

			//Append to the xyuv and alpha arrays 
			vertexItems.push(
				pt1.x, pt1.y, 0, 0, this.alpha,
				//Top Left Point
				pt2.x, pt2.y, this._canvas.width, 0, this.alpha,
				//Top Right Point
				pt3.x, pt3.y, this._canvas.width, this._canvas.height, this.alpha,          //Bottom Right Point
				pt4.x, pt4.y, 0, this._canvas.height, this.alpha
				//Bottom Left Point
				);
			//Add to the batch!
			(<Kiwi.Renderers.TextureAtlasRenderer>this.glRenderer).concatBatch(vertexItems);
		}
	}

	/**
	* Alias of the "Kiwi.GameObjects.Textfield". 
	* This will continue to be an alias until we can deprecate the existing version.
	*
	* @class TextField
	* @namespace Kiwi.GameObjects
	* @extends Kiwi.GameObjects.Textfield
	*/
	export var TextField = Kiwi.GameObjects.Textfield;

}