Update mobile version to mobile v2.2.1

The android version just got a much needed update to fix some resolution issues on devices with cutouts.

It turns out the mobile source was actually pretty out of date, like 3 versions out of date! This commit brings it up to date.

All the changes have just been about keeping the game running on modern devices, though. The biggest change was adding the Starling library to the project, which made the game GPU powered and sped the whole thing up.
This commit is contained in:
Terry Cavanagh
2022-12-02 18:19:58 +01:00
parent 86d90a1296
commit 72d018ea04
140 changed files with 30533 additions and 2409 deletions

View File

@@ -0,0 +1,94 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display3D.Context3DTextureFormat;
import flash.utils.ByteArray;
/** A parser for the ATF data format. */
public class AtfData
{
private var _format:String;
private var _width:int;
private var _height:int;
private var _numTextures:int;
private var _isCubeMap:Boolean;
private var _data:ByteArray;
/** Create a new instance by parsing the given byte array. */
public function AtfData(data:ByteArray)
{
if (!isAtfData(data)) throw new ArgumentError("Invalid ATF data");
if (data[6] == 255) data.position = 12; // new file version
else data.position = 6; // old file version
var format:uint = data.readUnsignedByte();
switch (format & 0x7f)
{
case 0:
case 1: _format = Context3DTextureFormat.BGRA; break;
case 12:
case 2:
case 3: _format = Context3DTextureFormat.COMPRESSED; break;
case 13:
case 4:
case 5: _format = "compressedAlpha"; break; // explicit string for compatibility
default: throw new Error("Invalid ATF format");
}
_width = Math.pow(2, data.readUnsignedByte());
_height = Math.pow(2, data.readUnsignedByte());
_numTextures = data.readUnsignedByte();
_isCubeMap = (format & 0x80) != 0;
_data = data;
// version 2 of the new file format contains information about
// the "-e" and "-n" parameters of png2atf
if (data[5] != 0 && data[6] == 255)
{
var emptyMipmaps:Boolean = (data[5] & 0x01) == 1;
var numTextures:int = data[5] >> 1 & 0x7f;
_numTextures = emptyMipmaps ? 1 : numTextures;
}
}
/** Checks the first 3 bytes of the data for the 'ATF' signature. */
public static function isAtfData(data:ByteArray):Boolean
{
if (data.length < 3) return false;
else
{
var signature:String = String.fromCharCode(data[0], data[1], data[2]);
return signature == "ATF";
}
}
/** The texture format. @see flash.display3D.textures.Context3DTextureFormat */
public function get format():String { return _format; }
/** The width of the texture in pixels. */
public function get width():int { return _width; }
/** The height of the texture in pixels. */
public function get height():int { return _height; }
/** The number of encoded textures. '1' means that there are no mip maps. */
public function get numTextures():int { return _numTextures; }
/** Indicates if the ATF data encodes a cube map. Not supported by Starling! */
public function get isCubeMap():Boolean { return _isCubeMap; }
/** The actual byte data, including header. */
public function get data():ByteArray { return _data; }
}
}

View File

@@ -0,0 +1,140 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display.BitmapData;
import flash.display3D.textures.TextureBase;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import starling.core.Starling;
import starling.utils.MathUtil;
import starling.utils.execute;
/** @private
*
* A concrete texture that wraps a <code>Texture</code> base.
* For internal use only. */
internal class ConcretePotTexture extends ConcreteTexture
{
private var _textureReadyCallback:Function;
private static var sMatrix:Matrix = new Matrix();
private static var sRectangle:Rectangle = new Rectangle();
private static var sOrigin:Point = new Point();
/** Creates a new instance with the given parameters. */
public function ConcretePotTexture(base:flash.display3D.textures.Texture, format:String,
width:int, height:int, mipMapping:Boolean,
premultipliedAlpha:Boolean,
optimizedForRenderTexture:Boolean=false, scale:Number=1)
{
super(base, format, width, height, mipMapping, premultipliedAlpha,
optimizedForRenderTexture, scale);
if (width != MathUtil.getNextPowerOfTwo(width))
throw new ArgumentError("width must be a power of two");
if (height != MathUtil.getNextPowerOfTwo(height))
throw new ArgumentError("height must be a power of two");
}
/** @inheritDoc */
override public function dispose():void
{
base.removeEventListener(Event.TEXTURE_READY, onTextureReady);
super.dispose();
}
/** @inheritDoc */
override protected function createBase():TextureBase
{
return Starling.context.createTexture(
nativeWidth, nativeHeight, format, optimizedForRenderTexture);
}
/** @inheritDoc */
override public function uploadBitmapData(data:BitmapData):void
{
potBase.uploadFromBitmapData(data);
var buffer:BitmapData = null;
if (data.width != nativeWidth || data.height != nativeHeight)
{
buffer = new BitmapData(nativeWidth, nativeHeight, true, 0);
buffer.copyPixels(data, data.rect, sOrigin);
data = buffer;
}
if (mipMapping && data.width > 1 && data.height > 1)
{
var currentWidth:int = data.width >> 1;
var currentHeight:int = data.height >> 1;
var level:int = 1;
var canvas:BitmapData = new BitmapData(currentWidth, currentHeight, true, 0);
var bounds:Rectangle = sRectangle;
var matrix:Matrix = sMatrix;
matrix.setTo(0.5, 0.0, 0.0, 0.5, 0.0, 0.0);
while (currentWidth >= 1 || currentHeight >= 1)
{
bounds.setTo(0, 0, currentWidth, currentHeight);
canvas.fillRect(bounds, 0);
canvas.draw(data, matrix, null, null, null, true);
potBase.uploadFromBitmapData(canvas, level++);
matrix.scale(0.5, 0.5);
currentWidth = currentWidth >> 1;
currentHeight = currentHeight >> 1;
}
canvas.dispose();
}
if (buffer) buffer.dispose();
setDataUploaded();
}
/** @inheritDoc */
override public function get isPotTexture():Boolean { return true; }
/** @inheritDoc */
override public function uploadAtfData(data:ByteArray, offset:int = 0, async:* = null):void
{
var isAsync:Boolean = async is Function || async === true;
if (async is Function)
{
_textureReadyCallback = async as Function;
base.addEventListener(Event.TEXTURE_READY, onTextureReady);
}
potBase.uploadCompressedTextureFromByteArray(data, offset, isAsync);
setDataUploaded();
}
private function onTextureReady(event:Event):void
{
base.removeEventListener(Event.TEXTURE_READY, onTextureReady);
execute(_textureReadyCallback, this);
_textureReadyCallback = null;
}
private function get potBase():flash.display3D.textures.Texture
{
return base as flash.display3D.textures.Texture;
}
}
}

View File

@@ -0,0 +1,54 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display.BitmapData;
import flash.display3D.textures.RectangleTexture;
import flash.display3D.textures.TextureBase;
import starling.core.Starling;
/** @private
*
* A concrete texture that wraps a <code>RectangleTexture</code> base.
* For internal use only. */
internal class ConcreteRectangleTexture extends ConcreteTexture
{
/** Creates a new instance with the given parameters. */
public function ConcreteRectangleTexture(base:RectangleTexture, format:String,
width:int, height:int, premultipliedAlpha:Boolean,
optimizedForRenderTexture:Boolean=false,
scale:Number=1)
{
super(base, format, width, height, false, premultipliedAlpha,
optimizedForRenderTexture, scale);
}
/** @inheritDoc */
override public function uploadBitmapData(data:BitmapData):void
{
rectangleBase.uploadFromBitmapData(data);
setDataUploaded();
}
/** @inheritDoc */
override protected function createBase():TextureBase
{
return Starling.context.createRectangleTexture(
nativeWidth, nativeHeight, format, optimizedForRenderTexture);
}
private function get rectangleBase():RectangleTexture
{
return base as RectangleTexture;
}
}
}

View File

@@ -0,0 +1,269 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display3D.textures.TextureBase;
import flash.media.Camera;
import flash.net.NetStream;
import flash.system.Capabilities;
import flash.utils.ByteArray;
import flash.utils.getQualifiedClassName;
import starling.core.Starling;
import starling.core.starling_internal;
import starling.errors.AbstractClassError;
import starling.errors.AbstractMethodError;
import starling.errors.NotSupportedError;
import starling.events.Event;
import starling.rendering.Painter;
import starling.utils.Color;
import starling.utils.execute;
/** A ConcreteTexture wraps a Stage3D texture object, storing the properties of the texture
* and providing utility methods for data upload, etc.
*
* <p>This class cannot be instantiated directly; create instances using
* <code>Texture.fromTextureBase</code> instead. However, that's only necessary when
* you need to wrap a <code>TextureBase</code> object in a Starling texture;
* the preferred way of creating textures is to use one of the other
* <code>Texture.from...</code> factory methods in the <code>Texture</code> class.</p>
*
* @see Texture
*/
public class ConcreteTexture extends Texture
{
private var _base:TextureBase;
private var _format:String;
private var _width:int;
private var _height:int;
private var _mipMapping:Boolean;
private var _premultipliedAlpha:Boolean;
private var _optimizedForRenderTexture:Boolean;
private var _scale:Number;
private var _onRestore:Function;
private var _dataUploaded:Boolean;
/** @private
*
* Creates a ConcreteTexture object from a TextureBase, storing information about size,
* mip-mapping, and if the channels contain premultiplied alpha values. May only be
* called from subclasses.
*
* <p>Note that <code>width</code> and <code>height</code> are expected in pixels,
* i.e. they do not take the scale factor into account.</p>
*/
public function ConcreteTexture(base:TextureBase, format:String, width:int, height:int,
mipMapping:Boolean, premultipliedAlpha:Boolean,
optimizedForRenderTexture:Boolean=false, scale:Number=1)
{
if (Capabilities.isDebugger &&
getQualifiedClassName(this) == "starling.textures::ConcreteTexture")
{
throw new AbstractClassError();
}
_scale = scale <= 0 ? 1.0 : scale;
_base = base;
_format = format;
_width = width;
_height = height;
_mipMapping = mipMapping;
_premultipliedAlpha = premultipliedAlpha;
_optimizedForRenderTexture = optimizedForRenderTexture;
_onRestore = null;
_dataUploaded = false;
}
/** Disposes the TextureBase object. */
public override function dispose():void
{
if (_base) _base.dispose();
this.onRestore = null; // removes event listener
super.dispose();
}
// texture data upload
/** Uploads a bitmap to the texture. The existing contents will be replaced.
* If the size of the bitmap does not match the size of the texture, the bitmap will be
* cropped or filled up with transparent pixels */
public function uploadBitmap(bitmap:Bitmap):void
{
uploadBitmapData(bitmap.bitmapData);
}
/** Uploads bitmap data to the texture. The existing contents will be replaced.
* If the size of the bitmap does not match the size of the texture, the bitmap will be
* cropped or filled up with transparent pixels */
public function uploadBitmapData(data:BitmapData):void
{
throw new NotSupportedError();
}
/** Uploads ATF data from a ByteArray to the texture. Note that the size of the
* ATF-encoded data must be exactly the same as the original texture size.
*
* <p>The 'async' parameter may be either a boolean value or a callback function.
* If it's <code>false</code> or <code>null</code>, the texture will be decoded
* synchronously and will be visible right away. If it's <code>true</code> or a function,
* the data will be decoded asynchronously. The texture will remain unchanged until the
* upload is complete, at which time the callback function will be executed. This is the
* expected function definition: <code>function(texture:Texture):void;</code></p>
*/
public function uploadAtfData(data:ByteArray, offset:int=0, async:*=null):void
{
throw new NotSupportedError();
}
/** Specifies a video stream to be rendered within the texture. */
public function attachNetStream(netStream:NetStream, onComplete:Function=null):void
{
attachVideo("NetStream", netStream, onComplete);
}
/** Specifies a video stream from a camera to be rendered within the texture. */
public function attachCamera(camera:Camera, onComplete:Function=null):void
{
attachVideo("Camera", camera, onComplete);
}
/** @private */
internal function attachVideo(type:String, attachment:Object, onComplete:Function=null):void
{
throw new NotSupportedError();
}
// texture backup (context loss)
private function onContextCreated():void
{
_dataUploaded = false;
_base = createBase(); // recreate the underlying texture
execute(_onRestore, this); // restore contents
// if no texture has been uploaded above, we init the texture with transparent pixels.
if (!_dataUploaded) clear();
}
/** Recreates the underlying Stage3D texture object with the same dimensions and attributes
* as the one that was passed to the constructor. You have to upload new data before the
* texture becomes usable again. Beware: this method does <strong>not</strong> dispose
* the current base. */
protected function createBase():TextureBase
{
throw new AbstractMethodError();
}
/** Recreates the underlying Stage3D texture. May be used to manually restore a texture.
* Beware that new data needs to be uploaded to the texture before it can be used. */
starling_internal function recreateBase():void
{
_base = createBase();
}
/** Clears the texture with a certain color and alpha value. The previous contents of the
* texture is wiped out. */
public function clear(color:uint=0x0, alpha:Number=0.0):void
{
if (_premultipliedAlpha && alpha < 1.0)
color = Color.rgb(Color.getRed(color) * alpha,
Color.getGreen(color) * alpha,
Color.getBlue(color) * alpha);
var painter:Painter = Starling.painter;
painter.pushState();
painter.state.renderTarget = this;
// we wrap the clear call in a try/catch block as a workaround for a problem of
// FP 11.8 plugin/projector: calling clear on a compressed texture doesn't work there
// (while it *does* work on iOS + Android).
try { painter.clear(color, alpha); }
catch (e:Error) {}
painter.popState();
setDataUploaded();
}
/** Notifies the instance that the base texture may now be used for rendering. */
protected function setDataUploaded():void
{
_dataUploaded = true;
}
// properties
/** Indicates if the base texture was optimized for being used in a render texture. */
public function get optimizedForRenderTexture():Boolean { return _optimizedForRenderTexture; }
/** Indicates if the base texture is a standard power-of-two dimensioned texture of type
* <code>flash.display3D.textures.Texture</code>. */
public function get isPotTexture():Boolean { return false; }
/** The function that you provide here will be called after a context loss.
* On execution, a new base texture will already have been created; however,
* it will be empty. Call one of the "upload..." methods from within the callback
* to restore the actual texture data.
*
* <listing>
* var texture:Texture = Texture.fromBitmap(new EmbeddedBitmap());
* texture.root.onRestore = function():void
* {
* texture.root.uploadFromBitmap(new EmbeddedBitmap());
* };</listing>
*/
public function get onRestore():Function { return _onRestore; }
public function set onRestore(value:Function):void
{
Starling.current.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
if (value != null)
{
_onRestore = value;
Starling.current.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
}
else _onRestore = null;
}
/** @inheritDoc */
public override function get base():TextureBase { return _base; }
/** @inheritDoc */
public override function get root():ConcreteTexture { return this; }
/** @inheritDoc */
public override function get format():String { return _format; }
/** @inheritDoc */
public override function get width():Number { return _width / _scale; }
/** @inheritDoc */
public override function get height():Number { return _height / _scale; }
/** @inheritDoc */
public override function get nativeWidth():Number { return _width; }
/** @inheritDoc */
public override function get nativeHeight():Number { return _height; }
/** @inheritDoc */
public override function get scale():Number { return _scale; }
/** @inheritDoc */
public override function get mipMapping():Boolean { return _mipMapping; }
/** @inheritDoc */
public override function get premultipliedAlpha():Boolean { return _premultipliedAlpha; }
}
}

View File

@@ -0,0 +1,98 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display3D.Context3DTextureFormat;
import flash.display3D.textures.TextureBase;
import flash.display3D.textures.VideoTexture;
import flash.events.Event;
import starling.core.Starling;
import starling.utils.execute;
/** @private
*
* A concrete texture that wraps a <code>VideoTexture</code> base.
* For internal use only. */
internal class ConcreteVideoTexture extends ConcreteTexture
{
private var _textureReadyCallback:Function;
/** Creates a new instance with the given parameters.
* <code>base</code> must be of type <code>flash.display3D.textures.VideoTexture</code>.
*/
public function ConcreteVideoTexture(base:VideoTexture, scale:Number=1)
{
super(base, Context3DTextureFormat.BGRA, base.videoWidth, base.videoHeight, false,
false, false, scale);
}
/** @inheritDoc */
override public function dispose():void
{
base.removeEventListener(Event.TEXTURE_READY, onTextureReady);
super.dispose();
}
/** @inheritDoc */
override protected function createBase():TextureBase
{
return Starling.context.createVideoTexture();
}
/** @private */
override internal function attachVideo(type:String, attachment:Object,
onComplete:Function=null):void
{
_textureReadyCallback = onComplete;
base["attach" + type](attachment);
base.addEventListener(Event.TEXTURE_READY, onTextureReady);
setDataUploaded();
}
private function onTextureReady(event:Event):void
{
base.removeEventListener(Event.TEXTURE_READY, onTextureReady);
execute(_textureReadyCallback, this);
_textureReadyCallback = null;
}
/** The actual width of the video in pixels. */
override public function get nativeWidth():Number
{
return videoBase.videoWidth;
}
/** The actual height of the video in pixels. */
override public function get nativeHeight():Number
{
return videoBase.videoHeight;
}
/** @inheritDoc */
override public function get width():Number
{
return nativeWidth / scale;
}
/** @inheritDoc */
override public function get height():Number
{
return nativeHeight / scale;
}
private function get videoBase():VideoTexture
{
return base as VideoTexture;
}
}
}

View File

@@ -0,0 +1,336 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display3D.textures.TextureBase;
import flash.errors.IllegalOperationError;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import starling.core.Starling;
import starling.display.BlendMode;
import starling.display.DisplayObject;
import starling.display.Image;
import starling.filters.FragmentFilter;
import starling.rendering.Painter;
import starling.rendering.RenderState;
import starling.utils.execute;
/** A RenderTexture is a dynamic texture onto which you can draw any display object.
*
* <p>After creating a render texture, just call the <code>drawObject</code> method to render
* an object directly onto the texture. The object will be drawn onto the texture at its current
* position, adhering its current rotation, scale and alpha properties.</p>
*
* <p>Drawing is done very efficiently, as it is happening directly in graphics memory. After
* you have drawn objects onto the texture, the performance will be just like that of a normal
* texture — no matter how many objects you have drawn.</p>
*
* <p>If you draw lots of objects at once, it is recommended to bundle the drawing calls in
* a block via the <code>drawBundled</code> method, like shown below. That will speed it up
* immensely, allowing you to draw hundreds of objects very quickly.</p>
*
* <pre>
* renderTexture.drawBundled(function():void
* {
* for (var i:int=0; i&lt;numDrawings; ++i)
* {
* image.rotation = (2 &#42; Math.PI / numDrawings) &#42; i;
* renderTexture.draw(image);
* }
* });
* </pre>
*
* <p>To erase parts of a render texture, you can use any display object like a "rubber" by
* setting its blending mode to <code>BlendMode.ERASE</code>. To wipe it completely clean,
* use the <code>clear</code> method.</p>
*
* <strong>Persistence</strong>
*
* <p>Older devices may require double buffering to support persistent render textures. Thus,
* you should disable the <code>persistent</code> parameter in the constructor if you only
* need to make one draw operation on the texture. The static <code>useDoubleBuffering</code>
* property allows you to customize if new textures will be created with or without double
* buffering.</p>
*
* <strong>Context Loss</strong>
*
* <p>Unfortunately, render textures are wiped clean when the render context is lost.
* This means that you need to manually recreate all their contents in such a case.
* One way to do that is by using the <code>root.onRestore</code> callback, like here:</p>
*
* <listing>
* renderTexture.root.onRestore = function():void
* {
* var quad:Quad = new Quad(100, 100, 0xff00ff);
* renderTexture.clear(); // required on texture restoration
* renderTexture.draw(quad);
* });</listing>
*
* <p>For example, a drawing app would need to store information about all draw operations
* when they occur, and then recreate them inside <code>onRestore</code> on a context loss
* (preferably using <code>drawBundled</code> instead).</p>
*
* <p>However, there is one problem: when that callback is executed, it's very likely that
* not all of your textures are already available, since they need to be restored, too (and
* that might take a while). You probably loaded your textures with the "AssetManager".
* In that case, you can listen to its <code>TEXTURES_RESTORED</code> event instead:</p>
*
* <listing>
* assetManager.addEventListener(Event.TEXTURES_RESTORED, function():void
* {
* var brush:Image = new Image(assetManager.getTexture("brush"));
* renderTexture.draw(brush);
* });</listing>
*
* <p>[Note that this time, there is no need to call <code>clear</code>, because that's the
* default behavior of <code>onRestore</code>, anyway — and we didn't modify that.]</p>
*
*/
public class RenderTexture extends SubTexture
{
private static const USE_DOUBLE_BUFFERING_DATA_NAME:String =
"starling.textures.RenderTexture.useDoubleBuffering";
private var _activeTexture:Texture;
private var _bufferTexture:Texture;
private var _helperImage:Image;
private var _drawing:Boolean;
private var _bufferReady:Boolean;
private var _isPersistent:Boolean;
// helper object
private static var sClipRect:Rectangle = new Rectangle();
/** Creates a new RenderTexture with a certain size (in points). If the texture is
* persistent, its contents remains intact after each draw call, allowing you to use the
* texture just like a canvas. If it is not, it will be cleared before each draw call.
*
* <p>Non-persistent textures can be used more efficiently on older devices; on modern
* hardware, it does not make a difference. For more information, have a look at the
* documentation of the <code>useDoubleBuffering</code> property.</p>
*/
public function RenderTexture(width:int, height:int, persistent:Boolean=true,
scale:Number=-1, format:String="bgra")
{
_isPersistent = persistent;
_activeTexture = Texture.empty(width, height, true, false, true, scale, format);
_activeTexture.root.onRestore = _activeTexture.root.clear;
super(_activeTexture, new Rectangle(0, 0, width, height), true, null, false);
if (persistent && useDoubleBuffering)
{
_bufferTexture = Texture.empty(width, height, true, false, true, scale, format);
_bufferTexture.root.onRestore = _bufferTexture.root.clear;
_helperImage = new Image(_bufferTexture);
_helperImage.textureSmoothing = TextureSmoothing.NONE; // solves some aliasing-issues
}
}
/** @inheritDoc */
public override function dispose():void
{
_activeTexture.dispose();
if (isDoubleBuffered)
{
_bufferTexture.dispose();
_helperImage.dispose();
}
super.dispose();
}
/** Draws an object into the texture. Note that any filters on the object will currently
* be ignored.
*
* @param object The object to draw.
* @param matrix If 'matrix' is null, the object will be drawn adhering its
* properties for position, scale, and rotation. If it is not null,
* the object will be drawn in the orientation depicted by the matrix.
* @param alpha The object's alpha value will be multiplied with this value.
* @param antiAliasing Values range from 0 (no antialiasing) to 4 (best quality).
* Beginning with AIR 22, this feature is supported on all platforms
* (except for software rendering mode).
*/
public function draw(object:DisplayObject, matrix:Matrix=null, alpha:Number=1.0,
antiAliasing:int=0):void
{
if (object == null) return;
if (_drawing)
render(object, matrix, alpha);
else
renderBundled(render, object, matrix, alpha, antiAliasing);
}
/** Bundles several calls to <code>draw</code> together in a block. This avoids buffer
* switches and allows you to draw multiple objects into a non-persistent texture.
* Note that the 'antiAliasing' setting provided here overrides those provided in
* individual 'draw' calls.
*
* @param drawingBlock a callback with the form: <pre>function():void;</pre>
* @param antiAliasing Values range from 0 (no antialiasing) to 4 (best quality).
* Beginning with AIR 22, this feature is supported on all platforms
* (except for software rendering mode).
*/
public function drawBundled(drawingBlock:Function, antiAliasing:int=0):void
{
renderBundled(drawingBlock, null, null, 1.0, antiAliasing);
}
private function render(object:DisplayObject, matrix:Matrix=null, alpha:Number=1.0):void
{
var painter:Painter = Starling.painter;
var state:RenderState = painter.state;
var wasCacheEnabled:Boolean = painter.cacheEnabled;
var filter:FragmentFilter = object.filter;
var mask:DisplayObject = object.mask;
painter.cacheEnabled = false;
painter.pushState();
state.alpha = object.alpha * alpha;
state.setModelviewMatricesToIdentity();
state.blendMode = object.blendMode == BlendMode.AUTO ?
BlendMode.NORMAL : object.blendMode;
if (matrix) state.transformModelviewMatrix(matrix);
else state.transformModelviewMatrix(object.transformationMatrix);
if (mask) painter.drawMask(mask);
if (filter) filter.render(painter);
else object.render(painter);
if (mask) painter.eraseMask(mask);
painter.popState();
painter.cacheEnabled = wasCacheEnabled;
}
private function renderBundled(renderBlock:Function, object:DisplayObject=null,
matrix:Matrix=null, alpha:Number=1.0,
antiAliasing:int=0):void
{
var painter:Painter = Starling.painter;
var state:RenderState = painter.state;
if (!Starling.current.contextValid) return;
// switch buffers
if (isDoubleBuffered)
{
var tmpTexture:Texture = _activeTexture;
_activeTexture = _bufferTexture;
_bufferTexture = tmpTexture;
_helperImage.texture = _bufferTexture;
}
painter.pushState();
var rootTexture:Texture = _activeTexture.root;
state.setProjectionMatrix(0, 0, rootTexture.width, rootTexture.height, width, height);
// limit drawing to relevant area
sClipRect.setTo(0, 0, _activeTexture.width, _activeTexture.height);
state.clipRect = sClipRect;
state.setRenderTarget(_activeTexture, true, antiAliasing);
painter.prepareToDraw();
if (isDoubleBuffered || !isPersistent || !_bufferReady)
painter.clear();
// draw buffer
if (isDoubleBuffered && _bufferReady)
_helperImage.render(painter);
else
_bufferReady = true;
try
{
_drawing = true;
execute(renderBlock, object, matrix, alpha);
}
finally
{
_drawing = false;
painter.popState();
}
}
/** Clears the render texture with a certain color and alpha value. Call without any
* arguments to restore full transparency. */
public function clear(color:uint=0, alpha:Number=0.0):void
{
_activeTexture.root.clear(color, alpha);
_bufferReady = true;
}
// properties
/** Indicates if the render texture is using double buffering. This might be necessary for
* persistent textures, depending on the runtime version and the value of
* 'forceDoubleBuffering'. */
private function get isDoubleBuffered():Boolean { return _bufferTexture != null; }
/** Indicates if the texture is persistent over multiple draw calls. */
public function get isPersistent():Boolean { return _isPersistent; }
/** @inheritDoc */
public override function get base():TextureBase { return _activeTexture.base; }
/** @inheritDoc */
public override function get root():ConcreteTexture { return _activeTexture.root; }
/** Indicates if new persistent textures should use double buffering. Single buffering
* is faster and requires less memory, but is not supported on all hardware.
*
* <p>By default, applications running with the profile "baseline" or "baselineConstrained"
* will use double buffering; all others use just a single buffer. You can override this
* behavior, though, by assigning a different value at runtime.</p>
*
* @default true for "baseline" and "baselineConstrained", false otherwise
*/
public static function get useDoubleBuffering():Boolean
{
if (Starling.current)
{
var painter:Painter = Starling.painter;
var sharedData:Dictionary = painter.sharedData;
if (USE_DOUBLE_BUFFERING_DATA_NAME in sharedData)
{
return sharedData[USE_DOUBLE_BUFFERING_DATA_NAME];
}
else
{
var profile:String = painter.profile ? painter.profile : "baseline";
var value:Boolean = profile == "baseline" || profile == "baselineConstrained";
sharedData[USE_DOUBLE_BUFFERING_DATA_NAME] = value;
return value;
}
}
else return false;
}
public static function set useDoubleBuffering(value:Boolean):void
{
if (Starling.current == null)
throw new IllegalOperationError("Starling not yet initialized");
else
Starling.painter.sharedData[USE_DOUBLE_BUFFERING_DATA_NAME] = value;
}
}
}

View File

@@ -0,0 +1,183 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display3D.textures.TextureBase;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import starling.core.starling_internal;
/** A SubTexture represents a section of another texture. This is achieved solely by
* manipulation of texture coordinates, making the class very efficient.
*
* <p><em>Note that it is OK to create subtextures of subtextures.</em></p>
*/
public class SubTexture extends Texture
{
private var _parent:Texture;
private var _ownsParent:Boolean;
private var _region:Rectangle;
private var _frame:Rectangle;
private var _rotated:Boolean;
private var _width:Number;
private var _height:Number;
private var _scale:Number;
private var _transformationMatrix:Matrix;
private var _transformationMatrixToRoot:Matrix;
/** Creates a new SubTexture containing the specified region of a parent texture.
*
* @param parent The texture you want to create a SubTexture from.
* @param region The region of the parent texture that the SubTexture will show
* (in points). If <code>null</code>, the complete area of the parent.
* @param ownsParent If <code>true</code>, the parent texture will be disposed
* automatically when the SubTexture is disposed.
* @param frame If the texture was trimmed, the frame rectangle can be used to restore
* the trimmed area.
* @param rotated If true, the SubTexture will show the parent region rotated by
* 90 degrees (CCW).
* @param scaleModifier The scale factor of the SubTexture will be calculated by
* multiplying the parent texture's scale factor with this value.
*/
public function SubTexture(parent:Texture, region:Rectangle=null,
ownsParent:Boolean=false, frame:Rectangle=null,
rotated:Boolean=false, scaleModifier:Number=1)
{
starling_internal::setTo(parent, region, ownsParent, frame, rotated, scaleModifier);
}
/** @private
*
* <p>Textures are supposed to be immutable, and Starling uses this assumption for
* optimizations and simplifications all over the place. However, in some situations where
* the texture is not accessible to the outside, this can be overruled in order to avoid
* allocations.</p>
*/
starling_internal function setTo(parent:Texture, region:Rectangle=null,
ownsParent:Boolean=false, frame:Rectangle=null,
rotated:Boolean=false, scaleModifier:Number=1):void
{
if (_region == null) _region = new Rectangle();
if (region) _region.copyFrom(region);
else _region.setTo(0, 0, parent.width, parent.height);
if (frame)
{
if (_frame) _frame.copyFrom(frame);
else _frame = frame.clone();
}
else _frame = null;
_parent = parent;
_ownsParent = ownsParent;
_rotated = rotated;
_width = (rotated ? _region.height : _region.width) / scaleModifier;
_height = (rotated ? _region.width : _region.height) / scaleModifier;
_scale = _parent.scale * scaleModifier;
if (_frame && (_frame.x > 0 || _frame.y > 0 ||
_frame.right < _width || _frame.bottom < _height))
{
trace("[Starling] Warning: frames inside the texture's region are unsupported.");
}
updateMatrices();
}
private function updateMatrices():void
{
if (_transformationMatrix) _transformationMatrix.identity();
else _transformationMatrix = new Matrix();
if (_transformationMatrixToRoot) _transformationMatrixToRoot.identity();
else _transformationMatrixToRoot = new Matrix();
if (_rotated)
{
_transformationMatrix.translate(0, -1);
_transformationMatrix.rotate(Math.PI / 2.0);
}
_transformationMatrix.scale(_region.width / _parent.width,
_region.height / _parent.height);
_transformationMatrix.translate(_region.x / _parent.width,
_region.y / _parent.height);
var texture:SubTexture = this;
while (texture)
{
_transformationMatrixToRoot.concat(texture._transformationMatrix);
texture = texture.parent as SubTexture;
}
}
/** Disposes the parent texture if this texture owns it. */
public override function dispose():void
{
if (_ownsParent) _parent.dispose();
super.dispose();
}
/** The texture which the SubTexture is based on. */
public function get parent():Texture { return _parent; }
/** Indicates if the parent texture is disposed when this object is disposed. */
public function get ownsParent():Boolean { return _ownsParent; }
/** If true, the SubTexture will show the parent region rotated by 90 degrees (CCW). */
public function get rotated():Boolean { return _rotated; }
/** The region of the parent texture that the SubTexture is showing (in points).
*
* <p>CAUTION: not a copy, but the actual object! Do not modify!</p> */
public function get region():Rectangle { return _region; }
/** @inheritDoc */
public override function get transformationMatrix():Matrix { return _transformationMatrix; }
/** @inheritDoc */
public override function get transformationMatrixToRoot():Matrix { return _transformationMatrixToRoot; }
/** @inheritDoc */
public override function get base():TextureBase { return _parent.base; }
/** @inheritDoc */
public override function get root():ConcreteTexture { return _parent.root; }
/** @inheritDoc */
public override function get format():String { return _parent.format; }
/** @inheritDoc */
public override function get width():Number { return _width; }
/** @inheritDoc */
public override function get height():Number { return _height; }
/** @inheritDoc */
public override function get nativeWidth():Number { return _width * _scale; }
/** @inheritDoc */
public override function get nativeHeight():Number { return _height * _scale; }
/** @inheritDoc */
public override function get mipMapping():Boolean { return _parent.mipMapping; }
/** @inheritDoc */
public override function get premultipliedAlpha():Boolean { return _parent.premultipliedAlpha; }
/** @inheritDoc */
public override function get scale():Number { return _scale; }
/** @inheritDoc */
public override function get frame():Rectangle { return _frame; }
}
}

View File

@@ -0,0 +1,753 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display3D.Context3D;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.textures.RectangleTexture;
import flash.display3D.textures.TextureBase;
import flash.display3D.textures.VideoTexture;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Camera;
import flash.net.NetStream;
import flash.system.Capabilities;
import flash.utils.ByteArray;
import flash.utils.getQualifiedClassName;
import starling.core.Starling;
import starling.errors.AbstractClassError;
import starling.errors.MissingContextError;
import starling.errors.NotSupportedError;
import starling.rendering.VertexData;
import starling.utils.MathUtil;
import starling.utils.MatrixUtil;
import starling.utils.SystemUtil;
/** <p>A texture stores the information that represents an image. It cannot be added to the
* display list directly; instead it has to be mapped onto a display object. In Starling,
* the most probably candidate for this job is the <code>Image</code> class.</p>
*
* <strong>Creating a texture</strong>
*
* <p>The <code>Texture</code> class is abstract, i.e. you cannot create instance of this
* class through its constructor. Instead, it offers a variety of factory methods, like
* <code>fromBitmapData</code> or <code>fromEmbeddedAsset</code>.</p>
*
* <strong>Texture Formats</strong>
*
* <p>Since textures can be created from a "BitmapData" object, Starling supports any bitmap
* format that is supported by Flash. And since you can render any Flash display object into
* a BitmapData object, you can use this to display non-Starling content in Starling - e.g.
* Shape objects.</p>
*
* <p>Starling also supports ATF textures (Adobe Texture Format), which is a container for
* compressed texture formats that can be rendered very efficiently by the GPU. Refer to
* the Flash documentation for more information about this format.</p>
*
* <p>Beginning with AIR 17, you can use Starling textures to show video content (if the
* current platform supports it; see "SystemUtil.supportsVideoTexture").
* The two factory methods "fromCamera" and "fromNetStream" allow you to make use of
* this feature.</p>
*
* <strong>Mip Mapping</strong>
*
* <p>MipMaps are scaled down versions of a texture. When an image is displayed smaller than
* its natural size, the GPU may display the mip maps instead of the original texture. This
* reduces aliasing and accelerates rendering. It does, however, also need additional memory;
* for that reason, mipmapping is disabled by default.</p>
*
* <strong>Texture Frame</strong>
*
* <p>The frame property of a texture allows you to let a texture appear inside the bounds of
* an image, leaving a transparent border around the texture. The frame rectangle is specified
* in the coordinate system of the texture (not the image):</p>
*
* <listing>
* var frame:Rectangle = new Rectangle(-10, -10, 30, 30);
* var texture:Texture = Texture.fromTexture(anotherTexture, null, frame);
* var image:Image = new Image(texture);</listing>
*
* <p>This code would create an image with a size of 30x30, with the texture placed at
* <code>x=10, y=10</code> within that image (assuming that 'anotherTexture' has a width and
* height of 10 pixels, it would appear in the middle of the image).</p>
*
* <p>The texture atlas makes use of this feature, as it allows to crop transparent edges
* of a texture and making up for the changed size by specifying the original texture frame.
* Tools like <a href="http://www.texturepacker.com/">TexturePacker</a> use this to
* optimize the atlas.</p>
*
* <strong>Texture Coordinates</strong>
*
* <p>If, on the other hand, you want to show only a part of the texture in an image
* (i.e. to crop the the texture), you can either create a subtexture (with the method
* 'Texture.fromTexture()' and specifying a rectangle for the region), or you can manipulate
* the texture coordinates of the image object. The method <code>image.setTexCoords</code>
* allows you to do that.</p>
*
* <strong>Context Loss</strong>
*
* <p>When the current rendering context is lost (which can happen on all platforms, but is
* especially common on Android and Windows), all texture data is destroyed. However,
* Starling will try to restore the textures. To do that, it will keep the bitmap
* and ATF data in memory - at the price of increased RAM consumption. You can optimize
* this behavior, though, by restoring the texture directly from its source, like in this
* example:</p>
*
* <listing>
* var texture:Texture = Texture.fromBitmap(new EmbeddedBitmap());
* texture.root.onRestore = function():void
* {
* texture.root.uploadFromBitmap(new EmbeddedBitmap());
* };</listing>
*
* <p>The <code>onRestore</code>-method will be called when the context was lost and the
* texture has been recreated (but is still empty). If you use the "AssetManager" class to
* manage your textures, this will be done automatically.</p>
*
* @see starling.display.Image
* @see starling.utils.AssetManager
* @see starling.utils.SystemUtil
* @see TextureAtlas
*/
public class Texture
{
// helper objects
private static var sDefaultOptions:TextureOptions = new TextureOptions();
private static var sRectangle:Rectangle = new Rectangle();
private static var sMatrix:Matrix = new Matrix();
private static var sPoint:Point = new Point();
/** @private */
public function Texture()
{
if (Capabilities.isDebugger &&
getQualifiedClassName(this) == "starling.textures::Texture")
{
throw new AbstractClassError();
}
}
/** Disposes the underlying texture data. Note that not all textures need to be disposed:
* SubTextures (created with 'Texture.fromTexture') just reference other textures and
* and do not take up resources themselves; this is also true for textures from an
* atlas. */
public function dispose():void
{
// override in subclasses
}
/** Creates a texture from any of the supported data types, using the specified options.
*
* @param data Either an embedded asset class, a Bitmap, BitmapData, or a ByteArray
* with ATF data.
* @param options Specifies options about the texture settings, e.g. the scale factor.
* If left empty, the default options will be used.
*/
public static function fromData(data:Object, options:TextureOptions=null):Texture
{
if (data is Bitmap) data = (data as Bitmap).bitmapData;
if (options == null) options = sDefaultOptions;
if (data is Class)
{
return fromEmbeddedAsset(data as Class,
options.mipMapping, options.optimizeForRenderToTexture,
options.scale, options.format, options.forcePotTexture);
}
else if (data is BitmapData)
{
return fromBitmapData(data as BitmapData,
options.mipMapping, options.optimizeForRenderToTexture,
options.scale, options.format, options.forcePotTexture);
}
else if (data is ByteArray)
{
return fromAtfData(data as ByteArray,
options.scale, options.mipMapping, options.onReady);
}
else
throw new ArgumentError("Unsupported 'data' type: " + getQualifiedClassName(data));
}
/** Creates a texture from a <code>TextureBase</code> object.
*
* @param base a Stage3D texture object created through the current context.
* @param width the width of the texture in pixels (not points!).
* @param height the height of the texture in pixels (not points!).
* @param options specifies options about the texture settings, e.g. the scale factor.
* If left empty, the default options will be used. Note that not all
* options are supported by all texture types.
*/
public static function fromTextureBase(base:TextureBase, width:int, height:int,
options:TextureOptions=null):ConcreteTexture
{
if (options == null) options = sDefaultOptions;
if (base is flash.display3D.textures.Texture)
{
return new ConcretePotTexture(base as flash.display3D.textures.Texture,
options.format, width, height, options.mipMapping,
options.premultipliedAlpha, options.optimizeForRenderToTexture,
options.scale);
}
else if (base is RectangleTexture)
{
return new ConcreteRectangleTexture(base as RectangleTexture,
options.format, width, height, options.premultipliedAlpha,
options.optimizeForRenderToTexture, options.scale);
}
else if (base is VideoTexture)
{
return new ConcreteVideoTexture(base as VideoTexture, options.scale);
}
else
throw new ArgumentError("Unsupported 'base' type: " + getQualifiedClassName(base));
}
/** Creates a texture object from an embedded asset class. Textures created with this
* method will be restored directly from the asset class in case of a context loss,
* which guarantees a very economic memory usage.
*
* @param assetClass must contain either a Bitmap or a ByteArray with ATF data.
* @param mipMapping for Bitmaps, indicates if mipMaps will be created;
* for ATF data, indicates if the contained mipMaps will be used.
* @param optimizeForRenderToTexture indicates if this texture will be used as
* render target.
* @param scale the scale factor of the created texture.
* @param format the context3D texture format to use. Ignored for ATF data.
* @param forcePotTexture indicates if the underlying Stage3D texture should be created
* as the power-of-two based "Texture" class instead of the more memory
* efficient "RectangleTexture". (Only applicable to bitmaps; ATF
* textures are always POT-textures, anyway.)
*/
public static function fromEmbeddedAsset(assetClass:Class, mipMapping:Boolean=false,
optimizeForRenderToTexture:Boolean=false,
scale:Number=1, format:String="bgra",
forcePotTexture:Boolean=false):Texture
{
var texture:Texture;
var asset:Object = new assetClass();
if (asset is Bitmap)
{
texture = Texture.fromBitmap(asset as Bitmap, mipMapping,
optimizeForRenderToTexture, scale, format, forcePotTexture);
texture.root.onRestore = function():void
{
texture.root.uploadBitmap(new assetClass());
};
}
else if (asset is ByteArray)
{
texture = Texture.fromAtfData(asset as ByteArray, scale, mipMapping, null);
texture.root.onRestore = function():void
{
texture.root.uploadAtfData(new assetClass());
};
}
else
{
throw new ArgumentError("Invalid asset type: " + getQualifiedClassName(asset));
}
asset = null; // avoid that object stays in memory (through 'onRestore' functions)
return texture;
}
/** Creates a texture object from a bitmap.
* Beware: you must not dispose the bitmap's data if Starling should handle a lost device
* context alternatively, you can handle restoration yourself via "texture.root.onRestore".
*
* @param bitmap the texture will be created with the bitmap data of this object.
* @param generateMipMaps indicates if mipMaps will be created.
* @param optimizeForRenderToTexture indicates if this texture will be used as
* render target
* @param scale the scale factor of the created texture. This affects the reported
* width and height of the texture object.
* @param format the context3D texture format to use. Pass one of the packed or
* compressed formats to save memory (at the price of reduced image
* quality).
* @param forcePotTexture indicates if the underlying Stage3D texture should be created
* as the power-of-two based "Texture" class instead of the more memory
* efficient "RectangleTexture".
*/
public static function fromBitmap(bitmap:Bitmap, generateMipMaps:Boolean=false,
optimizeForRenderToTexture:Boolean=false,
scale:Number=1, format:String="bgra",
forcePotTexture:Boolean=false):Texture
{
return fromBitmapData(bitmap.bitmapData, generateMipMaps, optimizeForRenderToTexture,
scale, format, forcePotTexture);
}
/** Creates a texture object from bitmap data.
* Beware: you must not dispose 'data' if Starling should handle a lost device context;
* alternatively, you can handle restoration yourself via "texture.root.onRestore".
*
* @param data the bitmap data to upload to the texture.
* @param generateMipMaps indicates if mipMaps will be created.
* @param optimizeForRenderToTexture indicates if this texture will be used as
* render target
* @param scale the scale factor of the created texture. This affects the reported
* width and height of the texture object.
* @param format the context3D texture format to use. Pass one of the packed or
* compressed formats to save memory (at the price of reduced image
* quality).
* @param forcePotTexture indicates if the underlying Stage3D texture should be created
* as the power-of-two based "Texture" class instead of the more memory
* efficient "RectangleTexture".
*/
public static function fromBitmapData(data:BitmapData, generateMipMaps:Boolean=false,
optimizeForRenderToTexture:Boolean=false,
scale:Number=1, format:String="bgra",
forcePotTexture:Boolean=false):Texture
{
var texture:Texture = Texture.empty(data.width / scale, data.height / scale, true,
generateMipMaps, optimizeForRenderToTexture, scale,
format, forcePotTexture);
texture.root.uploadBitmapData(data);
texture.root.onRestore = function():void
{
texture.root.uploadBitmapData(data);
};
return texture;
}
/** Creates a texture from ATF data (Adobe Texture Compression).
* Beware: you must not dispose 'data' if Starling should handle a lost device context;
* alternatively, you can handle restoration yourself via "texture.root.onRestore".
*
* @param data the raw data from an ATF file.
* @param scale the scale factor of the created texture. This affects the reported
* width and height of the texture object.
* @param useMipMaps If the ATF data contains mipmaps, this parameter controls if they
* are used; if it does not, this parameter has no effect.
* @param async If you pass a callback function, the texture will be decoded
* asynchronously, which allows a smooth framerate even during the
* loading process. However, don't use the texture before the callback
* has been executed. This is the expected function definition:
* <code>function(texture:Texture):void;</code>
* @param premultipliedAlpha Indicates if the ATF data contains pixels in PMA format.
* This is "false" for most ATF files, but can be customized in some
* tools.
*/
public static function fromAtfData(data:ByteArray, scale:Number=1, useMipMaps:Boolean=true,
async:Function=null, premultipliedAlpha:Boolean=false):Texture
{
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
var atfData:AtfData = new AtfData(data);
var nativeTexture:flash.display3D.textures.Texture = context.createTexture(
atfData.width, atfData.height, atfData.format, false);
var concreteTexture:ConcreteTexture = new ConcretePotTexture(nativeTexture,
atfData.format, atfData.width, atfData.height, useMipMaps && atfData.numTextures > 1,
premultipliedAlpha, false, scale);
concreteTexture.uploadAtfData(data, 0, async);
concreteTexture.onRestore = function():void
{
concreteTexture.uploadAtfData(data, 0);
};
return concreteTexture;
}
/** Creates a video texture from a NetStream.
*
* <p>Below, you'll find a minimal sample showing how to stream a video from a file.
* Note that <code>ns.play()</code> is called only after creating the texture, and
* outside the <code>onComplete</code>-callback. It's recommended to always make the
* calls in this order; otherwise, playback won't start on some platforms.</p>
*
* <listing>
* var nc:NetConnection = new NetConnection();
* nc.connect(null);
*
* var ns:NetStream = new NetStream(nc);
* var texture:Texture = Texture.fromNetStream(ns, 1, function():void
* {
* addChild(new Image(texture));
* });
*
* var file:File = File.applicationDirectory.resolvePath("bugs-bunny.m4v");
* ns.play(file.url);</listing>
*
* @param stream the NetStream from which the video data is streamed. Beware that 'play'
* should be called only after the method returns, and outside the
* <code>onComplete</code> callback.
* @param scale the scale factor of the created texture. This affects the reported
* width and height of the texture object.
* @param onComplete will be executed when the texture is ready. Contains a parameter
* of type 'Texture'.
*/
public static function fromNetStream(stream:NetStream, scale:Number=1,
onComplete:Function=null):Texture
{
// workaround for bug in NetStream class:
if (stream.client == stream && !("onMetaData" in stream))
stream.client = { onMetaData: function(md:Object):void {} };
return fromVideoAttachment("NetStream", stream, scale, onComplete);
}
/** Creates a video texture from a camera. Beware that the texture must not be used
* before the 'onComplete' callback has been executed; until then, it will have a size
* of zero pixels.
*
* <p>Here is a minimal sample showing how to display a camera video:</p>
*
* <listing>
* var camera:Camera = Camera.getCamera();
* var texture:Texture = Texture.fromCamera(camera, 1, function():void
* {
* addChild(new Image(texture));
* });</listing>
*
* @param camera the camera from which the video data is streamed.
* @param scale the scale factor of the created texture. This affects the reported
* width and height of the texture object.
* @param onComplete will be executed when the texture is ready. May contain a parameter
* of type 'Texture'.
*/
public static function fromCamera(camera:Camera, scale:Number=1,
onComplete:Function=null):Texture
{
return fromVideoAttachment("Camera", camera, scale, onComplete);
}
private static function fromVideoAttachment(type:String, attachment:Object,
scale:Number, onComplete:Function):Texture
{
if (!SystemUtil.supportsVideoTexture)
throw new NotSupportedError("Video Textures are not supported on this platform");
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
var base:VideoTexture = context.createVideoTexture();
var texture:ConcreteTexture = new ConcreteVideoTexture(base, scale);
texture.attachVideo(type, attachment, onComplete);
texture.onRestore = function():void
{
texture.root.attachVideo(type, attachment);
};
return texture;
}
/** Creates a texture with a certain size and color.
*
* @param width in points; number of pixels depends on scale parameter
* @param height in points; number of pixels depends on scale parameter
* @param color the RGB color the texture will be filled up
* @param alpha the alpha value that will be used for every pixel
* @param optimizeForRenderToTexture indicates if this texture will be used as render target
* @param scale if you omit this parameter, 'Starling.contentScaleFactor' will be used.
* @param format the context3D texture format to use. Pass one of the packed or
* compressed formats to save memory.
* @param forcePotTexture indicates if the underlying Stage3D texture should be created
* as the power-of-two based "Texture" class instead of the more memory
* efficient "RectangleTexture".
*/
public static function fromColor(width:Number, height:Number,
color:uint=0xffffff, alpha:Number=1.0,
optimizeForRenderToTexture:Boolean=false,
scale:Number=-1, format:String="bgra",
forcePotTexture:Boolean=false):Texture
{
var texture:Texture = Texture.empty(width, height, true, false,
optimizeForRenderToTexture, scale, format, forcePotTexture);
texture.root.clear(color, alpha);
texture.root.onRestore = function():void
{
texture.root.clear(color, alpha);
};
return texture;
}
/** Creates an empty texture of a certain size.
* Beware that the texture can only be used after you either upload some color data
* ("texture.root.upload...") or clear the texture ("texture.root.clear()").
*
* @param width in points; number of pixels depends on scale parameter
* @param height in points; number of pixels depends on scale parameter
* @param premultipliedAlpha the PMA format you will use the texture with. If you will
* use the texture for bitmap data, use "true"; for ATF data, use "false".
* @param mipMapping indicates if mipmaps should be used for this texture. When you upload
* bitmap data, this decides if mipmaps will be created; when you upload ATF
* data, this decides if mipmaps inside the ATF file will be displayed.
* @param optimizeForRenderToTexture indicates if this texture will be used as render target
* @param scale if you omit this parameter, 'Starling.contentScaleFactor' will be used.
* @param format the context3D texture format to use. Pass one of the packed or
* compressed formats to save memory (at the price of reduced image quality).
* @param forcePotTexture indicates if the underlying Stage3D texture should be created
* as the power-of-two based "Texture" class instead of the more memory
* efficient "RectangleTexture".
*/
public static function empty(width:Number, height:Number, premultipliedAlpha:Boolean=true,
mipMapping:Boolean=false, optimizeForRenderToTexture:Boolean=false,
scale:Number=-1, format:String="bgra",
forcePotTexture:Boolean=false):Texture
{
if (scale <= 0) scale = Starling.contentScaleFactor;
var actualWidth:int, actualHeight:int;
var nativeTexture:TextureBase;
var concreteTexture:ConcreteTexture;
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
var origWidth:Number = width * scale;
var origHeight:Number = height * scale;
var useRectTexture:Boolean = !forcePotTexture && !mipMapping &&
Starling.current.profile != "baselineConstrained" &&
format.indexOf("compressed") == -1;
if (useRectTexture)
{
actualWidth = Math.ceil(origWidth - 0.000000001); // avoid floating point errors
actualHeight = Math.ceil(origHeight - 0.000000001);
nativeTexture = context.createRectangleTexture(
actualWidth, actualHeight, format, optimizeForRenderToTexture);
concreteTexture = new ConcreteRectangleTexture(
nativeTexture as RectangleTexture, format, actualWidth, actualHeight,
premultipliedAlpha, optimizeForRenderToTexture, scale);
}
else
{
actualWidth = MathUtil.getNextPowerOfTwo(origWidth);
actualHeight = MathUtil.getNextPowerOfTwo(origHeight);
nativeTexture = context.createTexture(
actualWidth, actualHeight, format, optimizeForRenderToTexture);
concreteTexture = new ConcretePotTexture(
nativeTexture as flash.display3D.textures.Texture, format,
actualWidth, actualHeight, mipMapping, premultipliedAlpha,
optimizeForRenderToTexture, scale);
}
concreteTexture.onRestore = concreteTexture.clear;
if (actualWidth - origWidth < 0.001 && actualHeight - origHeight < 0.001)
return concreteTexture;
else
return new SubTexture(concreteTexture, new Rectangle(0, 0, width, height), true);
}
/** Creates a texture that contains a region (in pixels) of another texture. The new
* texture will reference the base texture; no data is duplicated.
*
* @param texture The texture you want to create a SubTexture from.
* @param region The region of the parent texture that the SubTexture will show
* (in points).
* @param frame If the texture was trimmed, the frame rectangle can be used to restore
* the trimmed area.
* @param rotated If true, the SubTexture will show the parent region rotated by
* 90 degrees (CCW).
* @param scaleModifier The scale factor of the new texture will be calculated by
* multiplying the parent texture's scale factor with this value.
*/
public static function fromTexture(texture:Texture, region:Rectangle=null,
frame:Rectangle=null, rotated:Boolean=false,
scaleModifier:Number=1.0):Texture
{
return new SubTexture(texture, region, false, frame, rotated, scaleModifier);
}
/** Sets up a VertexData instance with the correct positions for 4 vertices so that
* the texture can be mapped onto it unscaled. If the texture has a <code>frame</code>,
* the vertices will be offset accordingly.
*
* @param vertexData the VertexData instance to which the positions will be written.
* @param vertexID the start position within the VertexData instance.
* @param attrName the attribute name referencing the vertex positions.
* @param bounds useful only for textures with a frame. This will position the
* vertices at the correct position within the given bounds,
* distorted appropriately.
*/
public function setupVertexPositions(vertexData:VertexData, vertexID:int=0,
attrName:String="position",
bounds:Rectangle=null):void
{
var frame:Rectangle = this.frame;
var width:Number = this.width;
var height:Number = this.height;
if (frame)
sRectangle.setTo(-frame.x, -frame.y, width, height);
else
sRectangle.setTo(0, 0, width, height);
vertexData.setPoint(vertexID, attrName, sRectangle.left, sRectangle.top);
vertexData.setPoint(vertexID + 1, attrName, sRectangle.right, sRectangle.top);
vertexData.setPoint(vertexID + 2, attrName, sRectangle.left, sRectangle.bottom);
vertexData.setPoint(vertexID + 3, attrName, sRectangle.right, sRectangle.bottom);
if (bounds)
{
var scaleX:Number = bounds.width / frameWidth;
var scaleY:Number = bounds.height / frameHeight;
if (scaleX != 1.0 || scaleY != 1.0 || bounds.x != 0 || bounds.y != 0)
{
sMatrix.identity();
sMatrix.scale(scaleX, scaleY);
sMatrix.translate(bounds.x, bounds.y);
vertexData.transformPoints(attrName, sMatrix, vertexID, 4);
}
}
}
/** Sets up a VertexData instance with the correct texture coordinates for
* 4 vertices so that the texture is mapped to the complete quad.
*
* @param vertexData the vertex data to which the texture coordinates will be written.
* @param vertexID the start position within the VertexData instance.
* @param attrName the attribute name referencing the vertex positions.
*/
public function setupTextureCoordinates(vertexData:VertexData, vertexID:int=0,
attrName:String="texCoords"):void
{
setTexCoords(vertexData, vertexID , attrName, 0.0, 0.0);
setTexCoords(vertexData, vertexID + 1, attrName, 1.0, 0.0);
setTexCoords(vertexData, vertexID + 2, attrName, 0.0, 1.0);
setTexCoords(vertexData, vertexID + 3, attrName, 1.0, 1.0);
}
/** Transforms the given texture coordinates from the local coordinate system
* into the root texture's coordinate system. */
public function localToGlobal(u:Number, v:Number, out:Point=null):Point
{
if (out == null) out = new Point();
if (this == root) out.setTo(u, v);
else MatrixUtil.transformCoords(transformationMatrixToRoot, u, v, out);
return out;
}
/** Transforms the given texture coordinates from the root texture's coordinate system
* to the local coordinate system. */
public function globalToLocal(u:Number, v:Number, out:Point=null):Point
{
if (out == null) out = new Point();
if (this == root) out.setTo(u, v);
else
{
sMatrix.identity();
sMatrix.copyFrom(transformationMatrixToRoot);
sMatrix.invert();
MatrixUtil.transformCoords(sMatrix, u, v, out);
}
return out;
}
/** Writes the given texture coordinates to a VertexData instance after transforming
* them into the root texture's coordinate system. That way, the texture coordinates
* can be used directly to sample the texture in the fragment shader. */
public function setTexCoords(vertexData:VertexData, vertexID:int, attrName:String,
u:Number, v:Number):void
{
localToGlobal(u, v, sPoint);
vertexData.setPoint(vertexID, attrName, sPoint.x, sPoint.y);
}
/** Reads a pair of texture coordinates from the given VertexData instance and transforms
* them into the current texture's coordinate system. (Remember, the VertexData instance
* will always contain the coordinates in the root texture's coordinate system!) */
public function getTexCoords(vertexData:VertexData, vertexID:int,
attrName:String="texCoords", out:Point=null):Point
{
if (out == null) out = new Point();
vertexData.getPoint(vertexID, attrName, out);
return globalToLocal(out.x, out.y, out);
}
// properties
/** The texture frame if it has one (see class description), otherwise <code>null</code>.
* <p>CAUTION: not a copy, but the actual object! Do not modify!</p> */
public function get frame():Rectangle { return null; }
/** The height of the texture in points, taking into account the frame rectangle
* (if there is one). */
public function get frameWidth():Number { return frame ? frame.width : width; }
/** The width of the texture in points, taking into account the frame rectangle
* (if there is one). */
public function get frameHeight():Number { return frame ? frame.height : height; }
/** The width of the texture in points. */
public function get width():Number { return 0; }
/** The height of the texture in points. */
public function get height():Number { return 0; }
/** The width of the texture in pixels (without scale adjustment). */
public function get nativeWidth():Number { return 0; }
/** The height of the texture in pixels (without scale adjustment). */
public function get nativeHeight():Number { return 0; }
/** The scale factor, which influences width and height properties. */
public function get scale():Number { return 1.0; }
/** The Stage3D texture object the texture is based on. */
public function get base():TextureBase { return null; }
/** The concrete texture the texture is based on. */
public function get root():ConcreteTexture { return null; }
/** The <code>Context3DTextureFormat</code> of the underlying texture data. */
public function get format():String { return Context3DTextureFormat.BGRA; }
/** Indicates if the texture contains mip maps. */
public function get mipMapping():Boolean { return false; }
/** Indicates if the alpha values are premultiplied into the RGB values. */
public function get premultipliedAlpha():Boolean { return false; }
/** The matrix that is used to transform the texture coordinates into the coordinate
* space of the parent texture, if there is one. @default null
*
* <p>CAUTION: not a copy, but the actual object! Never modify this matrix!</p> */
public function get transformationMatrix():Matrix { return null; }
/** The matrix that is used to transform the texture coordinates into the coordinate
* space of the root texture, if this instance is not the root. @default null
*
* <p>CAUTION: not a copy, but the actual object! Never modify this matrix!</p> */
public function get transformationMatrixToRoot():Matrix { return null; }
/** Returns the maximum size constraint (for both width and height) for textures in the
* current Context3D profile. */
public static function get maxSize():int
{
var target:Starling = Starling.current;
var profile:String = target ? target.profile : "baseline";
if (profile == "baseline" || profile == "baselineConstrained")
return 2048;
else
return 4096;
}
}
}

View File

@@ -0,0 +1,221 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import starling.utils.StringUtil;
/** A texture atlas is a collection of many smaller textures in one big image. This class
* is used to access textures from such an atlas.
*
* <p>Using a texture atlas for your textures solves two problems:</p>
*
* <ul>
* <li>Whenever you switch between textures, the batching of image objects is disrupted.</li>
* <li>Any Stage3D texture has to have side lengths that are powers of two. Starling hides
* this limitation from you, but at the cost of additional graphics memory.</li>
* </ul>
*
* <p>By using a texture atlas, you avoid both texture switches and the power-of-two
* limitation. All textures are within one big "super-texture", and Starling takes care that
* the correct part of this texture is displayed.</p>
*
* <p>There are several ways to create a texture atlas. One is to use the atlas generator
* script that is bundled with Starling's sibling, the <a href="http://www.sparrow-framework.org">
* Sparrow framework</a>. It was only tested in Mac OS X, though. A great multi-platform
* alternative is the commercial tool <a href="http://www.texturepacker.com">
* Texture Packer</a>.</p>
*
* <p>Whatever tool you use, Starling expects the following file format:</p>
*
* <listing>
* &lt;TextureAtlas imagePath='atlas.png'&gt;
* &lt;SubTexture name='texture_1' x='0' y='0' width='50' height='50'/&gt;
* &lt;SubTexture name='texture_2' x='50' y='0' width='20' height='30'/&gt;
* &lt;/TextureAtlas&gt;
* </listing>
*
* <strong>Texture Frame</strong>
*
* <p>If your images have transparent areas at their edges, you can make use of the
* <code>frame</code> property of the Texture class. Trim the texture by removing the
* transparent edges and specify the original texture size like this:</p>
*
* <listing>
* &lt;SubTexture name='trimmed' x='0' y='0' height='10' width='10'
* frameX='-10' frameY='-10' frameWidth='30' frameHeight='30'/&gt;
* </listing>
*
* <strong>Texture Rotation</strong>
*
* <p>Some atlas generators can optionally rotate individual textures to optimize the texture
* distribution. This is supported via the boolean attribute "rotated". If it is set to
* <code>true</code> for a certain subtexture, this means that the texture on the atlas
* has been rotated by 90 degrees, clockwise. Starling will undo that rotation by rotating
* it counter-clockwise.</p>
*
* <p>In this case, the positional coordinates (<code>x, y, width, height</code>)
* are expected to point at the subtexture as it is present on the atlas (in its rotated
* form), while the "frame" properties must describe the texture in its upright form.</p>
*
*/
public class TextureAtlas
{
private var _atlasTexture:Texture;
private var _subTextures:Dictionary;
private var _subTextureNames:Vector.<String>;
/** helper objects */
private static var sNames:Vector.<String> = new <String>[];
/** Create a texture atlas from a texture by parsing the regions from an XML file. */
public function TextureAtlas(texture:Texture, atlasXml:XML=null)
{
_subTextures = new Dictionary();
_atlasTexture = texture;
if (atlasXml)
parseAtlasXml(atlasXml);
}
/** Disposes the atlas texture. */
public function dispose():void
{
_atlasTexture.dispose();
}
/** This function is called by the constructor and will parse an XML in Starling's
* default atlas file format. Override this method to create custom parsing logic
* (e.g. to support a different file format). */
protected function parseAtlasXml(atlasXml:XML):void
{
var scale:Number = _atlasTexture.scale;
var region:Rectangle = new Rectangle();
var frame:Rectangle = new Rectangle();
for each (var subTexture:XML in atlasXml.SubTexture)
{
var name:String = StringUtil.clean(subTexture.@name);
var x:Number = parseFloat(subTexture.@x) / scale;
var y:Number = parseFloat(subTexture.@y) / scale;
var width:Number = parseFloat(subTexture.@width) / scale;
var height:Number = parseFloat(subTexture.@height) / scale;
var frameX:Number = parseFloat(subTexture.@frameX) / scale;
var frameY:Number = parseFloat(subTexture.@frameY) / scale;
var frameWidth:Number = parseFloat(subTexture.@frameWidth) / scale;
var frameHeight:Number = parseFloat(subTexture.@frameHeight) / scale;
var rotated:Boolean = parseBool( subTexture.@rotated);
region.setTo(x, y, width, height);
frame.setTo(frameX, frameY, frameWidth, frameHeight);
if (frameWidth > 0 && frameHeight > 0)
addRegion(name, region, frame, rotated);
else
addRegion(name, region, null, rotated);
}
}
/** Retrieves a SubTexture by name. Returns <code>null</code> if it is not found. */
public function getTexture(name:String):Texture
{
return _subTextures[name];
}
/** Returns all textures that start with a certain string, sorted alphabetically
* (especially useful for "MovieClip"). */
public function getTextures(prefix:String="", out:Vector.<Texture>=null):Vector.<Texture>
{
if (out == null) out = new <Texture>[];
for each (var name:String in getNames(prefix, sNames))
out[out.length] = getTexture(name); // avoid 'push'
sNames.length = 0;
return out;
}
/** Returns all texture names that start with a certain string, sorted alphabetically. */
public function getNames(prefix:String="", out:Vector.<String>=null):Vector.<String>
{
var name:String;
if (out == null) out = new <String>[];
if (_subTextureNames == null)
{
// optimization: store sorted list of texture names
_subTextureNames = new <String>[];
for (name in _subTextures) _subTextureNames[_subTextureNames.length] = name;
_subTextureNames.sort(Array.CASEINSENSITIVE);
}
for each (name in _subTextureNames)
if (name.indexOf(prefix) == 0)
out[out.length] = name;
return out;
}
/** Returns the region rectangle associated with a specific name, or <code>null</code>
* if no region with that name has been registered. */
public function getRegion(name:String):Rectangle
{
var subTexture:SubTexture = _subTextures[name];
return subTexture ? subTexture.region : null;
}
/** Returns the frame rectangle of a specific region, or <code>null</code> if that region
* has no frame. */
public function getFrame(name:String):Rectangle
{
var subTexture:SubTexture = _subTextures[name];
return subTexture ? subTexture.frame : null;
}
/** If true, the specified region in the atlas is rotated by 90 degrees (clockwise). The
* SubTexture is thus rotated counter-clockwise to cancel out that transformation. */
public function getRotation(name:String):Boolean
{
var subTexture:SubTexture = _subTextures[name];
return subTexture ? subTexture.rotated : false;
}
/** Adds a named region for a SubTexture (described by rectangle with coordinates in
* points) with an optional frame. */
public function addRegion(name:String, region:Rectangle, frame:Rectangle=null,
rotated:Boolean=false):void
{
_subTextures[name] = new SubTexture(_atlasTexture, region, false, frame, rotated);
_subTextureNames = null;
}
/** Removes a region with a certain name. */
public function removeRegion(name:String):void
{
var subTexture:SubTexture = _subTextures[name];
if (subTexture) subTexture.dispose();
delete _subTextures[name];
_subTextureNames = null;
}
/** The base texture that makes up the atlas. */
public function get texture():Texture { return _atlasTexture; }
// utility methods
private static function parseBool(value:String):Boolean
{
return value.toLowerCase() == "true";
}
}
}

View File

@@ -0,0 +1,100 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import starling.core.Starling;
/** The TextureOptions class specifies options for loading textures with the
* <code>Texture.fromData</code> and <code>Texture.fromTextureBase</code> methods. */
public class TextureOptions
{
private var _scale:Number;
private var _format:String;
private var _mipMapping:Boolean;
private var _optimizeForRenderToTexture:Boolean = false;
private var _premultipliedAlpha:Boolean;
private var _forcePotTexture:Boolean;
private var _onReady:Function = null;
/** Creates a new instance with the given options. */
public function TextureOptions(scale:Number=1.0, mipMapping:Boolean=false,
format:String="bgra", premultipliedAlpha:Boolean=true,
forcePotTexture:Boolean=false)
{
_scale = scale;
_format = format;
_mipMapping = mipMapping;
_forcePotTexture = forcePotTexture;
_premultipliedAlpha = premultipliedAlpha;
}
/** Creates a clone of the TextureOptions object with the exact same properties. */
public function clone():TextureOptions
{
var clone:TextureOptions = new TextureOptions(_scale, _mipMapping, _format);
clone._optimizeForRenderToTexture = _optimizeForRenderToTexture;
clone._premultipliedAlpha = _premultipliedAlpha;
clone._forcePotTexture = _forcePotTexture;
clone._onReady = _onReady;
return clone;
}
/** The scale factor, which influences width and height properties. If you pass '-1',
* the current global content scale factor will be used. @default 1.0 */
public function get scale():Number { return _scale; }
public function set scale(value:Number):void
{
_scale = value > 0 ? value : Starling.contentScaleFactor;
}
/** The <code>Context3DTextureFormat</code> of the underlying texture data. Only used
* for textures that are created from Bitmaps; the format of ATF files is set when they
* are created. @default BGRA */
public function get format():String { return _format; }
public function set format(value:String):void { _format = value; }
/** Indicates if the texture contains mip maps. @default false */
public function get mipMapping():Boolean { return _mipMapping; }
public function set mipMapping(value:Boolean):void { _mipMapping = value; }
/** Indicates if the texture will be used as render target. */
public function get optimizeForRenderToTexture():Boolean { return _optimizeForRenderToTexture; }
public function set optimizeForRenderToTexture(value:Boolean):void { _optimizeForRenderToTexture = value; }
/** Indicates if the underlying Stage3D texture should be created as the power-of-two based
* <code>Texture</code> class instead of the more memory efficient <code>RectangleTexture</code>.
* That might be useful when you need to render the texture with wrap mode <code>repeat</code>.
* @default false */
public function get forcePotTexture():Boolean { return _forcePotTexture; }
public function set forcePotTexture(value:Boolean):void { _forcePotTexture = value; }
/** A callback that is used only for ATF textures; if it is set, the ATF data will be
* decoded asynchronously. The texture can only be used when the callback has been
* executed. This property is ignored for all other texture types (they are ready
* immediately when the 'Texture.from...' method returns, anyway), and it's only used
* by the <code>Texture.fromData</code> factory method.
*
* <p>This is the expected function definition:
* <code>function(texture:Texture):void;</code></p>
*
* @default null
*/
public function get onReady():Function { return _onReady; }
public function set onReady(value:Function):void { _onReady = value; }
/** Indicates if the alpha values are premultiplied into the RGB values. This is typically
* true for textures created from BitmapData and false for textures created from ATF data.
* This property will only be read by the <code>Texture.fromTextureBase</code> factory
* method. @default true */
public function get premultipliedAlpha():Boolean { return _premultipliedAlpha; }
public function set premultipliedAlpha(value:Boolean):void { _premultipliedAlpha = value; }
}
}

View File

@@ -0,0 +1,36 @@
// =================================================================================================
//
// Starling Framework
// Copyright Gamua GmbH. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import starling.errors.AbstractClassError;
/** A class that provides constant values for the possible smoothing algorithms of a texture. */
public class TextureSmoothing
{
/** @private */
public function TextureSmoothing() { throw new AbstractClassError(); }
/** No smoothing, also called "Nearest Neighbor". Pixels will scale up as big rectangles. */
public static const NONE:String = "none";
/** Bilinear filtering. Creates smooth transitions between pixels. */
public static const BILINEAR:String = "bilinear";
/** Trilinear filtering. Highest quality by taking the next mip map level into account. */
public static const TRILINEAR:String = "trilinear";
/** Determines whether a smoothing value is valid. */
public static function isValid(smoothing:String):Boolean
{
return smoothing == NONE || smoothing == BILINEAR || smoothing == TRILINEAR;
}
}
}