├── .gitignore ├── demo ├── assets │ ├── ui.png │ ├── openfl.png │ ├── background.jpg │ ├── blue_button.png │ ├── images │ │ ├── metalworks_mobile.png │ │ └── metalworks_mobile.xml │ ├── fonts │ │ ├── SourceSansPro-Regular.eot │ │ ├── SourceSansPro-Regular.ttf │ │ ├── SourceSansPro-Regular.woff │ │ ├── SourceSansPro-Semibold.eot │ │ ├── SourceSansPro-Semibold.ttf │ │ └── SourceSansPro-Semibold.woff │ ├── GrilledCheeseBTN_Size36_ColorFFFFFF.png │ ├── GrilledCheeseBTN_Size18_ColorFFFFFF_StrokeA8364B.png │ ├── GrilledCheeseBTN_Size36_ColorFFFFFF_StrokeA8364B.png │ ├── LobsterTwoRegular_Size54_ColorFFFFFF_StrokeAF384E_DropShadow560D1B.png │ ├── strings.json │ ├── movieclip_test.json │ ├── ui.xml │ ├── external_element_test.json │ ├── particle_test.json │ ├── localization_test.json │ ├── pixelmask_test.json │ ├── tween_test.json │ ├── mail_popup.json │ ├── mail_item.json │ └── connect_popup.json ├── src │ ├── feathers │ │ ├── utils │ │ │ ├── type │ │ │ │ ├── ArrayUtil.hx │ │ │ │ ├── SafeCast.hx │ │ │ │ ├── AcceptEither.hx │ │ │ │ ├── UnionMap.hx │ │ │ │ └── UnionWeakMap.hx │ │ │ ├── geom │ │ │ │ ├── matrixToRotation.hx │ │ │ │ ├── matrixToScaleX.hx │ │ │ │ ├── matrixToScaleY.hx │ │ │ │ └── FeathersMatrixUtil.hx │ │ │ ├── display │ │ │ │ ├── stageToStarling.hx │ │ │ │ ├── calculateScaleRatioToFill.hx │ │ │ │ ├── calculateScaleRatioToFit.hx │ │ │ │ ├── getDisplayObjectDepthFromStage.hx │ │ │ │ └── FeathersDisplayUtil.hx │ │ │ ├── math │ │ │ │ ├── roundToPrecision.hx │ │ │ │ ├── roundUpToNearest.hx │ │ │ │ ├── roundDownToNearest.hx │ │ │ │ ├── roundToNearest.hx │ │ │ │ ├── clamp.hx │ │ │ │ └── FeathersMathUtil.hx │ │ │ ├── text │ │ │ │ ├── TextInputNavigation.hx │ │ │ │ └── TextInputRestrict.hx │ │ │ └── ScreenDensityScaleFactorManager.hx │ │ ├── core │ │ │ ├── ITextBaselineControl.hx │ │ │ ├── IMultilineTextEditor.hx │ │ │ ├── INativeFocusOwner.hx │ │ │ ├── IFocusContainer.hx │ │ │ ├── IGroupedToggle.hx │ │ │ ├── IValidating.hx │ │ │ ├── IFocusManager.hx │ │ │ ├── ITextRenderer.hx │ │ │ ├── IToggle.hx │ │ │ ├── IFocusExtras.hx │ │ │ ├── IFeathersEventDispatcher.hx │ │ │ ├── ValidationQueue.hx │ │ │ ├── IFocusDisplayObject.hx │ │ │ └── IFeathersControl.hx │ │ ├── display │ │ │ └── RenderDelegate.hx │ │ └── textures │ │ │ └── Scale3Textures.hx │ └── starlingbuilder │ │ └── demo │ │ ├── AssetMediator.hx │ │ ├── ConnectPopup.hx │ │ ├── ParsedLayouts.hx │ │ ├── LayoutTest.hx │ │ ├── MailItemRenderer.hx │ │ ├── ExternalElementTest.hx │ │ ├── TweenTest.hx │ │ ├── LocalizationHandler.hx │ │ ├── Main.hx │ │ ├── MailPopup.hx │ │ ├── ContainerButtonPopup.hx │ │ ├── MovieClipTest.hx │ │ ├── AnchorLayoutTest.hx │ │ ├── HUD.hx │ │ └── LocalizationTest.hx ├── project.xml └── theme │ └── src │ └── feathers │ └── themes │ ├── MetalWorksMobileTheme.hx │ └── MetalWorksMobileThemeWithAssetManager.hx ├── src └── starlingbuilder │ └── engine │ ├── format │ ├── IDataFormatter.hx │ └── DefaultDataFormatter.hx │ ├── IDisplayObjectHandler.hx │ ├── localization │ ├── ILocalization.hx │ ├── ILocalizationHandler.hx │ ├── DefaultLocalizationHandler.hx │ └── DefaultLocalization.hx │ ├── DefaultAssetMediator.hx │ ├── util │ ├── ObjectLocaterUtil.hx │ └── StageUtil.hx │ ├── tween │ ├── ITweenBuilder.hx │ └── DefaultTweenBuilder.hx │ ├── IUIBuilder.hx │ ├── IAssetMediator.hx │ ├── LayoutLoader.hx │ └── UIElementFactory.hx ├── scaffold ├── project.xml ├── src │ ├── Main.hx │ └── Game.hx └── assets │ └── hello.json ├── README.md └── LICENSE.md /.gitignore: -------------------------------------------------------------------------------- 1 | demo/Export 2 | scaffold/Export 3 | out 4 | .idea -------------------------------------------------------------------------------- /demo/assets/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/ui.png -------------------------------------------------------------------------------- /demo/assets/openfl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/openfl.png -------------------------------------------------------------------------------- /demo/assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/background.jpg -------------------------------------------------------------------------------- /demo/assets/blue_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/blue_button.png -------------------------------------------------------------------------------- /demo/assets/images/metalworks_mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/images/metalworks_mobile.png -------------------------------------------------------------------------------- /demo/assets/fonts/SourceSansPro-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/fonts/SourceSansPro-Regular.eot -------------------------------------------------------------------------------- /demo/assets/fonts/SourceSansPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/fonts/SourceSansPro-Regular.ttf -------------------------------------------------------------------------------- /demo/assets/fonts/SourceSansPro-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/fonts/SourceSansPro-Regular.woff -------------------------------------------------------------------------------- /demo/assets/fonts/SourceSansPro-Semibold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/fonts/SourceSansPro-Semibold.eot -------------------------------------------------------------------------------- /demo/assets/fonts/SourceSansPro-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/fonts/SourceSansPro-Semibold.ttf -------------------------------------------------------------------------------- /demo/assets/fonts/SourceSansPro-Semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/fonts/SourceSansPro-Semibold.woff -------------------------------------------------------------------------------- /demo/assets/GrilledCheeseBTN_Size36_ColorFFFFFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/GrilledCheeseBTN_Size36_ColorFFFFFF.png -------------------------------------------------------------------------------- /demo/assets/GrilledCheeseBTN_Size18_ColorFFFFFF_StrokeA8364B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/GrilledCheeseBTN_Size18_ColorFFFFFF_StrokeA8364B.png -------------------------------------------------------------------------------- /demo/assets/GrilledCheeseBTN_Size36_ColorFFFFFF_StrokeA8364B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/GrilledCheeseBTN_Size36_ColorFFFFFF_StrokeA8364B.png -------------------------------------------------------------------------------- /demo/assets/LobsterTwoRegular_Size54_ColorFFFFFF_StrokeAF384E_DropShadow560D1B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuhengh/starling-builder-haxe/HEAD/demo/assets/LobsterTwoRegular_Size54_ColorFFFFFF_StrokeAF384E_DropShadow560D1B.png -------------------------------------------------------------------------------- /demo/assets/strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello":{"en_US":"hello", "de_DE":"hallo", "es_ES":"hola", "fr_FR":"bonjour", "cn_ZH":"你好"}, 3 | "world":{"en_US":"world", "de_DE":"wereld", "es_ES":"mundo", "fr_FR":"monde", "cn_ZH":"世界"} 4 | } -------------------------------------------------------------------------------- /src/starlingbuilder/engine/format/IDataFormatter.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.format; 9 | 10 | /** 11 | * @private 12 | */ 13 | interface IDataFormatter 14 | { 15 | function read(data:Dynamic):Dynamic; 16 | } 17 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/type/ArrayUtil.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.type; 2 | 3 | class ArrayUtil 4 | { 5 | public static function resize(arr:Array, newLength:Int, defaultValue:T = null):Void 6 | { 7 | var length:Int = arr.length; 8 | if (newLength < length) 9 | arr.splice(newLength, length - newLength); 10 | else if (newLength > length) 11 | { 12 | for (i in length ... newLength) 13 | arr[i] = defaultValue; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/type/SafeCast.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.type; 2 | import haxe.macro.Expr; 3 | 4 | class SafeCast 5 | { 6 | 7 | macro public static function safe_cast(value:Expr, type:Expr) 8 | { 9 | switch(value.expr) 10 | { 11 | case EConst(c): 12 | //trace('$value is a constant'); 13 | return macro Std.is($value, $type) ? cast $value : null; 14 | default: 15 | //trace('!$value'); 16 | return macro $b { [(macro var e = $value), (macro Std.is(e, $type) ? cast e : null)] }; 17 | } 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/AssetMediator.hx: -------------------------------------------------------------------------------- 1 | package starlingbuilder.demo; 2 | import starling.utils.AssetManager; 3 | import openfl.Assets; 4 | import starlingbuilder.engine.DefaultAssetMediator; 5 | 6 | class AssetMediator extends DefaultAssetMediator 7 | { 8 | public function new(assetManager:AssetManager) 9 | { 10 | super(assetManager); 11 | } 12 | 13 | override public function getExternalData(name:String):Dynamic 14 | { 15 | return Assets.getText("assets/" + name + ".json"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demo/src/feathers/core/ITextBaselineControl.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * A UI control with text that has a baseline. 11 | */ 12 | interface ITextBaselineControl extends IFeathersControl 13 | { 14 | /** 15 | * Returns the text baseline measurement, in pixels. 16 | */ 17 | var baseline(get, never):Float; 18 | //function get_baseline():Float; 19 | } 20 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/geom/matrixToRotation.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.geom 9 | { 10 | import flash.geom.Matrix; 11 | 12 | /** 13 | * Extracts the rotation value (in radians) from a flash.geom.Matrix 14 | * 15 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html flash.geom.Matrix 16 | */ 17 | public function matrixToRotation(matrix:Matrix):Float 18 | { 19 | var c:Float = matrix.c; 20 | var d:Float = matrix.d; 21 | return -Math.atan(c / d); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/geom/matrixToScaleX.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.geom; 9 | import openfl.geom.Matrix; 10 | 11 | /** 12 | * Extracts the x scale value from a openfl.geom.Matrix 13 | * 14 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html openfl.geom.Matrix 15 | */ 16 | public function matrixToScaleX(matrix:Matrix):Float 17 | { 18 | var a:Float = matrix.a; 19 | var b:Float = matrix.b; 20 | return Math.sqrt(a * a + b * b); 21 | } 22 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/geom/matrixToScaleY.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.geom; 9 | import openfl.geom.Matrix; 10 | 11 | /** 12 | * Extracts the y scale value from a openfl.geom.Matrix 13 | * 14 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html openfl.geom.Matrix 15 | */ 16 | public function matrixToScaleY(matrix:Matrix):Float 17 | { 18 | var c:Float = matrix.c; 19 | var d:Float = matrix.d; 20 | return Math.sqrt(c * c + d * d); 21 | } 22 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/display/stageToStarling.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.display 9 | { 10 | import starling.core.Starling; 11 | import starling.display.Stage; 12 | 13 | /** 14 | * Finds the Starling instance that controls a particular 15 | * starling.display.Stage. 16 | */ 17 | public function stageToStarling(stage:Stage):Starling 18 | { 19 | for each(var starling:Starling in Starling.all) 20 | { 21 | if(starling.stage == stage) 22 | { 23 | return starling; 24 | } 25 | } 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/IDisplayObjectHandler.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine; 9 | 10 | import starling.display.DisplayObject; 11 | 12 | /** 13 | * Interface of callback when the display object is created in UIBuilder. 14 | * It's called internally by UIBuilder.load() or UIBuilder.create(). 15 | * 16 | * @see starlingbuilder.engine.UIBuilder 17 | */ 18 | interface IDisplayObjectHandler 19 | { 20 | function onCreate(obj:DisplayObject, paramsDict:Map):Void; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/format/DefaultDataFormatter.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.format; 9 | import haxe.Json; 10 | 11 | /** 12 | * @private 13 | */ 14 | class DefaultDataFormatter implements IDataFormatter 15 | { 16 | public function new() 17 | { 18 | } 19 | 20 | public function read(data:Dynamic):Dynamic 21 | { 22 | if (Std.is(data, String)) 23 | { 24 | return Json.parse(data); 25 | } 26 | else 27 | { 28 | return data; 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/type/AcceptEither.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.type; 2 | // http://jasono.co/2014/01/09/accept-either-string-or-int-without-resorting-to-dynamic/ 3 | // http://try.haxe.org/#b6b6a 4 | 5 | abstract AcceptEither (Either) { 6 | 7 | public inline function new( e:Either ) this = e; 8 | 9 | public var value(get,never):Dynamic; 10 | public var type(get,never):Either; 11 | 12 | inline function get_value() switch this { case Left(v) | Right(v): return v; } 13 | @:to inline function get_type() return this; 14 | 15 | @:from static function fromA( v:A ):AcceptEither return new AcceptEither( Left(v) ); 16 | @:from static function fromB( v:B ):AcceptEither return new AcceptEither( Right(v) ); 17 | } 18 | 19 | enum Either { 20 | Left( v:A ); 21 | Right( v:B ); 22 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/type/UnionMap.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.type; 2 | 3 | class UnionMap 4 | { 5 | private var strMap:Map = new Map(); 6 | private var objMap:Map<{}, V> = new Map(); 7 | 8 | public function new() 9 | { 10 | } 11 | 12 | public function get(key:Dynamic):V 13 | { 14 | if (Std.is(key, String)) 15 | return strMap[key]; 16 | else if (key != null) 17 | return objMap[key]; 18 | else 19 | return null; 20 | } 21 | 22 | public function set(key:Dynamic, value:V):Void 23 | { 24 | if (Std.is(key, String)) 25 | strMap[key] = value; 26 | else if (key != null) 27 | objMap[key] = value; 28 | } 29 | 30 | public function remove(key:Dynamic) 31 | { 32 | if (Std.is(key, String)) 33 | strMap.remove(key); 34 | else if (key != null) 35 | objMap.remove(key); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /scaffold/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/display/calculateScaleRatioToFill.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.display; 9 | /** 10 | * Calculates a scale value to maintain aspect ratio and fill the required 11 | * bounds (with the possibility of cutting of the edges a bit). 12 | */ 13 | public function calculateScaleRatioToFill(originalWidth:Float, originalHeight:Float, targetWidth:Float, targetHeight:Float):Float 14 | { 15 | var widthRatio:Float = targetWidth / originalWidth; 16 | var heightRatio:Float = targetHeight / originalHeight; 17 | if(widthRatio > heightRatio) 18 | { 19 | return widthRatio; 20 | } 21 | return heightRatio; 22 | } -------------------------------------------------------------------------------- /demo/assets/movieclip_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"starling.display.MovieClip", 6 | "constructorParams":[ 7 | { 8 | "cls":"__AS3__.vec.Vector.", 9 | "label":"prefix", 10 | "name":"textures", 11 | "value":"meter_" 12 | } 13 | ], 14 | "customParams":{}, 15 | "params":{ 16 | "fps":6, 17 | "name":"movieClip", 18 | "x":87.5, 19 | "y":69.5 20 | } 21 | } 22 | ], 23 | "cls":"starling.display.Sprite", 24 | "customParams":{}, 25 | "params":{ 26 | "name":"root" 27 | } 28 | }, 29 | "setting":{ 30 | "canvasColor":16777215, 31 | "canvasSize":{ 32 | "x":640, 33 | "y":960 34 | } 35 | }, 36 | "version":"1.0" 37 | } -------------------------------------------------------------------------------- /demo/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/display/calculateScaleRatioToFit.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.display; 9 | /** 10 | * Calculates a scale value to maintain aspect ratio and fit inside the 11 | * required bounds (with the possibility of a bit of empty space on the 12 | * edges). 13 | */ 14 | public function calculateScaleRatioToFit(originalWidth:Float, originalHeight:Float, targetWidth:Float, targetHeight:Float):Float 15 | { 16 | var widthRatio:Float = targetWidth / originalWidth; 17 | var heightRatio:Float = targetHeight / originalHeight; 18 | if(widthRatio < heightRatio) 19 | { 20 | return widthRatio; 21 | } 22 | return heightRatio; 23 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/math/roundToPrecision.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.math; 9 | /** 10 | * Rounds a number to a certain level of precision. Useful for limiting the number of 11 | * decimal places on a fractional number. 12 | * 13 | * @param number the input number to round. 14 | * @param precision the number of decimal digits to keep 15 | * @return the rounded number, or the original input if no rounding is needed 16 | * 17 | * @see Math#round 18 | */ 19 | public function roundToPrecision(number:Float, precision:Int = 0):Float 20 | { 21 | var decimalPlaces:Float = Math.pow(10, precision); 22 | return Math.round(decimalPlaces * number) / decimalPlaces; 23 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/math/roundUpToNearest.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.math; 9 | /** 10 | * Rounds a Float up to the nearest multiple of an input. For example, by rounding 11 | * 16 up to the nearest 10, you will receive 20. Similar to the built-in function Math.ceil(). 12 | * 13 | * @param numberToRound the number to round up 14 | * @param nearest the number whose mutiple must be found 15 | * @return the rounded number 16 | * 17 | * @see Math#ceil 18 | */ 19 | public function roundUpToNearest(number:Float, nearest:Float = 1):Float 20 | { 21 | if(nearest == 0) 22 | { 23 | return number; 24 | } 25 | return Math.ceil(roundToPrecision(number / nearest, 10)) * nearest; 26 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/math/roundDownToNearest.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.math; 9 | /** 10 | * Rounds a Float down to the nearest multiple of an input. For example, by rounding 11 | * 16 down to the nearest 10, you will receive 10. Similar to the built-in function Math.floor(). 12 | * 13 | * @param numberToRound the number to round down 14 | * @param nearest the number whose mutiple must be found 15 | * @return the rounded number 16 | * 17 | * @see Math#floor 18 | */ 19 | public function roundDownToNearest(number:Float, nearest:Float = 1):Float 20 | { 21 | if(nearest == 0) 22 | { 23 | return number; 24 | } 25 | return Math.floor(roundToPrecision(number / nearest, 10)) * nearest; 26 | } -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/ConnectPopup.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.display.Button; 11 | import starling.display.Sprite; 12 | import starling.events.Event; 13 | 14 | class ConnectPopup extends Sprite 15 | { 16 | public function new() 17 | { 18 | super(); 19 | 20 | var sprite:Sprite = UIBuilderDemo.uiBuilder.load(ParsedLayouts.connect_popup).object; 21 | addChild(sprite); 22 | 23 | var button:Button = cast sprite.getChildByName("generic_exit"); 24 | button.addEventListener(Event.TRIGGERED, onExit); 25 | } 26 | 27 | private function onExit(event:Event):Void 28 | { 29 | removeFromParent(true); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/math/roundToNearest.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.math; 9 | /** 10 | * Rounds a Float to the nearest multiple of an input. For example, by rounding 11 | * 16 to the nearest 10, you will receive 20. Similar to the built-in function Math.round(). 12 | * 13 | * @param numberToRound the number to round 14 | * @param nearest the number whose mutiple must be found 15 | * @return the rounded number 16 | * 17 | * @see Math#round 18 | */ 19 | public function roundToNearest(number:Float, nearest:Float = 1):Float 20 | { 21 | if(nearest == 0) 22 | { 23 | return number; 24 | } 25 | var roundedNumber:Float = Math.round(roundToPrecision(number / nearest, 10)) * nearest; 26 | return roundToPrecision(roundedNumber, 10); 27 | } -------------------------------------------------------------------------------- /src/starlingbuilder/engine/localization/ILocalization.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.localization; 9 | 10 | /** 11 | * Interface of localizing display objects. It's used in both the editor and the project. 12 | * Once passed into UIBuilder, the localization will work automatically when UIBuilder.load() is called 13 | * 14 | * @see starlingbuilder.engine.UIBuilder 15 | */ 16 | interface ILocalization 17 | { 18 | /** 19 | * Get localized text from key 20 | * @param key key of the text 21 | * @return localized text 22 | */ 23 | function getLocalizedText(key:String):String; 24 | 25 | /** 26 | * Current locale property. 27 | */ 28 | public var locale(get, set):String; 29 | } 30 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/type/UnionWeakMap.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.type; 2 | import haxe.ds.WeakMap; 3 | 4 | class UnionWeakMap 5 | { 6 | #if flash 7 | private var strMap:WeakMap = new WeakMap(); 8 | private var objMap:WeakMap<{}, V> = new WeakMap(); 9 | #else 10 | private var strMap:Map = new Map(); 11 | private var objMap:Map<{}, V> = new Map(); 12 | #end 13 | 14 | public function new() 15 | { 16 | } 17 | 18 | public function get(key:Dynamic):V 19 | { 20 | if (Std.is(key, String)) 21 | return strMap.get(key); 22 | else if (key != null) 23 | return objMap.get(key); 24 | else 25 | return null; 26 | } 27 | 28 | public function set(key:Dynamic, value:V) 29 | { 30 | if (Std.is(key, String)) 31 | strMap.set(key, value); 32 | else if (key != null) 33 | objMap.set(key, value); 34 | } 35 | 36 | public function remove(key:Dynamic) 37 | { 38 | if (Std.is(key, String)) 39 | strMap.remove(key); 40 | else if (key != null) 41 | objMap.remove(key); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/math/clamp.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.math; 9 | 10 | /** 11 | * Forces a numeric value into a specified range. 12 | * 13 | * @param value The value to force into the range. 14 | * @param minimum The minimum bound of the range. 15 | * @param maximum The maximum bound of the range. 16 | * @return A value within the specified range. 17 | * 18 | * @author Josh Tynjala (joshblog.net) 19 | */ 20 | public function clamp(value:Float, minimum:Float, maximum:Float):Float 21 | { 22 | if(minimum > maximum) 23 | { 24 | throw new ArgumentError("minimum should be smaller than maximum."); 25 | } 26 | if(value < minimum) 27 | { 28 | value = minimum; 29 | } 30 | else if(value > maximum) 31 | { 32 | value = maximum; 33 | } 34 | return value; 35 | } -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/ParsedLayouts.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | class ParsedLayouts 11 | { 12 | public static var connect_popup:Dynamic; 13 | 14 | public static var mail_popup:Dynamic; 15 | 16 | public static var mail_item:Dynamic; 17 | 18 | public static var hud:Dynamic; 19 | 20 | public static var localization_test:Dynamic; 21 | 22 | public static var tween_test:Dynamic; 23 | 24 | public static var external_element_test:Dynamic; 25 | 26 | public static var movieclip_test:Dynamic; 27 | 28 | public static var layout_test:Dynamic; 29 | 30 | public static var anchorlayout_test:Dynamic; 31 | 32 | public static var containerbutton_test:Dynamic; 33 | 34 | public static var particle_test:Dynamic; 35 | 36 | public static var pixelmask_test:Dynamic; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IMultilineTextEditor.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * Handles the editing of text, and supports multiline editing. This is not 11 | * a text editor intended for a TextArea component. Instead, 12 | * its a text editor intended for a TextInput component and it 13 | * is expected to provide its own scroll bars. 14 | * 15 | * @see feathers.controls.TextInput 16 | * @see ../../../help/text-editors Introduction to Feathers text editors 17 | */ 18 | interface IMultilineTextEditor extends ITextEditor 19 | { 20 | /** 21 | * Indicates whether the text editor can display more than one line of 22 | * text. 23 | */ 24 | var multiline(get, set):Bool; 25 | //function get_multiline():Bool; 26 | 27 | /** 28 | * @private 29 | */ 30 | //function set_multiline(value:Bool):Void; 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Starling Builder Haxe 2 | 3 | This is a Haxe port of Starling Builder engine. Starling Builder is an open source UI editor for Starling Framework. The original AS3 version repository is from https://github.com/yuhengh/starling-builder-engine 4 | 5 | 6 | This Haxe version interprets the same layout format of the AS3 version. 7 | It gives you the ability to target both Flash/AIR and non-Flash/AIR platform (mostly html5). 8 | You can check out the online demo project at 9 | 10 | http://starlingbuilder.github.io/demo-haxe/ 11 | 12 | It should work well on desktop, tablet and phone browsers. 13 | 14 | #### Setup OpenFL 15 | 16 | haxelib install openfl 17 | haxelib run openfl setup 18 | 19 | #### Setup Starling 20 | 21 | haxelib install starling 22 | 23 | Currently the Starling port is based on Starling 1.8. Feathers UI port(only partially working) is based on Feathers UI 2.2. 24 | 25 | #### Run the demo 26 | 27 | cd demo 28 | openfl test flash 29 | openfl test html5 30 | 31 | #### Documentation 32 | 33 | For more information, please visit our wiki page at http://wiki.starling-framework.org/builder/start -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/LayoutTest.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.display.Sprite; 11 | import starling.events.Touch; 12 | import starling.events.TouchEvent; 13 | import starling.events.TouchPhase; 14 | 15 | class LayoutTest extends Sprite 16 | { 17 | private var _sprite:Sprite; 18 | 19 | public function new() 20 | { 21 | super(); 22 | 23 | _sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.layout_test, false); 24 | addChild(_sprite); 25 | 26 | addEventListener(TouchEvent.TOUCH, onTouchEvent); 27 | } 28 | 29 | private function onTouchEvent(event:TouchEvent):Void 30 | { 31 | var touch:Touch = event.getTouch(this); 32 | if (touch != null && touch.phase == TouchPhase.ENDED) 33 | { 34 | removeFromParent(true); 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/display/getDisplayObjectDepthFromStage.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.display; 9 | import starling.display.DisplayObject; 10 | 11 | /** 12 | * Calculates how many levels deep the target object is on the display list, 13 | * starting from the Starling stage. If the target object is the stage, the 14 | * depth will be 0. A direct child of the stage will have a 15 | * depth of 1, and it increases with each new level. If the 16 | * object does not have a reference to the stage, the depth will always be 17 | * -1, even if the object has a parent. 18 | */ 19 | public function getDisplayObjectDepthFromStage(target:DisplayObject):Int 20 | { 21 | if(!target.stage) 22 | { 23 | return -1; 24 | } 25 | var count:Int = 0; 26 | while(target.parent) 27 | { 28 | target = target.parent; 29 | count++; 30 | } 31 | return count; 32 | } 33 | -------------------------------------------------------------------------------- /scaffold/src/Main.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | 4 | import starling.events.Event; 5 | import starling.events.ResizeEvent; 6 | import openfl.geom.Rectangle; 7 | import openfl.geom.Point; 8 | import starlingbuilder.engine.util.StageUtil; 9 | import starling.core.Starling; 10 | import openfl.display.Sprite; 11 | 12 | 13 | class Main extends Sprite 14 | { 15 | public var starling:Starling; 16 | public var stageUtil:StageUtil; 17 | 18 | public function new() 19 | { 20 | super(); 21 | 22 | stageUtil = new StageUtil(stage); 23 | starling = new Starling(Game, stage); 24 | //starling.showStats = true; 25 | starling.stage.addEventListener(ResizeEvent.RESIZE, onResize); 26 | 27 | starling.start(); 28 | } 29 | 30 | private function onResize(event:ResizeEvent):Void 31 | { 32 | starling.viewPort = new Rectangle(0, 0, event.width, event.height); 33 | 34 | var size:Point = stageUtil.getScaledStageSize(event.width, event.height); 35 | 36 | starling.stage.stageWidth = cast size.x; 37 | starling.stage.stageHeight = cast size.y; 38 | } 39 | 40 | 41 | } -------------------------------------------------------------------------------- /src/starlingbuilder/engine/localization/ILocalizationHandler.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.localization; 9 | 10 | import starling.display.DisplayObject; 11 | 12 | /** 13 | * Interface for cases that localization needs special treatment (e.g. change to a different font for some languages) 14 | * Once passed into UIBuilder, the callback will be fired automatically when the localization is happening. 15 | * 16 | * @see starlingbuilder.engine.UIBuilder 17 | */ 18 | interface ILocalizationHandler 19 | { 20 | /** 21 | * Callback function when a display object is localized 22 | * @param object display object 23 | * @param text text of the display object 24 | * @param paramsDict params dictionary of meta data 25 | * @param locale the current locale 26 | */ 27 | function localize(object:DisplayObject, text:String, paramsDict:Map, locale:String):Void; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/MailItemRenderer.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import feathers.controls.renderers.LayoutGroupListItemRenderer; 11 | 12 | import starling.display.Sprite; 13 | import starling.text.TextField; 14 | 15 | class MailItemRenderer extends LayoutGroupListItemRenderer 16 | { 17 | public var _text:TextField; 18 | 19 | private var _sprite:Sprite; 20 | 21 | public function new() 22 | { 23 | super(); 24 | } 25 | 26 | override private function initialize():Void 27 | { 28 | if (_sprite == null) 29 | { 30 | _sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.mail_item, true, this); 31 | addChild(_sprite); 32 | } 33 | } 34 | 35 | override public function set_data(value:Dynamic):Dynamic 36 | { 37 | super.data = value; 38 | 39 | if (_data) 40 | _text.text = _data.label; 41 | 42 | return value; 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /demo/src/feathers/core/INativeFocusOwner.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | import flash.display.InteractiveObject; 10 | 11 | /** 12 | * If a Feathers component may receive focus, it may be associated with a 13 | * display object on the native stage. The focus manager will automatically 14 | * pass focus to the native focus. 15 | * 16 | * @see http://feathersui.com/help/focus.html 17 | */ 18 | interface INativeFocusOwner extends IFocusDisplayObject 19 | { 20 | /** 21 | * A display object on the native stage that is given focus when this 22 | * Feathers display object is given focus by a focus manager. 23 | * 24 | *

This property may return null. When it returns 25 | * null, the focus manager should treat this display object 26 | * like any other display object that may receive focus but doesn't 27 | * implement INativeFocusOwner.

28 | */ 29 | var nativeFocus(get, never):InteractiveObject; 30 | //function get_nativeFocus():InteractiveObject; 31 | } 32 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IFocusContainer.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * A component that can receive focus with children that can receive focus. 11 | * 12 | * @see feathers.core.IFocusManager 13 | */ 14 | interface IFocusContainer extends IFocusDisplayObject 15 | { 16 | /** 17 | * Determines if this component's children can receive focus. This 18 | * property is completely independent from the isFocusEnabled 19 | * property. In other words, it's possible to disable focus on this 20 | * component while still allowing focus on its children (or the other 21 | * way around). 22 | * 23 | *

In the following example, the focus is disabled:

24 | * 25 | * 26 | * object.isFocusEnabled = false; 27 | * 28 | * @see #isFocusEnabled 29 | */ 30 | var isChildFocusEnabled(get, set):Bool; 31 | //function get_isChildFocusEnabled():Bool; 32 | 33 | /** 34 | * @private 35 | */ 36 | //function set_isChildFocusEnabled(value:Bool):Bool; 37 | } 38 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/ExternalElementTest.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starlingbuilder.demo.ParsedLayouts; 11 | import starlingbuilder.demo.UIBuilderDemo; 12 | import starling.display.Sprite; 13 | import starling.events.Touch; 14 | import starling.events.TouchEvent; 15 | import starling.events.TouchPhase; 16 | 17 | class ExternalElementTest extends Sprite 18 | { 19 | private var _sprite:Sprite; 20 | 21 | public function new() 22 | { 23 | super(); 24 | 25 | _sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.external_element_test, false); 26 | addChild(_sprite); 27 | 28 | addEventListener(TouchEvent.TOUCH, onTouchEvent); 29 | } 30 | 31 | private function onTouchEvent(event:TouchEvent):Void 32 | { 33 | var touch:Touch = event.getTouch(this); 34 | if (touch != null && touch.phase == TouchPhase.ENDED) 35 | { 36 | removeFromParent(true); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IGroupedToggle.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * A toggle associated with a specific group. 11 | * 12 | * @see ToggleGroup 13 | */ 14 | interface IGroupedToggle extends IToggle 15 | { 16 | /** 17 | * When the toggle is added to a ToggleGroup, the group 18 | * will manage the entire group's selection when one of the toggles in 19 | * the group changes. 20 | * 21 | *

In the following example, a Radio is added to a ToggleGroup:

22 | * 23 | * 24 | * var group:ToggleGroup = new ToggleGroup(); 25 | * group.addEventListener( Event.CHANGE, group_changeHandler ); 26 | * 27 | * var radio:Radio = new Radio(); 28 | * radio.toggleGroup = group; 29 | * this.addChild( radio ); 30 | */ 31 | var toggleGroup(get, set):ToggleGroup; 32 | //function get_toggleGroup():ToggleGroup; 33 | 34 | /** 35 | * @private 36 | */ 37 | //function set_toggleGroup(value:ToggleGroup):Void; 38 | } 39 | -------------------------------------------------------------------------------- /scaffold/src/Game.hx: -------------------------------------------------------------------------------- 1 | package ; 2 | import openfl.errors.Error; 3 | import openfl.Assets; 4 | import haxe.Json; 5 | import starlingbuilder.engine.UIBuilder; 6 | import starlingbuilder.engine.DefaultAssetMediator; 7 | import starlingbuilder.engine.IUIBuilder; 8 | import starlingbuilder.engine.IAssetMediator; 9 | import starling.utils.AssetManager; 10 | import starling.display.Sprite; 11 | class Game extends Sprite 12 | { 13 | private var _assetManager:AssetManager; 14 | private var _assetMediator:IAssetMediator; 15 | 16 | public static var uiBuilder:IUIBuilder; 17 | 18 | public function new() 19 | { 20 | super(); 21 | 22 | _assetManager = new AssetManager(); 23 | _assetMediator = new DefaultAssetMediator(_assetManager); 24 | uiBuilder = new UIBuilder(_assetMediator); 25 | 26 | _assetManager.loadQueue(function(ratio:Float):Void{ 27 | if (ratio == 1) 28 | { 29 | init(); 30 | } 31 | }); 32 | } 33 | 34 | private function init():Void 35 | { 36 | var data:Dynamic = Json.parse(Assets.getText("assets/hello.json")); 37 | var sprite:Sprite = cast uiBuilder.create(data); 38 | //throw new Error("wtf"); 39 | addChild(sprite); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/localization/DefaultLocalizationHandler.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.localization; 9 | 10 | import starling.display.DisplayObject; 11 | import starling.text.TextField; 12 | import starling.text.TextFieldAutoSize; 13 | 14 | /** 15 | * Default implementation of ILocalizationHandler 16 | * 17 | * @see ILocalizationHandler 18 | */ 19 | class DefaultLocalizationHandler implements ILocalizationHandler 20 | { 21 | public function new() 22 | { 23 | } 24 | 25 | /** 26 | * @inheritDoc 27 | */ 28 | 29 | public function localize(object:DisplayObject, text:String, paramsDict:Map, locale:String):Void 30 | { 31 | //Assuming that TextField with auto size will always have pivot align to center 32 | if (Std.is(object, TextField)) 33 | { 34 | var textField:TextField = cast object; 35 | 36 | if (textField.autoSize != TextFieldAutoSize.NONE) 37 | { 38 | textField.alignPivot(); 39 | } 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/geom/FeathersMatrixUtil.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.geom; 2 | import openfl.geom.Matrix; 3 | 4 | class FeathersMatrixUtil 5 | { 6 | 7 | /** 8 | * Extracts the rotation value (in radians) from a openfl.geom.Matrix 9 | * 10 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html openfl.geom.Matrix 11 | */ 12 | public static function matrixToRotation(matrix:Matrix):Float 13 | { 14 | var c:Float = matrix.c; 15 | var d:Float = matrix.d; 16 | return -Math.atan(c / d); 17 | } 18 | 19 | /** 20 | * Extracts the x scale value from a openfl.geom.Matrix 21 | * 22 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html openfl.geom.Matrix 23 | */ 24 | public static function matrixToScaleX(matrix:Matrix):Float 25 | { 26 | var a:Float = matrix.a; 27 | var b:Float = matrix.b; 28 | return Math.sqrt(a * a + b * b); 29 | } 30 | 31 | /** 32 | * Extracts the y scale value from a openfl.geom.Matrix 33 | * 34 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html openfl.geom.Matrix 35 | */ 36 | public static function matrixToScaleY(matrix:Matrix):Float 37 | { 38 | var c:Float = matrix.c; 39 | var d:Float = matrix.d; 40 | return Math.sqrt(c * c + d * d); 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /demo/src/feathers/core/IValidating.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * A display object that supports validation. Display objects of this type 11 | * will delay updating after property changes until just before Starling 12 | * renders the display list to avoid running redundant code. 13 | */ 14 | interface IValidating extends IFeathersDisplayObject 15 | { 16 | /** 17 | * The component's depth in the display list, relative to the stage. If 18 | * the component isn't on the stage, its depth will be -1. 19 | * 20 | *

Used by the validation system to validate components from the 21 | * top down

. 22 | */ 23 | var depth(get, never):Int; 24 | //function get_depth():Int; 25 | 26 | /** 27 | * Immediately validates the display object, if it is invalid. The 28 | * validation system exists to postpone updating a display object after 29 | * properties are changed until until the last possible moment the 30 | * display object is rendered. This allows multiple properties to be 31 | * changed at a time without requiring a full update every time. 32 | */ 33 | function validate():Void; 34 | } 35 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/TweenTest.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.display.Sprite; 11 | import starling.events.Touch; 12 | import starling.events.TouchEvent; 13 | import starling.events.TouchPhase; 14 | 15 | class TweenTest extends Sprite 16 | { 17 | private var _sprite:Sprite; 18 | 19 | public function new() 20 | { 21 | super(); 22 | 23 | var data:Dynamic = UIBuilderDemo.uiBuilder.load(ParsedLayouts.tween_test, false); 24 | _sprite = cast data.object; 25 | addChild(_sprite); 26 | 27 | UIBuilderDemo.uiBuilder.tweenBuilder.start(_sprite, data.params); 28 | 29 | addEventListener(TouchEvent.TOUCH, onTouchEvent); 30 | } 31 | 32 | override public function dispose():Void 33 | { 34 | UIBuilderDemo.uiBuilder.tweenBuilder.stop(_sprite); 35 | super.dispose(); 36 | } 37 | 38 | private function onTouchEvent(event:TouchEvent):Void 39 | { 40 | var touch:Touch = event.getTouch(this); 41 | if (touch != null && touch.phase == TouchPhase.ENDED) 42 | { 43 | removeFromParent(true); 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/LocalizationHandler.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.display.DisplayObject; 11 | import starling.text.BitmapFont; 12 | import starling.text.TextField; 13 | 14 | import starlingbuilder.engine.localization.DefaultLocalizationHandler; 15 | 16 | /** 17 | * Default implementation of ILocalizationHandler 18 | * 19 | * @see ILocalizationHandler 20 | */ 21 | class LocalizationHandler extends DefaultLocalizationHandler 22 | { 23 | /** 24 | * Constructor 25 | */ 26 | public function new() 27 | { 28 | super(); 29 | } 30 | 31 | /** 32 | * @inheritDoc 33 | */ 34 | override public function localize(object:DisplayObject, text:String, paramsDict:Map, locale:String):Void 35 | { 36 | var textField:TextField = cast object; 37 | if (textField != null) 38 | { 39 | if (locale == "cn_ZH" && textField.fontName == BitmapFont.MINI) 40 | textField.fontName = "_sans"; 41 | else if (textField.fontName == "_sans") 42 | textField.fontName = BitmapFont.MINI; 43 | } 44 | 45 | super.localize(object, text, paramsDict, locale); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/Main.hx: -------------------------------------------------------------------------------- 1 | package starlingbuilder.demo; 2 | 3 | 4 | import starling.events.ResizeEvent; 5 | import openfl.geom.Rectangle; 6 | import openfl.geom.Point; 7 | import starlingbuilder.engine.util.StageUtil; 8 | import starling.core.Starling; 9 | import openfl.display.Sprite; 10 | 11 | 12 | class Main extends Sprite 13 | { 14 | 15 | public var starling:Starling; 16 | public var stageUtil:StageUtil; 17 | 18 | public function new() 19 | { 20 | super(); 21 | 22 | stageUtil = new StageUtil(stage); 23 | starling = new Starling(UIBuilderDemo, stage); 24 | //starling.showStats = true; 25 | starling.stage.addEventListener(ResizeEvent.RESIZE, onResize); 26 | 27 | var w:Int = stage.stageWidth; 28 | var h:Int = stage.stageHeight; 29 | starling.viewPort = new Rectangle(0, 0, w, h); 30 | var size:Point = stageUtil.getScaledStageSize(w, h); 31 | 32 | starling.stage.stageWidth = cast size.x; 33 | starling.stage.stageHeight = cast size.y; 34 | 35 | starling.start(); 36 | } 37 | 38 | private function onResize(event:ResizeEvent):Void 39 | { 40 | starling.viewPort = new Rectangle(0, 0, event.width, event.height); 41 | 42 | var size:Point = stageUtil.getScaledStageSize(event.width, event.height); 43 | 44 | starling.stage.stageWidth = cast size.x; 45 | starling.stage.stageHeight = cast size.y; 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/MailPopup.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import feathers.controls.List; 11 | import feathers.controls.renderers.IListItemRenderer; 12 | import feathers.core.PopUpManager; 13 | import feathers.data.ListCollection; 14 | 15 | import starling.display.Button; 16 | import starling.display.Sprite; 17 | import starling.events.Event; 18 | 19 | class MailPopup extends Sprite 20 | { 21 | //auto bind variables 22 | public var _list:List; 23 | public var _exitButton:Button; 24 | 25 | public function new() 26 | { 27 | super(); 28 | 29 | var sprite:Sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.mail_popup, true, this); 30 | addChild(sprite); 31 | 32 | var listCollection:ListCollection = new ListCollection(); 33 | 34 | for (i in 1...50) 35 | { 36 | listCollection.push({label: ("You received a gift " + i)}); 37 | } 38 | 39 | _list.itemRendererFactory = function():IListItemRenderer 40 | { 41 | return new MailItemRenderer(); 42 | } 43 | _list.dataProvider = listCollection; 44 | 45 | _exitButton.addEventListener(Event.TRIGGERED, onExit); 46 | } 47 | 48 | private function onExit(event:Event):Void 49 | { 50 | removeFromParent(true); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Simplified BSD License 2 | ====================== 3 | 4 | Copyright 2015 SGN Inc. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of 10 | conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 13 | of conditions and the following disclaimer in the documentation and/or other materials 14 | provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY SGN "AS IS" AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SGN OR 19 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | The views and conclusions contained in the software and documentation are those of the 27 | authors and should not be interpreted as representing official policies, either expressed 28 | or implied, of SGN. 29 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/ContainerButtonPopup.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.display.Button; 11 | import starling.display.Sprite; 12 | import starling.events.Event; 13 | 14 | import starlingbuilder.extensions.uicomponents.ContainerButton; 15 | 16 | class ContainerButtonPopup extends Sprite 17 | { 18 | //auto bind variables 19 | public var _closeButton:Button; 20 | public var _buyButton:ContainerButton; 21 | public var _claimButton:ContainerButton; 22 | 23 | public function new() 24 | { 25 | super(); 26 | 27 | var sprite:Sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.containerbutton_test, true, this); 28 | addChild(sprite); 29 | 30 | _closeButton.addEventListener(Event.TRIGGERED, onExit); 31 | _buyButton.addEventListener(Event.TRIGGERED, onBuy); 32 | _claimButton.addEventListener(Event.TRIGGERED, onClaim); 33 | } 34 | 35 | private function onExit(event:Event):Void 36 | { 37 | removeFromParent(true); 38 | } 39 | 40 | private function onBuy(event:Event):Void 41 | { 42 | trace("onBuy"); 43 | } 44 | 45 | private function onClaim(event:Event):Void 46 | { 47 | trace("onClaim"); 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/MovieClipTest.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starlingbuilder.demo.ParsedLayouts; 11 | import starlingbuilder.demo.UIBuilderDemo; 12 | import starling.core.Starling; 13 | import starling.display.MovieClip; 14 | import starling.display.Sprite; 15 | import starling.events.Touch; 16 | import starling.events.TouchEvent; 17 | import starling.events.TouchPhase; 18 | 19 | class MovieClipTest extends Sprite 20 | { 21 | private var _sprite:Sprite; 22 | private var _movieClip:MovieClip; 23 | 24 | public function new() 25 | { 26 | super(); 27 | 28 | _sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.movieclip_test, false); 29 | addChild(_sprite); 30 | 31 | _movieClip = cast _sprite.getChildByName("movieClip"); 32 | Starling.current.juggler.add(_movieClip); 33 | _movieClip.play(); 34 | 35 | addEventListener(TouchEvent.TOUCH, onTouchEvent); 36 | } 37 | 38 | private function onTouchEvent(event:TouchEvent):Void 39 | { 40 | var touch:Touch = event.getTouch(this); 41 | if (touch != null && touch.phase == TouchPhase.ENDED) 42 | { 43 | removeFromParent(true); 44 | } 45 | } 46 | 47 | override public function dispose():Void 48 | { 49 | Starling.current.juggler.remove(_movieClip); 50 | super.dispose(); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IFocusManager.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | import starling.display.DisplayObjectContainer; 10 | 11 | /** 12 | * Interface for focus management. 13 | * 14 | * @see feathers.core.IFocusDisplayObject 15 | * @see feathers.core.FocusManager 16 | */ 17 | interface IFocusManager 18 | { 19 | /** 20 | * Determines if this focus manager is enabled. A focus manager may be 21 | * disabled when another focus manager has control, such as when a 22 | * modal pop-up is displayed. 23 | */ 24 | var isEnabled(get, set):Bool; 25 | //function get_isEnabled():Bool; 26 | 27 | /** 28 | * @private 29 | */ 30 | //function set_isEnabled(value:Bool):Void; 31 | 32 | /** 33 | * The object that currently has focus. May return null if 34 | * no object has focus. 35 | * 36 | *

In the following example, the focus is changed:

37 | * 38 | * 39 | * focusManager.focus = someObject; 40 | */ 41 | var focus(get, set):IFocusDisplayObject; 42 | //function get_focus():IFocusDisplayObject; 43 | 44 | /** 45 | * @private 46 | */ 47 | //function set_focus(value:IFocusDisplayObject):Void; 48 | 49 | /** 50 | * The top-level container of the focus manager. This isn't necessarily 51 | * the root of the display list. 52 | */ 53 | var root(get, never):DisplayObjectContainer; 54 | function get_root():DisplayObjectContainer; 55 | } 56 | -------------------------------------------------------------------------------- /demo/src/feathers/core/ITextRenderer.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | import openfl.geom.Point; 10 | 11 | /** 12 | * Interface that handles common capabilities of rendering text. 13 | * 14 | * @see ../../../help/text-renderers.html Introduction to Feathers text renderers 15 | */ 16 | interface ITextRenderer extends IFeathersControl extends ITextBaselineControl 17 | { 18 | /** 19 | * The text to render. 20 | * 21 | *

If using the Label component, this property should 22 | * be set on the Label, and it will be passed down to the 23 | * text renderer.

24 | */ 25 | var text(get, set):String; 26 | //function get_text():String; 27 | 28 | /** 29 | * @private 30 | */ 31 | //function set_text(value:String):Void; 32 | 33 | /** 34 | * Determines if the text wraps to the next line when it reaches the 35 | * width (or max width) of the component. 36 | * 37 | *

If using the Label component, this property should 38 | * be set on the Label, and it will be passed down to the 39 | * text renderer automatically.

40 | */ 41 | var wordWrap(get, set):Bool; 42 | //function get_wordWrap():Bool; 43 | 44 | /** 45 | * @private 46 | */ 47 | //function set_wordWrap(value:Bool):Void; 48 | 49 | /** 50 | * Measures the text's bounds (without a full validation, if 51 | * possible). 52 | */ 53 | function measureText(result:Point = null):Point; 54 | } 55 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IToggle.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * Dispatched when the selection changes. 11 | * 12 | *

The properties of the event object have the following values:

13 | * 14 | * 15 | * 16 | * 20 | * 21 | * 25 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 17 | * event listener that handles the event. For example, if you use 18 | * myButton.addEventListener() to register an event listener, 19 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 22 | * it is not always the Object listening for the event. Use the 23 | * currentTarget property to always access the Object 24 | * listening for the event.
26 | * 27 | * @eventType starling.events.Event.CHANGE 28 | */ 29 | ///[Event(name="change",type="starling.events.Event")] 30 | 31 | /** 32 | * An interface for something that may be selected. 33 | */ 34 | interface IToggle extends IFeathersControl 35 | { 36 | /** 37 | * Indicates if the IToggle is selected or not. 38 | */ 39 | var isSelected(get, set):Bool; 40 | //function get_isSelected():Bool; 41 | 42 | /** 43 | * @private 44 | */ 45 | //function set_isSelected(value:Bool):Void; 46 | } -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/AnchorLayoutTest.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.events.ResizeEvent; 11 | import starling.core.Starling; 12 | 13 | import starling.display.Sprite; 14 | import starling.display.Stage; 15 | import starling.events.Touch; 16 | import starling.events.TouchEvent; 17 | import starling.events.TouchPhase; 18 | 19 | class AnchorLayoutTest extends Sprite 20 | { 21 | private var _sprite:Sprite; 22 | 23 | public function new() 24 | { 25 | super(); 26 | 27 | _sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.anchorlayout_test, false); 28 | 29 | onResize(null); 30 | 31 | addChild(_sprite); 32 | 33 | addEventListener(TouchEvent.TOUCH, onTouchEvent); 34 | 35 | Starling.current.stage.addEventListener(ResizeEvent.RESIZE, onResize); 36 | } 37 | 38 | private function onTouchEvent(event:TouchEvent):Void 39 | { 40 | var touch:Touch = event.getTouch(this); 41 | if (touch != null && touch.phase == TouchPhase.ENDED) 42 | { 43 | removeFromParent(true); 44 | } 45 | } 46 | 47 | private function onResize(event:ResizeEvent):Void 48 | { 49 | var stage:Stage = Starling.current.stage; 50 | _sprite.width = stage.stageWidth; 51 | _sprite.height = stage.stageHeight; 52 | } 53 | 54 | override public function dispose():Void 55 | { 56 | Starling.current.stage.removeEventListener(ResizeEvent.RESIZE, onResize); 57 | super.dispose(); 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/DefaultAssetMediator.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine; 9 | 10 | import openfl.Vector; 11 | import starling.textures.Texture; 12 | import starling.utils.AssetManager; 13 | 14 | /** 15 | * Default implementation of IAssetMediator 16 | * 17 | * @see IAssetMediator 18 | */ 19 | class DefaultAssetMediator implements IAssetMediator 20 | { 21 | private var _assetManager:AssetManager; 22 | 23 | public function new(assetManager:AssetManager) 24 | { 25 | _assetManager = assetManager; 26 | } 27 | 28 | /** 29 | * @inheritDoc 30 | */ 31 | 32 | public function getTexture(name:String):Texture 33 | { 34 | return _assetManager.getTexture(name); 35 | } 36 | 37 | /** 38 | * @inheritDoc 39 | */ 40 | 41 | public function getTextures(prefix:String = "", result:Vector = null):Vector 42 | { 43 | return _assetManager.getTextures(prefix, result); 44 | } 45 | 46 | /** 47 | * @inheritDoc 48 | */ 49 | 50 | public function getExternalData(name:String):Dynamic 51 | { 52 | return null; 53 | } 54 | 55 | /** 56 | * @inheritDoc 57 | */ 58 | 59 | public function getXml(name:String):Xml 60 | { 61 | return _assetManager.getXml(name); 62 | } 63 | 64 | /** 65 | * @inheritDoc 66 | */ 67 | 68 | public function getObject(name:String):Dynamic 69 | { 70 | return _assetManager.getObject(name); 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IFocusExtras.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | import starling.display.DisplayObject; 10 | 11 | /** 12 | * A container that may have extra children that aren't accessible from the 13 | * standard display list functions like getChildAt(), but those 14 | * "extra" children may still need to receive focus. An example of this 15 | * would be a container with "chrome", such as feathers.controls.Panel. 16 | * 17 | * @see feathers.core.IFocusManager 18 | */ 19 | interface IFocusExtras 20 | { 21 | /** 22 | * Extra display objects that are not accessible through standard 23 | * display list functions like getChildAt(), but should 24 | * appear before those children in the focus order. Typically, this is 25 | * for containers that have chrome that is hidden from the normal 26 | * display list API. 27 | * 28 | *

May return null if there are no extra children.

29 | */ 30 | var focusExtrasBefore(get, never):Array; 31 | //function get_focusExtrasBefore():Array; 32 | 33 | /** 34 | * Extra display objects that are not accessible through standard 35 | * display list functions like getChildAt(), but should 36 | * appear after those children in the focus order. Typically, this is 37 | * for containers that have chrome that is hidden from the normal 38 | * display list API. 39 | * 40 | *

May return null if there are no extra children.

41 | */ 42 | var focusExtrasAfter(get, never):Array; 43 | //function get_focusExtrasAfter():Array; 44 | } 45 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/localization/DefaultLocalization.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.localization; 9 | 10 | /** 11 | * Default implementation of ILocalization 12 | * 13 | * @see ILocalization 14 | * @see http://wiki.starling-framework.org/builder/localization Using Localization 15 | */ 16 | import Reflect; 17 | 18 | class DefaultLocalization implements ILocalization 19 | { 20 | private var _data:Dynamic; 21 | private var _locale:String; 22 | 23 | public var locale(get, set):String; 24 | 25 | /** 26 | * Constructor 27 | * @param data localization data 28 | * @param locale current locale 29 | */ 30 | 31 | public function new(data:Dynamic, locale:String = null):Void 32 | { 33 | _data = data; 34 | _locale = locale; 35 | } 36 | 37 | /** 38 | * @inheritDoc 39 | */ 40 | 41 | public function getLocalizedText(key:String):String 42 | { 43 | if (_locale != null && Reflect.hasField(_data, key) && Reflect.hasField(Reflect.field(_data, key), _locale)) 44 | { 45 | return Reflect.field(Reflect.field(_data, key), _locale); 46 | } 47 | else 48 | { 49 | return null; 50 | } 51 | } 52 | 53 | /** 54 | * @inheritDoc 55 | */ 56 | 57 | public function get_locale():String 58 | { 59 | return _locale; 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | 66 | public function set_locale(value:String):String 67 | { 68 | _locale = value; 69 | return _locale; 70 | } 71 | 72 | } 73 | 74 | -------------------------------------------------------------------------------- /demo/assets/ui.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/assets/external_element_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"starling.display.Sprite", 6 | "customParams":{ 7 | "source":"connect_popup" 8 | }, 9 | "params":{ 10 | "filter":{ 11 | "cls":"starling.filters.BlurFilter", 12 | "constructorParams":[], 13 | "customParams":{}, 14 | "params":{ 15 | "blurX":10, 16 | "blurY":10, 17 | "resolution":1 18 | } 19 | }, 20 | "name":"connect_popup", 21 | "scaleX":0.59, 22 | "scaleY":0.59, 23 | "x":60.97, 24 | "y":48.48 25 | } 26 | }, 27 | { 28 | "cls":"starling.display.Sprite", 29 | "customParams":{ 30 | "source":"connect_popup" 31 | }, 32 | "params":{ 33 | "filter":{ 34 | "cls":"starling.filters.BlurFilter", 35 | "constructorParams":[], 36 | "customParams":{}, 37 | "params":{ 38 | "blurX":2, 39 | "blurY":2, 40 | "resolution":1 41 | } 42 | }, 43 | "name":"connect_popup", 44 | "scaleX":0.59, 45 | "scaleY":0.59, 46 | "x":118.18, 47 | "y":114.94 48 | } 49 | }, 50 | { 51 | "cls":"starling.display.Sprite", 52 | "customParams":{ 53 | "source":"connect_popup" 54 | }, 55 | "params":{ 56 | "name":"connect_popup", 57 | "scaleX":0.59, 58 | "scaleY":0.59, 59 | "x":189.88, 60 | "y":183 61 | } 62 | } 63 | ], 64 | "cls":"starling.display.Sprite", 65 | "customParams":{}, 66 | "params":{ 67 | "name":"root" 68 | } 69 | }, 70 | "setting":{ 71 | "canvasColor":16777215, 72 | "canvasSize":{ 73 | "x":640, 74 | "y":960 75 | } 76 | }, 77 | "version":"1.0" 78 | } -------------------------------------------------------------------------------- /demo/assets/particle_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"starlingbuilder.extensions.particle.FFParticleSprite", 6 | "customParams":{}, 7 | "params":{ 8 | "config":{ 9 | "cls":"XML", 10 | "name":"default_particle" 11 | }, 12 | "name":"fFParticleSprite", 13 | "particleId":"1", 14 | "texture":{ 15 | "cls":"starling.textures.Texture", 16 | "textureName":"default_particle_png" 17 | }, 18 | "x":187, 19 | "y":121 20 | } 21 | }, 22 | { 23 | "cls":"starlingbuilder.extensions.particle.FFParticleSprite", 24 | "customParams":{}, 25 | "params":{ 26 | "config":{ 27 | "cls":"XML", 28 | "name":"default_particle" 29 | }, 30 | "name":"fFParticleSprite", 31 | "particleId":"2", 32 | "texture":{ 33 | "cls":"starling.textures.Texture", 34 | "textureName":"meter_element_star_0" 35 | }, 36 | "x":325, 37 | "y":127.5 38 | } 39 | }, 40 | { 41 | "cls":"starlingbuilder.extensions.particle.FFParticleSprite", 42 | "customParams":{}, 43 | "params":{ 44 | "config":{ 45 | "cls":"XML", 46 | "name":"default_particle" 47 | }, 48 | "name":"fFParticleSprite", 49 | "particleId":"3", 50 | "texture":{ 51 | "cls":"starling.textures.Texture", 52 | "textureName":"generic_check_green" 53 | }, 54 | "x":486, 55 | "y":125 56 | } 57 | } 58 | ], 59 | "cls":"starling.display.Sprite", 60 | "customParams":{}, 61 | "params":{ 62 | "name":"root" 63 | } 64 | }, 65 | "setting":{ 66 | "canvasColor":65793, 67 | "canvasSize":{ 68 | "x":640, 69 | "y":960 70 | } 71 | }, 72 | "version":"1.0" 73 | } -------------------------------------------------------------------------------- /scaffold/assets/hello.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"starling.text.TextField", 6 | "constructorParams":[ 7 | { 8 | "value":200 9 | }, 10 | { 11 | "value":100 12 | }, 13 | { 14 | "value":"" 15 | }, 16 | { 17 | "name":"fontName", 18 | "value":"Verdana" 19 | }, 20 | { 21 | "value":46 22 | }, 23 | { 24 | "value":16777215 25 | } 26 | ], 27 | "customParams":{}, 28 | "params":{ 29 | "color":700465, 30 | "fontName":"Verdana", 31 | "fontSize":46, 32 | "height":70, 33 | "name":"Verdana", 34 | "text":"world", 35 | "width":158, 36 | "x":130 37 | } 38 | }, 39 | { 40 | "cls":"starling.text.TextField", 41 | "constructorParams":[ 42 | { 43 | "value":200 44 | }, 45 | { 46 | "value":100 47 | }, 48 | { 49 | "value":"" 50 | }, 51 | { 52 | "name":"fontName", 53 | "value":"Verdana" 54 | }, 55 | { 56 | "value":46 57 | }, 58 | { 59 | "value":16777215 60 | } 61 | ], 62 | "customParams":{}, 63 | "params":{ 64 | "color":3639506, 65 | "fontName":"Verdana", 66 | "fontSize":46, 67 | "height":70, 68 | "name":"hello", 69 | "text":"Hello", 70 | "width":130 71 | } 72 | } 73 | ], 74 | "cls":"starling.display.Sprite", 75 | "customParams":{}, 76 | "params":{ 77 | "name":"root" 78 | } 79 | }, 80 | "setting":{ 81 | "canvasColor":16777215, 82 | "canvasSize":{ 83 | "x":640, 84 | "y":960 85 | } 86 | }, 87 | "version":"1.0" 88 | } -------------------------------------------------------------------------------- /demo/assets/localization_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"starling.text.TextField", 6 | "constructorParams":[ 7 | { 8 | "value":200 9 | }, 10 | { 11 | "value":100 12 | }, 13 | { 14 | "value":"" 15 | }, 16 | { 17 | "name":"fontName", 18 | "value":"Verdana" 19 | }, 20 | { 21 | "value":46 22 | }, 23 | { 24 | "value":16777215 25 | } 26 | ], 27 | "customParams":{ 28 | "localizeKey":"hello" 29 | }, 30 | "params":{ 31 | "color":3523141, 32 | "fontName":"Verdana", 33 | "fontSize":46, 34 | "height":100, 35 | "name":"Verdana", 36 | "width":200, 37 | "x":144, 38 | "y":49.5 39 | } 40 | }, 41 | { 42 | "cls":"starling.text.TextField", 43 | "constructorParams":[ 44 | { 45 | "value":200 46 | }, 47 | { 48 | "value":100 49 | }, 50 | { 51 | "value":"" 52 | }, 53 | { 54 | "name":"fontName", 55 | "value":"Verdana" 56 | }, 57 | { 58 | "value":46 59 | }, 60 | { 61 | "value":16777215 62 | } 63 | ], 64 | "customParams":{ 65 | "localizeKey":"world" 66 | }, 67 | "params":{ 68 | "color":1305849, 69 | "fontName":"Verdana", 70 | "fontSize":46, 71 | "height":100, 72 | "name":"Verdana", 73 | "width":200, 74 | "x":144, 75 | "y":108 76 | } 77 | } 78 | ], 79 | "cls":"starling.display.Sprite", 80 | "customParams":{}, 81 | "params":{ 82 | "name":"root" 83 | } 84 | }, 85 | "setting":{ 86 | "canvasSize":{ 87 | "x":640, 88 | "y":960 89 | } 90 | }, 91 | "version":"1.0" 92 | } -------------------------------------------------------------------------------- /demo/src/feathers/utils/text/TextInputNavigation.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.text; 9 | /** 10 | * Functions for navigating text inputs with the keyboard. 11 | */ 12 | class TextInputNavigation 13 | { 14 | /** 15 | * @private 16 | */ 17 | private static var IS_WORD:EReg = ~/\w/; 18 | 19 | /** 20 | * @private 21 | */ 22 | private static var IS_WHITESPACE:EReg = ~/\s/; 23 | 24 | /** 25 | * Finds the start index of the word that starts before the selection. 26 | */ 27 | public static function findPreviousWordStartIndex(text:String, selectionStartIndex:Int):Int 28 | { 29 | if(selectionStartIndex <= 0) 30 | { 31 | return 0; 32 | } 33 | var nextCharIsWord:Bool = IS_WORD.match(text.charAt(selectionStartIndex - 1)); 34 | //for(var i:Int = selectionStartIndex - 2; i >= 0; i--) 35 | var i:Int = selectionStartIndex - 2; 36 | while(i >= 0) 37 | { 38 | var charIsWord:Bool = IS_WORD.match(text.charAt(i)); 39 | if(!charIsWord && nextCharIsWord) 40 | { 41 | return i + 1; 42 | } 43 | nextCharIsWord = charIsWord; 44 | i--; 45 | } 46 | return 0; 47 | } 48 | 49 | /** 50 | * Finds the start index of the next word that starts after the 51 | * selection. 52 | */ 53 | public static function findNextWordStartIndex(text:String, selectionEndIndex:Int):Int 54 | { 55 | var textLength:Int = text.length; 56 | if(selectionEndIndex >= textLength - 1) 57 | { 58 | return textLength; 59 | } 60 | //the first character is a special case. any non-whitespace is 61 | //considered part of the word. 62 | var prevCharIsWord:Bool = !IS_WHITESPACE.match(text.charAt(selectionEndIndex)); 63 | //for(var i:Int = selectionEndIndex + 1; i < textLength; i++) 64 | for(i in selectionEndIndex + 1 ... textLength) 65 | { 66 | var charIsWord:Bool = IS_WORD.match(text.charAt(i)); 67 | if(charIsWord && !prevCharIsWord) 68 | { 69 | return i; 70 | } 71 | prevCharIsWord = charIsWord; 72 | } 73 | return textLength; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/util/ObjectLocaterUtil.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.util; 9 | 10 | /** 11 | * @private 12 | */ 13 | class ObjectLocaterUtil 14 | { 15 | public static function set(obj:Dynamic, propertyName:String, value:Dynamic):Void 16 | { 17 | //handle dot access (e.g. foo.bar) 18 | var array:Array = propertyName.split("."); 19 | var lastName:String = array.pop(); 20 | 21 | var res:Dynamic = obj; 22 | 23 | for (name in array) 24 | { 25 | res = Reflect.field(res, name); 26 | } 27 | 28 | Reflect.setField(res, lastName, value); 29 | } 30 | 31 | public static function get(obj:Dynamic, propertyName:String):Dynamic 32 | { 33 | //handle dot access (e.g. foo.bar) 34 | var array:Array = propertyName.split("."); 35 | 36 | var res:Dynamic = obj; 37 | 38 | for (name in array) 39 | { 40 | res = Reflect.field(res, name); 41 | } 42 | 43 | return res; 44 | } 45 | 46 | public static function del(obj:Dynamic, propertyName:String):Void 47 | { 48 | var array:Array = propertyName.split("."); 49 | var lastName:String = array.pop(); 50 | 51 | var res:Dynamic = obj; 52 | 53 | for (name in array) 54 | { 55 | res = Reflect.field(res, name); 56 | } 57 | 58 | Reflect.deleteField(res, lastName); 59 | } 60 | 61 | public static function hasProperty(obj:Dynamic, propertyName:String):Bool 62 | { 63 | //handle dot access (e.g. foo.bar) 64 | var array:Array = propertyName.split("."); 65 | 66 | var res:Dynamic = obj; 67 | 68 | for (name in array) 69 | { 70 | if (Reflect.hasField(res, name)) 71 | { 72 | res = Reflect.field(res, name); 73 | } 74 | else 75 | { 76 | return false; 77 | } 78 | } 79 | 80 | return true; 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/display/FeathersDisplayUtil.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.display; 2 | import starling.core.Starling; 3 | import starling.display.DisplayObject; 4 | import starling.display.Stage; 5 | 6 | class FeathersDisplayUtil 7 | { 8 | 9 | /** 10 | * Calculates a scale value to maintain aspect ratio and fill the required 11 | * bounds (with the possibility of cutting of the edges a bit). 12 | */ 13 | public static function calculateScaleRatioToFill(originalWidth:Float, originalHeight:Float, targetWidth:Float, targetHeight:Float):Float 14 | { 15 | var widthRatio:Float = targetWidth / originalWidth; 16 | var heightRatio:Float = targetHeight / originalHeight; 17 | if(widthRatio > heightRatio) 18 | { 19 | return widthRatio; 20 | } 21 | return heightRatio; 22 | } 23 | 24 | /** 25 | * Calculates a scale value to maintain aspect ratio and fit inside the 26 | * required bounds (with the possibility of a bit of empty space on the 27 | * edges). 28 | */ 29 | public static function calculateScaleRatioToFit(originalWidth:Float, originalHeight:Float, targetWidth:Float, targetHeight:Float):Float 30 | { 31 | var widthRatio:Float = targetWidth / originalWidth; 32 | var heightRatio:Float = targetHeight / originalHeight; 33 | if(widthRatio < heightRatio) 34 | { 35 | return widthRatio; 36 | } 37 | return heightRatio; 38 | } 39 | 40 | /** 41 | * Calculates how many levels deep the target object is on the display list, 42 | * starting from the Starling stage. If the target object is the stage, the 43 | * depth will be 0. A direct child of the stage will have a 44 | * depth of 1, and it increases with each new level. If the 45 | * object does not have a reference to the stage, the depth will always be 46 | * -1, even if the object has a parent. 47 | */ 48 | public static function getDisplayObjectDepthFromStage(target:DisplayObject):Int 49 | { 50 | if(target.stage == null) 51 | { 52 | return -1; 53 | } 54 | var count:Int = 0; 55 | while(target.parent != null) 56 | { 57 | target = target.parent; 58 | count++; 59 | } 60 | return count; 61 | } 62 | 63 | public static function stageToStarling(stage:Stage):Starling 64 | { 65 | for (starling in Starling.all) 66 | { 67 | if(starling.stage == stage) 68 | { 69 | return starling; 70 | } 71 | } 72 | return null; 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/starlingbuilder/engine/tween/ITweenBuilder.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.tween; 9 | 10 | import starling.display.DisplayObject; 11 | 12 | /** 13 | * Interface of playing tween set by the editor. 14 | * 15 | *

16 | * You need to manually call start/stop in your project when you want to start/stop a tween. 17 | *
18 | * NOTE: The stop method should ALWAYS be called with the start method to avoid memory leak when the components are disposed. 19 | *
20 | * The following example shows how to start and stop a tween: 21 | *

22 | * 23 | * 24 | * var data:Object = uiBuilder.load(layoutData); 25 | * var sprite:Sprite = data.object as Sprite; 26 | * var paramsDict:Dictionary = data.params; 27 | *
28 | * uiBuilder.tweenBuilder.startTween(sprite, paramsDict); 29 | *
30 | * ... 31 | *
32 | * uiBuilder.tweenBuilder.stopTween(sprite);
33 | * 34 | * @see starlingbuilder.engine.UIBuilder 35 | */ 36 | interface ITweenBuilder 37 | { 38 | /** 39 | * Start tween according tweenData in layout 40 | * 41 | * @param root of the DisplayObjects need to tween 42 | * @param paramsDict A dictionary of the mapping of every UIElement to its layout data 43 | * @param names array of names (e.g. ["container.button1", "container.button2") to be start tween, if null then start all the available tween 44 | */ 45 | function start(root:DisplayObject, paramsDict:Map, names:Array = null):Void; 46 | 47 | /** 48 | * Stop tween according tweenData in layout 49 | * 50 | * @param root of the DisplayObject needs to be tween 51 | * @param paramsDict A dictionary of the mapping of every UIElement to its layout data, if null then stop all the available tweens 52 | * @param names array of names (e.g. ["container.button1", "container.button2") to be stop tween, if null then stop all the available tweens 53 | */ 54 | function stop(root:DisplayObject, paramsDict:Map = null, names:Array = null):Void; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/HUD.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.events.ResizeEvent; 11 | import starlingbuilder.engine.util.StageUtil; 12 | import starling.core.Starling; 13 | import starling.display.Button; 14 | import starling.display.Image; 15 | import starling.display.Sprite; 16 | import starling.display.Stage; 17 | import starling.events.Touch; 18 | import starling.events.TouchEvent; 19 | import starling.events.TouchPhase; 20 | 21 | class HUD extends Sprite 22 | { 23 | private var _sprite:Sprite; 24 | 25 | //auto bind variables 26 | public var _topContainer:Sprite; 27 | public var _bottomContainer:Sprite; 28 | public var _settingsButton:Button; 29 | 30 | public var _background:Image; 31 | 32 | public function new() 33 | { 34 | super(); 35 | 36 | _background = new Image(UIBuilderDemo.assetManager.getTexture("background")); 37 | addChild(_background); 38 | 39 | _sprite = cast UIBuilderDemo.uiBuilder.create(ParsedLayouts.hud, false, this); 40 | addChild(_sprite); 41 | 42 | onResize(null); 43 | 44 | addEventListener(TouchEvent.TOUCH, onTouchEvent); 45 | 46 | Starling.current.stage.addEventListener(ResizeEvent.RESIZE, onResize); 47 | } 48 | 49 | private function onTouchEvent(event:TouchEvent):Void 50 | { 51 | var touch:Touch = event.getTouch(this); 52 | if (touch != null && touch.phase == TouchPhase.ENDED) 53 | { 54 | removeFromParent(true); 55 | } 56 | } 57 | 58 | private function onResize(event:ResizeEvent):Void 59 | { 60 | var stage:Stage = Starling.current.stage; 61 | 62 | _topContainer.x = stage.stageWidth * 0.5; 63 | _topContainer.y = 0; 64 | 65 | _bottomContainer.x = stage.stageWidth * 0.5; 66 | _bottomContainer.y = stage.stageHeight; 67 | 68 | _settingsButton.x = stage.stageWidth + 4; 69 | _settingsButton.y = stage.stageHeight + 4; 70 | 71 | StageUtil.fitBackground(_background); 72 | } 73 | 74 | override public function dispose():Void 75 | { 76 | Starling.current.stage.removeEventListener(ResizeEvent.RESIZE, onResize); 77 | super.dispose(); 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /demo/assets/pixelmask_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "children":[ 6 | { 7 | "cls":"starling.display.Image", 8 | "constructorParams":[ 9 | { 10 | "cls":"starling.textures.Texture", 11 | "textureName":"meter_element_bg" 12 | } 13 | ], 14 | "customParams":{}, 15 | "params":{ 16 | "name":"meter_element_bg", 17 | "x":-2, 18 | "y":-1 19 | } 20 | }, 21 | { 22 | "children":[ 23 | { 24 | "cls":"starling.display.Image", 25 | "constructorParams":[ 26 | { 27 | "cls":"starling.textures.Texture", 28 | "textureName":"meter_element_fill" 29 | } 30 | ], 31 | "customParams":{}, 32 | "params":{ 33 | "name":"_fill", 34 | "pivotX":89, 35 | "pivotY":89, 36 | "rotation":-1.57, 37 | "x":89, 38 | "y":89 39 | }, 40 | "tweenData":{ 41 | "properties":{ 42 | "repeatCount":0, 43 | "rotation":4.71 44 | }, 45 | "time":2 46 | } 47 | } 48 | ], 49 | "cls":"starling.extensions.pixelmask.PixelMaskDisplayObject", 50 | "customParams":{}, 51 | "params":{ 52 | "name":"pixelMaskDisplayObject", 53 | "pixelMask":{ 54 | "cls":"starling.display.Image", 55 | "constructorParams":[ 56 | { 57 | "cls":"starling.textures.Texture", 58 | "textureName":"meter_element_fill" 59 | } 60 | ], 61 | "customParams":{}, 62 | "params":{ 63 | "name":null 64 | } 65 | } 66 | } 67 | } 68 | ], 69 | "cls":"starling.display.Sprite", 70 | "customParams":{}, 71 | "params":{ 72 | "name":"sprite", 73 | "x":129, 74 | "y":77 75 | } 76 | } 77 | ], 78 | "cls":"starling.display.Sprite", 79 | "customParams":{}, 80 | "params":{ 81 | "name":"root" 82 | } 83 | }, 84 | "setting":{ 85 | "canvasColor":16777215, 86 | "canvasSize":{ 87 | "x":640, 88 | "y":960 89 | } 90 | }, 91 | "version":"1.0" 92 | } -------------------------------------------------------------------------------- /demo/assets/tween_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"starling.display.Image", 6 | "constructorParams":[ 7 | { 8 | "cls":"starling.textures.Texture", 9 | "textureName":"boostslot_bg_green" 10 | } 11 | ], 12 | "customParams":{}, 13 | "params":{ 14 | "name":"boostslot_bg_green", 15 | "pivotX":67, 16 | "pivotY":51, 17 | "x":189.5, 18 | "y":224.5 19 | }, 20 | "tweenData":{ 21 | "properties":{ 22 | "repeatCount":0, 23 | "reverse":true, 24 | "scaleX":0.9, 25 | "scaleY":0.9 26 | }, 27 | "time":1 28 | } 29 | }, 30 | { 31 | "cls":"starling.display.Image", 32 | "constructorParams":[ 33 | { 34 | "cls":"starling.textures.Texture", 35 | "textureName":"generic_button_blue" 36 | } 37 | ], 38 | "customParams":{}, 39 | "params":{ 40 | "name":"generic_button_blue", 41 | "pivotX":132.5, 42 | "pivotY":55, 43 | "x":445, 44 | "y":96 45 | }, 46 | "tweenData":[ 47 | { 48 | "properties":{ 49 | "repeatCount":0, 50 | "reverse":true, 51 | "scaleX":0.9, 52 | "scaleY":0.9 53 | }, 54 | "time":1 55 | }, 56 | { 57 | "properties":{ 58 | "alpha":0, 59 | "repeatCount":0, 60 | "reverse":true 61 | }, 62 | "time":0.2 63 | } 64 | ] 65 | }, 66 | { 67 | "cls":"starling.display.Image", 68 | "constructorParams":[ 69 | { 70 | "cls":"starling.textures.Texture", 71 | "textureName":"meter_element_star_0" 72 | } 73 | ], 74 | "customParams":{}, 75 | "params":{ 76 | "name":"meter_element_star_0", 77 | "pivotX":25.5, 78 | "pivotY":24.5, 79 | "x":369, 80 | "y":257 81 | }, 82 | "tweenData":{ 83 | "properties":{ 84 | "repeatCount":0, 85 | "rotation":6.28 86 | }, 87 | "time":2 88 | } 89 | } 90 | ], 91 | "cls":"starling.display.Sprite", 92 | "customParams":{}, 93 | "params":{ 94 | "name":"root" 95 | } 96 | }, 97 | "setting":{ 98 | "canvasSize":{ 99 | "x":640, 100 | "y":960 101 | } 102 | }, 103 | "version":"1.0" 104 | } -------------------------------------------------------------------------------- /demo/src/starlingbuilder/demo/LocalizationTest.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.demo; 9 | 10 | import starling.display.Button; 11 | import starling.core.Starling; 12 | 13 | import starling.display.Quad; 14 | 15 | import starling.display.Sprite; 16 | import starling.display.Stage; 17 | import starling.events.Event; 18 | import starling.events.Touch; 19 | import starling.events.TouchEvent; 20 | import starling.events.TouchPhase; 21 | 22 | class LocalizationTest extends Sprite 23 | { 24 | private var _sprite:Sprite; 25 | private var _params:Map; 26 | 27 | public function new() 28 | { 29 | super(); 30 | 31 | var stage:Stage = Starling.current.stage; 32 | var quad:Quad = new Quad(stage.stageWidth, stage.stageHeight); 33 | addChild(quad); 34 | 35 | var data:Dynamic = UIBuilderDemo.uiBuilder.load(ParsedLayouts.localization_test, false); 36 | _sprite = data.object; 37 | _params = data.params; 38 | addChild(_sprite); 39 | 40 | var sprite:Sprite = new Sprite(); 41 | var data:Array = [ 42 | {label:"en_US"}, 43 | {label:"de_DE"}, 44 | {label:"es_ES"}, 45 | {label:"fr_FR"}, 46 | {label:"cn_ZH"} 47 | ]; 48 | 49 | for (i in 0...data.length) 50 | { 51 | var button:Button = new Button(UIBuilderDemo.assetManager.getTexture("blue_button")); 52 | button.text = data[i].label; 53 | button.fontColor = 0xffffff; 54 | button.fontName = "GrilledCheeseBTN_Size36_ColorFFFFFF"; 55 | button.fontSize = 30; 56 | button.y = (button.height + 10) * i; 57 | button.addEventListener(Event.TRIGGERED, onButton); 58 | sprite.addChild(button); 59 | } 60 | 61 | sprite.y = 300; 62 | 63 | addChild(sprite); 64 | 65 | quad.addEventListener(TouchEvent.TOUCH, onTouchEvent); 66 | } 67 | 68 | private function onTouchEvent(event:TouchEvent):Void 69 | { 70 | var touch:Touch = event.getTouch(this); 71 | if (touch != null && touch.phase == TouchPhase.ENDED) 72 | { 73 | removeFromParent(true); 74 | } 75 | } 76 | 77 | private function onButton(event:Event, data:Dynamic):Void 78 | { 79 | var locale:String = cast(event.target, Button).text; 80 | 81 | UIBuilderDemo.uiBuilder.localization.locale = locale; 82 | UIBuilderDemo.uiBuilder.localizeTexts(_sprite, _params); 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /demo/assets/mail_popup.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"feathers.display.Scale3Image", 6 | "constructorParams":[ 7 | { 8 | "cls":"feathers.textures.Scale3Textures", 9 | "scaleRatio":[ 10 | 0.28, 11 | 0.3, 12 | "vertical" 13 | ], 14 | "textureName":"generic_popup_bg" 15 | } 16 | ], 17 | "customParams":{}, 18 | "params":{ 19 | "height":645, 20 | "name":"generic_popup_bg", 21 | "width":638, 22 | "x":-1.5, 23 | "y":51 24 | } 25 | }, 26 | { 27 | "cls":"starling.display.Button", 28 | "constructorParams":[ 29 | { 30 | "cls":"starling.textures.Texture", 31 | "textureName":"generic_exit" 32 | } 33 | ], 34 | "customParams":{}, 35 | "params":{ 36 | "height":73, 37 | "name":"_exitButton", 38 | "width":77, 39 | "x":559.5, 40 | "y":41 41 | } 42 | }, 43 | { 44 | "cls":"starling.display.Image", 45 | "constructorParams":[ 46 | { 47 | "cls":"starling.textures.Texture", 48 | "textureName":"title_bg" 49 | } 50 | ], 51 | "customParams":{}, 52 | "params":{ 53 | "name":"title_bg", 54 | "x":108, 55 | "y":16.5 56 | } 57 | }, 58 | { 59 | "cls":"starling.text.TextField", 60 | "constructorParams":[ 61 | { 62 | "value":200 63 | }, 64 | { 65 | "value":100 66 | }, 67 | { 68 | "value":"Abc123" 69 | }, 70 | { 71 | "value":"Verdana" 72 | }, 73 | { 74 | "value":46 75 | }, 76 | { 77 | "value":16777215 78 | } 79 | ], 80 | "customParams":{}, 81 | "params":{ 82 | "autoSize":"bothDirections", 83 | "fontName":"LobsterTwoRegular_Size54_ColorFFFFFF_StrokeAF384E_DropShadow560D1B", 84 | "fontSize":55, 85 | "height":58.06, 86 | "name":"LobsterTwoRegular_Size54_ColorFFFFFF_StrokeAF384E_DropShadow560D1B", 87 | "text":"Inbox", 88 | "width":135.46, 89 | "x":249.77, 90 | "y":36 91 | } 92 | }, 93 | { 94 | "cls":"feathers.controls.List", 95 | "customParams":{}, 96 | "params":{ 97 | "height":515, 98 | "name":"_list", 99 | "width":534, 100 | "x":54.5, 101 | "y":122 102 | } 103 | } 104 | ], 105 | "cls":"starling.display.Sprite", 106 | "customParams":{ 107 | "container":1 108 | }, 109 | "params":{ 110 | "name":null 111 | } 112 | }, 113 | "setting":{ 114 | "canvasColor":16777215, 115 | "canvasSize":{ 116 | "x":640, 117 | "y":860 118 | } 119 | }, 120 | "version":"1.0" 121 | } -------------------------------------------------------------------------------- /demo/src/feathers/display/RenderDelegate.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.display; 9 | import flash.geom.Matrix; 10 | import flash.geom.Point; 11 | import flash.geom.Rectangle; 12 | import starling.utils.Max; 13 | 14 | import starling.core.RenderSupport; 15 | import starling.display.DisplayObject; 16 | import starling.utils.MatrixUtil; 17 | 18 | /** 19 | * Passes rendering to another display object, but provides its own separate 20 | * transformation. 21 | * 22 | *

Touching the delegate does not pass touches to the target. The 23 | * delegate is a separate display object. However, interacting with the 24 | * target may affect the rendering of the delegate.

25 | */ 26 | class RenderDelegate extends DisplayObject 27 | { 28 | /** 29 | * @private 30 | */ 31 | private static var HELPER_MATRIX:Matrix = new Matrix(); 32 | 33 | /** 34 | * @private 35 | */ 36 | private static var HELPER_POINT:Point = new Point(); 37 | 38 | /** 39 | * Constructor. 40 | */ 41 | public function new(target:DisplayObject) 42 | { 43 | super(); 44 | this._target = target; 45 | } 46 | 47 | /** 48 | * @private 49 | */ 50 | private var _target:DisplayObject; 51 | 52 | /** 53 | * The displaying object being rendered. 54 | */ 55 | public function get_target():DisplayObject 56 | { 57 | return this._target; 58 | } 59 | 60 | /** 61 | * @private 62 | */ 63 | public function set_target(value:DisplayObject):DisplayObject 64 | { 65 | this._target = value; 66 | return get_target(); 67 | } 68 | 69 | /** 70 | * @private 71 | */ 72 | override public function getBounds(targetSpace:DisplayObject, resultRect:Rectangle = null):Rectangle 73 | { 74 | resultRect = this._target.getBounds(this._target, resultRect); 75 | this.getTransformationMatrix(targetSpace, HELPER_MATRIX); 76 | var minX:Float = Max.MAX_VALUE; 77 | var maxX:Float = -Max.MAX_VALUE; 78 | var minY:Float = Max.MAX_VALUE; 79 | var maxY:Float = -Max.MAX_VALUE; 80 | //for(var i:Int = 0; i < 4; i++) 81 | for(i in 0 ... 4) 82 | { 83 | MatrixUtil.transformCoords(HELPER_MATRIX, i % 2 == 0 ? 0 : resultRect.width, i < 2 ? 0 : resultRect.height, HELPER_POINT); 84 | if(HELPER_POINT.x < minX) 85 | { 86 | minX = HELPER_POINT.x; 87 | } 88 | if(HELPER_POINT.x > maxX) 89 | { 90 | maxX = HELPER_POINT.x; 91 | } 92 | if(HELPER_POINT.y < minY) 93 | { 94 | minY = HELPER_POINT.y; 95 | } 96 | if(HELPER_POINT.y > maxY) 97 | { 98 | maxY = HELPER_POINT.y; 99 | } 100 | } 101 | resultRect.setTo(minX, minY, maxX - minX, maxY - minY); 102 | return resultRect; 103 | } 104 | 105 | /** 106 | * @private 107 | */ 108 | override public function render(support:RenderSupport, parentAlpha:Float):Void 109 | { 110 | var oldAlpha:Float = this._target.alpha; 111 | this._target.alpha = this.alpha; 112 | this._target.render(support, parentAlpha); 113 | this._target.alpha = oldAlpha; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IFeathersEventDispatcher.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | import starling.events.Event; 10 | 11 | import haxe.Constraints.Function; 12 | 13 | /** 14 | * Public properties and functions from starling.events.EventDispatcher 15 | * in helpful interface form. 16 | * 17 | *

Never cast an object to this type. Cast to EventDispatcher 18 | * instead. This interface exists only to support easier code hinting for 19 | * interfaces.

20 | * 21 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html starling.events.EventDispatcher 22 | */ 23 | interface IFeathersEventDispatcher 24 | { 25 | /** 26 | * Adds a listener for an event type. 27 | * 28 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html#addEventListener() Full description of starling.events.EventDispatcher.addEventListener() in Gamua's Starling Framework API Reference 29 | */ 30 | function addEventListener(type:String, listener:Function):Void; 31 | 32 | /** 33 | * Removes a listener for an event type. 34 | * 35 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html#removeEventListener() Full description of starling.events.EventDispatcher.addEventListener() in Gamua's Starling Framework API Reference 36 | */ 37 | function removeEventListener(type:String, listener:Function):Void; 38 | 39 | /** 40 | * Removes all listeners for an event type. 41 | * 42 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html#removeEventListeners() Full description of starling.events.EventDispatcher.removeEventListeners() in Gamua's Starling Framework API Reference 43 | */ 44 | function removeEventListeners(type:String = null):Void; 45 | 46 | /** 47 | * Dispatches an event to all listeners added for the specified event type. 48 | * 49 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html#dispatchEvent() Full description of starling.events.EventDispatcher.dispatchEvent() in Gamua's Starling Framework API Reference 50 | */ 51 | function dispatchEvent(event:Event):Void; 52 | 53 | /** 54 | * Dispatches an event from the pool with the specified to all listeners 55 | * for the specified event type. 56 | * 57 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html#dispatchEventWith() Full description of starling.events.EventDispatcher.dispatchEventWith() in Gamua's Starling Framework API Reference 58 | */ 59 | function dispatchEventWith(type:String, bubbles:Bool = false, data:Dynamic = null):Void; 60 | 61 | /** 62 | * Checks if a listener has been added for the specified event type. 63 | * 64 | * @see http://doc.starling-framework.org/core/starling/events/EventDispatcher.html#hasEventListener() Full description of starling.events.EventDispatcher.hasEventListener() in Gamua's Starling Framework API Reference 65 | */ 66 | function hasEventListener(type:String):Bool; 67 | } 68 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/IUIBuilder.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine; 9 | 10 | import starling.display.DisplayObject; 11 | 12 | import starlingbuilder.engine.localization.ILocalization; 13 | 14 | import starlingbuilder.engine.localization.ILocalizationHandler; 15 | 16 | import starlingbuilder.engine.tween.ITweenBuilder; 17 | 18 | /** 19 | * Main interface of the Starling Builder engine API 20 | * 21 | * @see UIBuilder 22 | */ 23 | interface IUIBuilder 24 | { 25 | /** 26 | * Load from layout data, create display objects and the associated meta data 27 | * 28 | * @param data 29 | * layout data 30 | * 31 | * @param trimLeadingSpace 32 | * whether to trim the leading space on the top level elements 33 | * set to true if loading a popup, set to false if loading a hud 34 | * 35 | * @param binder 36 | * An optional object you want to bind properties with UI components with the same name, if name starts with "_" 37 | * 38 | * @return 39 | * An object with {object:Sprite, params:Dictionary, data:data}; 40 | * 41 | *

object: the sprite to create

42 | *

params: A Dictionary of the mapping of every UIElement to its layout data

43 | *

data: the as3 plain object format of the layout

44 | * 45 | * @see #create() 46 | * 47 | */ 48 | function load(data:Dynamic, trimLeadingSpace:Bool = true, binder:Dynamic = null):Dynamic; 49 | 50 | 51 | /** 52 | * Create UI element from data 53 | * 54 | * @param data 55 | * data in as3 plain object format 56 | * 57 | * @return 58 | * starling display object 59 | */ 60 | function createUIElement(data:Dynamic):Dynamic; 61 | 62 | /** 63 | * Localize texts in display object 64 | * 65 | * @param root of the DisplayObject needs to be localize 66 | * @param A Dictionary of the mapping of every UIElement to its layout data 67 | */ 68 | function localizeTexts(root:DisplayObject, paramsDict:Map):Void; 69 | 70 | 71 | /** 72 | * Create display objects from layout. 73 | * Short cut for load().object 74 | * 75 | * @see #load() 76 | */ 77 | function create(data:Dynamic, trimLeadingSpace:Bool = true, binder:Dynamic = null):Dynamic; 78 | 79 | 80 | /** 81 | * Tween builder property 82 | */ 83 | public var tweenBuilder(get, set):ITweenBuilder; 84 | 85 | /** 86 | * Localization property 87 | */ 88 | public var localization(get, set):ILocalization; 89 | 90 | /** 91 | * Localization handler 92 | */ 93 | public var localizationHandler(get, set):ILocalizationHandler; 94 | 95 | /** 96 | * Display object handler 97 | */ 98 | public var displayObjectHandler(get, set):IDisplayObjectHandler; 99 | 100 | } 101 | 102 | -------------------------------------------------------------------------------- /demo/theme/src/feathers/themes/MetalWorksMobileTheme.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012-2015 Bowler Hat LLC 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | package feathers.themes; 26 | import openfl.display.Bitmap; 27 | import openfl.display.BitmapData; 28 | import openfl.Assets; 29 | 30 | import starling.events.Event; 31 | import starling.textures.Texture; 32 | import starling.textures.TextureAtlas; 33 | 34 | /** 35 | * The "Metal Works" theme for mobile Feathers apps. 36 | * 37 | *

This version of the theme embeds its assets. To load assets at 38 | * runtime, see MetalWorksMobileThemeWithAssetManager instead.

39 | * 40 | * @see http://feathersui.com/help/theme-assets.html 41 | */ 42 | class MetalWorksMobileTheme extends BaseMetalWorksMobileTheme 43 | { 44 | /** 45 | * @private 46 | */ 47 | //[Embed(source="/../assets/images/metalworks_mobile.xml",mimeType="application/octet-stream")] 48 | //private static var ATLAS_XML:Class; 49 | inline public static var ATLAS_XML_NAME = "assets/images/metalworks_mobile.xml"; 50 | 51 | /** 52 | * @private 53 | */ 54 | //[Embed(source="/../assets/images/metalworks_mobile.png")] 55 | //private static var ATLAS_BITMAP:Class; 56 | inline public static var ATLAS_BITMAP_NAME = "assets/images/metalworks_mobile.png"; 57 | 58 | /** 59 | * Constructor. 60 | */ 61 | public function new(scaleToDPI:Bool = true) 62 | { 63 | super(scaleToDPI); 64 | this.initialize(); 65 | this.dispatchEventWith(Event.COMPLETE); 66 | } 67 | 68 | /** 69 | * @private 70 | */ 71 | override private function initialize():Void 72 | { 73 | this.initializeTextureAtlas(); 74 | super.initialize(); 75 | } 76 | 77 | /** 78 | * @private 79 | */ 80 | private function initializeTextureAtlas():Void 81 | { 82 | var atlasBitmapData:BitmapData = Assets.getBitmapData(ATLAS_BITMAP_NAME); 83 | var atlasTexture:Texture = Texture.fromBitmapData(atlasBitmapData, false); 84 | atlasTexture.root.onRestore = this.atlasTexture_onRestore; 85 | atlasBitmapData.dispose(); 86 | this.atlas = new TextureAtlas(atlasTexture, Xml.parse(Assets.getText(ATLAS_XML_NAME))); 87 | } 88 | 89 | /** 90 | * @private 91 | */ 92 | private function atlasTexture_onRestore():Void 93 | { 94 | var atlasBitmapData:BitmapData = Assets.getBitmapData(ATLAS_BITMAP_NAME); 95 | this.atlas.texture.root.uploadBitmapData(atlasBitmapData); 96 | atlasBitmapData.dispose(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/IAssetMediator.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine; 9 | 10 | import openfl.Vector; 11 | import starling.textures.Texture; 12 | 13 | /** 14 | * Interface for getting assets from the project 15 | * 16 | *

17 | * You should implement your AssetMediator in your project. 18 | * It can be a simple wrapper of starling.utils.AssetManager. 19 | *

20 | * 21 | * The following example is a simple implementation of IAssetMediator 22 | * 23 | * 24 | * public class AssetMediator 25 | * { 26 | * private var _assetManager:AssetManager; 27 | *
28 | * public function AssetMediator(assetManager:AssetManager) 29 | * { 30 | * _assetManager = assetManager; 31 | * } 32 | *
33 | * public function getTexture(name:String):Texture 34 | * { 35 | * return _assetManager.getTexture(name); 36 | * } 37 | *
38 | * public function getTextures(prefix:String="", result:Vector.<Texture>=null):Vector.<Texture> 39 | * { 40 | * return _assetManager.getTextures(prefix, result); 41 | * } 42 | *
43 | * public function getExternalData(name:String):Object 44 | * { 45 | * return null; 46 | * } 47 | * }
48 | * 49 | * @see UIBuilder 50 | */ 51 | interface IAssetMediator 52 | { 53 | /** 54 | * Get texture by name. 55 | * This method has the same signature of starling.utils.AssetManager.getTexture 56 | * @param name name of the texture 57 | * @return texture with matched name 58 | */ 59 | function getTexture(name:String):Texture; 60 | 61 | /** 62 | * Get textures by prefix. 63 | * This method has the same signature of starling.utils.AssetManager.getTextures 64 | * Only used by MovieClip. 65 | * @param prefix prefix of the textures 66 | * @param result vector of the matched textures to return 67 | * @return vector of the matched textures 68 | */ 69 | function getTextures(prefix:String = "", result:Vector = null):Vector; 70 | 71 | /** 72 | * Get external data by name. 73 | * Only used by loading external data (a layout referencing other layouts) 74 | * @param name of the layout 75 | * @return external data with matched name 76 | */ 77 | function getExternalData(name:String):Dynamic; 78 | 79 | /** 80 | * This method is used to get XML data. 81 | * You can make it simply return null if you don't use the feature. 82 | * @param name 83 | * @return 84 | */ 85 | function getXml(name:String):Xml; 86 | 87 | /** 88 | * This method is used to get other data (JSON data, etc) 89 | * You can make it simply return null if you don't use the feature. 90 | * @param name 91 | * @return 92 | */ 93 | function getObject(name:String):Dynamic; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/math/FeathersMathUtil.hx: -------------------------------------------------------------------------------- 1 | package feathers.utils.math; 2 | import openfl.display.OpenGLView; 3 | import openfl.errors.ArgumentError; 4 | 5 | /** 6 | * ... 7 | * @author ... 8 | */ 9 | class FeathersMathUtil 10 | { 11 | 12 | /** 13 | * Forces a numeric value into a specified range. 14 | * 15 | * @param value The value to force into the range. 16 | * @param minimum The minimum bound of the range. 17 | * @param maximum The maximum bound of the range. 18 | * @return A value within the specified range. 19 | * 20 | * @author Josh Tynjala (joshblog.net) 21 | */ 22 | public static function clamp(value:Float, minimum:Float, maximum:Float):Float 23 | { 24 | if(minimum > maximum) 25 | { 26 | throw new ArgumentError("minimum should be smaller than maximum."); 27 | } 28 | if(value < minimum) 29 | { 30 | value = minimum; 31 | } 32 | else if(value > maximum) 33 | { 34 | value = maximum; 35 | } 36 | return value; 37 | } 38 | 39 | /** 40 | * Rounds a Float down to the nearest multiple of an input. For example, by rounding 41 | * 16 down to the nearest 10, you will receive 10. Similar to the built-in function Math.floor(). 42 | * 43 | * @param numberToRound the number to round down 44 | * @param nearest the number whose mutiple must be found 45 | * @return the rounded number 46 | * 47 | * @see Math#floor 48 | */ 49 | public static function roundDownToNearest(number:Float, nearest:Float = 1):Float 50 | { 51 | if(nearest == 0) 52 | { 53 | return number; 54 | } 55 | return Math.floor(roundToPrecision(number / nearest, 10)) * nearest; 56 | } 57 | 58 | /** 59 | * Rounds a Float to the nearest multiple of an input. For example, by rounding 60 | * 16 to the nearest 10, you will receive 20. Similar to the built-in function Math.round(). 61 | * 62 | * @param numberToRound the number to round 63 | * @param nearest the number whose mutiple must be found 64 | * @return the rounded number 65 | * 66 | * @see Math#round 67 | */ 68 | public static function roundToNearest(number:Float, nearest:Float = 1):Float 69 | { 70 | if(nearest == 0) 71 | { 72 | return number; 73 | } 74 | var roundedFloat:Float = Math.round(roundToPrecision(number / nearest, 10)) * nearest; 75 | return roundToPrecision(roundedFloat, 10); 76 | } 77 | 78 | /** 79 | * Rounds a number to a certain level of precision. Useful for limiting the number of 80 | * decimal places on a fractional number. 81 | * 82 | * @param number the input number to round. 83 | * @param precision the number of decimal digits to keep 84 | * @return the rounded number, or the original input if no rounding is needed 85 | * 86 | * @see Math#round 87 | */ 88 | public static function roundToPrecision(number:Float, precision:Int = 0):Float 89 | { 90 | var decimalPlaces:Float = Math.pow(10, precision); 91 | return Math.round(decimalPlaces * number) / decimalPlaces; 92 | } 93 | 94 | /** 95 | * Rounds a Float up to the nearest multiple of an input. For example, by rounding 96 | * 16 up to the nearest 10, you will receive 20. Similar to the built-in function Math.ceil(). 97 | * 98 | * @param numberToRound the number to round up 99 | * @param nearest the number whose mutiple must be found 100 | * @return the rounded number 101 | * 102 | * @see Math#ceil 103 | */ 104 | public static function roundUpToNearest(number:Float, nearest:Float = 1):Float 105 | { 106 | if(nearest == 0) 107 | { 108 | return number; 109 | } 110 | return Math.ceil(roundToPrecision(number / nearest, 10)) * nearest; 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /demo/assets/mail_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"feathers.controls.List", 6 | "customParams":{ 7 | "forEditor":true 8 | }, 9 | "params":{ 10 | "height":515, 11 | "name":"obj1", 12 | "width":534, 13 | "x":53, 14 | "y":166 15 | } 16 | }, 17 | { 18 | "cls":"feathers.display.Scale9Image", 19 | "constructorParams":[ 20 | { 21 | "cls":"feathers.textures.Scale9Textures", 22 | "scaleRatio":[ 23 | 0.3, 24 | 0.3, 25 | 0.4, 26 | 0.4 27 | ], 28 | "textureName":"generic_box_white" 29 | } 30 | ], 31 | "customParams":{}, 32 | "params":{ 33 | "height":112, 34 | "name":"generic_box_white", 35 | "width":517, 36 | "x":62, 37 | "y":172.5 38 | } 39 | }, 40 | { 41 | "cls":"starling.display.Image", 42 | "constructorParams":[ 43 | { 44 | "cls":"starling.textures.Texture", 45 | "textureName":"generic_gift" 46 | } 47 | ], 48 | "customParams":{}, 49 | "params":{ 50 | "name":"generic_gift", 51 | "scaleX":1.01, 52 | "scaleY":1.01, 53 | "x":493, 54 | "y":186 55 | } 56 | }, 57 | { 58 | "cls":"starling.display.Image", 59 | "constructorParams":[ 60 | { 61 | "cls":"starling.textures.Texture", 62 | "textureName":"generic_app_icon" 63 | } 64 | ], 65 | "customParams":{}, 66 | "params":{ 67 | "name":"generic_app_icon", 68 | "scaleY":1.01, 69 | "x":132, 70 | "y":186 71 | } 72 | }, 73 | { 74 | "cls":"starling.text.TextField", 75 | "constructorParams":[ 76 | { 77 | "value":200 78 | }, 79 | { 80 | "value":100 81 | }, 82 | { 83 | "value":"Abc123" 84 | }, 85 | { 86 | "name":"fontName", 87 | "value":"GrilledCheeseBTN_Size36_ColorFFFFFF" 88 | }, 89 | { 90 | "value":46 91 | }, 92 | { 93 | "value":16777215 94 | } 95 | ], 96 | "customParams":{}, 97 | "params":{ 98 | "autoScale":true, 99 | "color":12273920, 100 | "fontName":"GrilledCheeseBTN_Size36_ColorFFFFFF", 101 | "fontSize":37, 102 | "height":46, 103 | "name":"_text", 104 | "text":"You received a gift!", 105 | "width":267, 106 | "x":215, 107 | "y":204.5 108 | } 109 | }, 110 | { 111 | "cls":"starling.display.Image", 112 | "constructorParams":[ 113 | { 114 | "cls":"starling.textures.Texture", 115 | "textureName":"generic_check_bg" 116 | } 117 | ], 118 | "customParams":{}, 119 | "params":{ 120 | "name":"generic_check_bg", 121 | "x":71, 122 | "y":201.5 123 | } 124 | } 125 | ], 126 | "cls":"starling.display.Sprite", 127 | "customParams":{ 128 | "container":1 129 | }, 130 | "params":{ 131 | "name":null 132 | } 133 | }, 134 | "setting":{ 135 | "canvasColor":16777215, 136 | "canvasSize":{ 137 | "x":640, 138 | "y":960 139 | } 140 | }, 141 | "version":"1.0" 142 | } -------------------------------------------------------------------------------- /src/starlingbuilder/engine/LayoutLoader.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine; 9 | 10 | import haxe.Json; 11 | import openfl.Assets; 12 | 13 | /** 14 | * Helper class to load layouts 15 | * 16 | *

This class provide an easy and efficient way to load layout files from embedded data, parse the data and cached it into memory. 17 | * The following example load and parse the layout data from EmbeddedLayout class to ParsedLayout class: 18 | *

19 | * 20 | * 21 | * public class EmbeddedLayout 22 | * { 23 | * [Embed(source="layouts/connect_popup.json", mimeType="application/octet-stream")] 24 | * public static const connect_popup:Class; 25 | *
26 | * [Embed(source="layouts/mail_popup.json", mimeType="application/octet-stream")] 27 | * public static const mail_popup:Class; 28 | * } 29 | *
30 | * public class ParsedLayout 31 | * { 32 | * public static var connect_popup:Object; 33 | *
34 | * public static var mail_popup:Object; 35 | * } 36 | *
37 | * //loader with preload option 38 | * var loader:LayoutLoader = new LayoutLoader(EmbeddedLayout, ParsedLayout); 39 | * var sprite:Sprite = uiBuilder.create(ParsedLayout.connect_popup) as Sprite; 40 | *
41 | * //loader without preload option 42 | * var loader2:LayoutLoader = new LayoutLoader(EmbeddedLayout, ParsedLayout, false); 43 | * var sprite2:Sprite = uiBuilder.create(loader2.loadByClass(EmbeddedLayout.connect_popup));
44 | * 45 | * @see http://github.com/mindjolt/starling-builder-engine/tree/master/demo Starling Builder demo project 46 | * 47 | */ 48 | class LayoutLoader 49 | { 50 | private var _layoutCls:Class; 51 | private var _preload:Bool; 52 | 53 | /** 54 | * Constructor 55 | * @param embeddedCls class with embedded layout 56 | * @param layoutCls class with parsed layout 57 | * @param preload whether to preload it. If set to true, calling load() or loadByClass() is not necessary 58 | */ 59 | public function new(layoutCls:Class, preload:Bool = true) 60 | { 61 | _layoutCls = layoutCls; 62 | _preload = preload; 63 | 64 | if (_preload) 65 | preloadLayouts(); 66 | } 67 | 68 | /** 69 | * Load a layout with name, only need to use it when preload = false 70 | * @param name layout name 71 | * @return parsed as3 object 72 | */ 73 | public function load(name:String):Dynamic 74 | { 75 | var value:Dynamic = Reflect.getProperty(_layoutCls, name); 76 | 77 | if (value == null) 78 | { 79 | value = Json.parse(Assets.getText(name)); 80 | Reflect.setProperty(_layoutCls, name, value); 81 | } 82 | 83 | return value; 84 | } 85 | 86 | /** 87 | * Traverse all the public static variable of the embedded class, parse and assign to the same public static variable of the layout class 88 | */ 89 | private function preloadLayouts():Void 90 | { 91 | for (name in Type.getClassFields(_layoutCls)) 92 | { 93 | var obj = Reflect.getProperty(_layoutCls, name); 94 | 95 | if (obj == null) 96 | Reflect.setField(_layoutCls, name, Json.parse(Assets.getText("assets/" + name + ".json"))); 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /demo/assets/connect_popup.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout":{ 3 | "children":[ 4 | { 5 | "cls":"feathers.display.Scale3Image", 6 | "constructorParams":[ 7 | { 8 | "cls":"feathers.textures.Scale3Textures", 9 | "scaleRatio":[ 10 | 0.28, 11 | 0.3, 12 | "vertical" 13 | ], 14 | "textureName":"generic_popup_bg" 15 | } 16 | ], 17 | "customParams":{}, 18 | "params":{ 19 | "height":645, 20 | "name":"generic_popup_bg", 21 | "width":638, 22 | "x":-1.5, 23 | "y":51 24 | } 25 | }, 26 | { 27 | "cls":"feathers.display.Scale9Image", 28 | "constructorParams":[ 29 | { 30 | "cls":"feathers.textures.Scale9Textures", 31 | "scaleRatio":[ 32 | 0.3, 33 | 0.3, 34 | 0.4, 35 | 0.4 36 | ], 37 | "textureName":"generic_box_white" 38 | } 39 | ], 40 | "customParams":{}, 41 | "params":{ 42 | "height":453, 43 | "name":"generic_box_white", 44 | "width":550, 45 | "x":42.5, 46 | "y":83.5 47 | } 48 | }, 49 | { 50 | "cls":"starling.display.Button", 51 | "constructorParams":[ 52 | { 53 | "cls":"starling.textures.Texture", 54 | "textureName":"generic_exit" 55 | } 56 | ], 57 | "customParams":{}, 58 | "params":{ 59 | "height":74, 60 | "name":"generic_exit", 61 | "scaleY":1.01, 62 | "width":77, 63 | "x":559.5, 64 | "y":41 65 | } 66 | }, 67 | { 68 | "cls":"starling.display.Image", 69 | "constructorParams":[ 70 | { 71 | "cls":"starling.textures.Texture", 72 | "textureName":"title_bg" 73 | } 74 | ], 75 | "customParams":{}, 76 | "params":{ 77 | "name":"title_bg", 78 | "x":108, 79 | "y":16.5 80 | } 81 | }, 82 | { 83 | "cls":"starling.display.Image", 84 | "constructorParams":[ 85 | { 86 | "cls":"starling.textures.Texture", 87 | "textureName":"connectFB_image" 88 | } 89 | ], 90 | "customParams":{}, 91 | "params":{ 92 | "name":"connectFB_image", 93 | "x":73, 94 | "y":122.5 95 | } 96 | }, 97 | { 98 | "cls":"starling.text.TextField", 99 | "constructorParams":[ 100 | { 101 | "value":200 102 | }, 103 | { 104 | "value":100 105 | }, 106 | { 107 | "value":"Abc123" 108 | }, 109 | { 110 | "value":"Verdana" 111 | }, 112 | { 113 | "value":46 114 | }, 115 | { 116 | "value":16777215 117 | } 118 | ], 119 | "customParams":{}, 120 | "params":{ 121 | "autoSize":"bothDirections", 122 | "fontName":"lobstertworegular_size54_colorffffff_strokeaf384e_dropshadow560d1b", 123 | "fontSize":55, 124 | "height":59.07, 125 | "name":"LobsterTwoRegular_Size54_ColorFFFFFF_StrokeAF384E_DropShadow560D1B", 126 | "text":"Connect Facebook", 127 | "width":371.76, 128 | "x":135.62, 129 | "y":37.9 130 | } 131 | }, 132 | { 133 | "cls":"starling.text.TextField", 134 | "constructorParams":[ 135 | { 136 | "value":200 137 | }, 138 | { 139 | "value":100 140 | }, 141 | { 142 | "value":"Abc123" 143 | }, 144 | { 145 | "value":"Verdana" 146 | }, 147 | { 148 | "value":46 149 | }, 150 | { 151 | "value":16777215 152 | } 153 | ], 154 | "customParams":{}, 155 | "params":{ 156 | "color":10761216, 157 | "fontName":"grilledcheesebtn_size36_colorffffff", 158 | "fontSize":49, 159 | "height":152, 160 | "name":"GrilledCheeseBTN_Size36_ColoFFFFFF_DropShadow1C0900", 161 | "text":"Connect Facebook to have more fun!", 162 | "width":474, 163 | "x":90.5, 164 | "y":358 165 | } 166 | }, 167 | { 168 | "cls":"starling.display.Button", 169 | "constructorParams":[ 170 | { 171 | "cls":"starling.textures.Texture", 172 | "textureName":"generic_button_blue" 173 | } 174 | ], 175 | "customParams":{}, 176 | "params":{ 177 | "height":110, 178 | "name":"generic_button_blue", 179 | "width":265, 180 | "x":189, 181 | "y":543.5 182 | } 183 | } 184 | ], 185 | "cls":"starling.display.Sprite", 186 | "customParams":{ 187 | "container":1 188 | }, 189 | "params":{ 190 | "name":"root" 191 | } 192 | }, 193 | "setting":{ 194 | "canvasColor":16777215, 195 | "canvasSize":{ 196 | "x":640, 197 | "y":860 198 | } 199 | }, 200 | "version":"1.0" 201 | } -------------------------------------------------------------------------------- /demo/theme/src/feathers/themes/MetalWorksMobileThemeWithAssetManager.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Josh Tynjala 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | package feathers.themes; 26 | import starling.core.Starling; 27 | import starling.events.Event; 28 | import starling.utils.AssetManager; 29 | 30 | /** 31 | * Dispatched when the theme's assets are loaded, and the theme has 32 | * initialized. Feathers component will not be skinned automatically by the 33 | * theme until this event is dispatched. 34 | * 35 | *

The properties of the event object have the following values:

36 | * 37 | * 38 | * 39 | * 43 | * 44 | * 48 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 40 | * event listener that handles the event. For example, if you use 41 | * myButton.addEventListener() to register an event listener, 42 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 45 | * it is not always the Object listening for the event. Use the 46 | * currentTarget property to always access the Object 47 | * listening for the event.
49 | * 50 | * @eventType starling.events.Event.COMPLETE 51 | */ 52 | //[Event(name="complete",type="starling.events.Event")] 53 | 54 | /** 55 | * The "Metal Works" theme for mobile Feathers apps. 56 | * 57 | *

This version of the theme requires loading assets at runtime. To use 58 | * embedded assets, see MetalWorksMobileTheme instead.

59 | * 60 | *

To use this theme, the following files must be included when packaging 61 | * your app:

62 | *
    63 | *
  • images/metalworks_mobile.png
  • 64 | *
  • images/metalworks_mobile.xml
  • 65 | *
66 | * 67 | * @see http://wiki.starling-framework.org/feathers/theme-assets 68 | */ 69 | class MetalWorksMobileThemeWithAssetManager extends BaseMetalWorksMobileTheme 70 | { 71 | /** 72 | * @private 73 | * The name of the texture atlas in the asset manager. 74 | */ 75 | inline private static var ATLAS_NAME:String = "metalworks_mobile"; 76 | 77 | /** 78 | * Constructor. 79 | * @param assetsBasePath The root folder of the assets. 80 | * @param assetManager An optional pre-created asset manager. 81 | */ 82 | public function new(assetsBasePath:String = null, assetManager:AssetManager = null) 83 | { 84 | this.loadAssets(assetsBasePath, assetManager); 85 | } 86 | 87 | /** 88 | * @private 89 | * The paths to each of the assets, relative to the base path. 90 | */ 91 | private var assetPaths:Array = new 92 | [ 93 | "images/metalworks_mobile.xml", 94 | "images/metalworks_mobile.png" 95 | ]; 96 | 97 | /** 98 | * @private 99 | */ 100 | private var assetManager:AssetManager; 101 | 102 | /** 103 | * @private 104 | */ 105 | override public function dispose():Void 106 | { 107 | super.dispose(); 108 | if(this.assetManager) 109 | { 110 | this.assetManager.removeTextureAtlas(ATLAS_NAME); 111 | this.assetManager = null; 112 | } 113 | } 114 | 115 | /** 116 | * @private 117 | */ 118 | override private function initialize():Void 119 | { 120 | this.atlas = this.assetManager.getTextureAtlas(ATLAS_NAME); 121 | super.initialize(); 122 | } 123 | 124 | /** 125 | * @private 126 | */ 127 | private function assetManager_onProgress(progress:Float):Void 128 | { 129 | if(progress < 1) 130 | { 131 | return; 132 | } 133 | this.initialize(); 134 | this.dispatchEventWith(Event.COMPLETE); 135 | } 136 | 137 | /** 138 | * @private 139 | */ 140 | private function loadAssets(assetsBasePath:String, assetManager:AssetManager):Void 141 | { 142 | this.assetManager = assetManager; 143 | if(!this.assetManager) 144 | { 145 | this.assetManager = new AssetManager(Starling.current.contentScaleFactor); 146 | } 147 | //add a trailing slash, if needed 148 | if(assetsBasePath.lastIndexOf("/") != assetsBasePath.length - 1) 149 | { 150 | assetsBasePath += "/"; 151 | } 152 | var assetPaths:Array = this.assetPaths; 153 | var assetCount:Int = assetPaths.length; 154 | for(i in 0 ... assetCount) 155 | { 156 | var asset:String = assetPaths[i]; 157 | this.assetManager.enqueue(assetsBasePath + asset); 158 | } 159 | this.assetManager.loadQueue(assetManager_onProgress); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /demo/src/feathers/core/ValidationQueue.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | #if 0 10 | import openfl.utils.Dictionary; 11 | #end 12 | import haxe.ds.WeakMap; 13 | 14 | import starling.animation.IAnimatable; 15 | import starling.core.Starling; 16 | 17 | //[ExcludeClass] 18 | class ValidationQueue implements IAnimatable 19 | { 20 | /** 21 | * @private 22 | */ 23 | #if flash 24 | private static var STARLING_TO_VALIDATION_QUEUE:WeakMap = new WeakMap(); 25 | #else 26 | private static var STARLING_TO_VALIDATION_QUEUE:Map = new Map(); 27 | #end 28 | 29 | /** 30 | * Gets the validation queue for the specified Starling instance. If 31 | * a validation queue does not exist for the specified Starling 32 | * instance, a new one will be created. 33 | */ 34 | public static function forStarling(starling:Starling):ValidationQueue 35 | { 36 | if(starling == null) 37 | { 38 | return null; 39 | } 40 | var queue:ValidationQueue = STARLING_TO_VALIDATION_QUEUE.get(starling); 41 | if(queue == null) 42 | { 43 | STARLING_TO_VALIDATION_QUEUE.set(starling, queue = new ValidationQueue(starling)); 44 | } 45 | return queue; 46 | } 47 | 48 | /** 49 | * Constructor. 50 | */ 51 | public function new(starling:Starling) 52 | { 53 | this._starling = starling; 54 | } 55 | 56 | private var _starling:Starling; 57 | 58 | private var _isValidating:Bool = false; 59 | 60 | /** 61 | * If true, the queue is currently validating. 62 | * 63 | *

In the following example, we check if the queue is currently validating:

64 | * 65 | * 66 | * if( queue.isValidating ) 67 | * { 68 | * // do something 69 | * } 70 | */ 71 | public var isValidating(get, never):Bool; 72 | public function get_isValidating():Bool 73 | { 74 | return this._isValidating; 75 | } 76 | 77 | private var _delayedQueue:Array = new Array(); 78 | private var _queue:Array = new Array(); 79 | 80 | /** 81 | * Disposes the validation queue. 82 | */ 83 | public function dispose():Void 84 | { 85 | if(this._starling != null) 86 | { 87 | this._starling.juggler.remove(this); 88 | this._starling = null; 89 | } 90 | } 91 | 92 | /** 93 | * Adds a validating component to the queue. 94 | */ 95 | public function addControl(control:IValidating, delayIfValidating:Bool):Void 96 | { 97 | //if the juggler was purged, we need to add the queue back in. 98 | if(!this._starling.juggler.contains(this)) 99 | { 100 | this._starling.juggler.add(this); 101 | } 102 | var currentQueue:Array = (this._isValidating && delayIfValidating) ? this._delayedQueue : this._queue; 103 | if(currentQueue.indexOf(control) >= 0) 104 | { 105 | //already queued 106 | return; 107 | } 108 | var queueLength:Int = currentQueue.length; 109 | if(this._isValidating && currentQueue == this._queue) 110 | { 111 | //special case: we need to keep it sorted 112 | var depth:Int = control.depth; 113 | 114 | //we're traversing the queue backwards because it's 115 | //significantly more likely that we're going to push than that 116 | //we're going to splice, so there's no point to iterating over 117 | //the whole queue 118 | //for(var i:Int = queueLength - 1; i >= 0; i--) 119 | var i:Int = queueLength - 1; 120 | while(i >= 0) 121 | { 122 | var otherControl:IValidating = currentQueue[i]; 123 | var otherDepth:Int = otherControl.depth; 124 | //we can skip the overhead of calling queueSortFunction and 125 | //of looking up the value we've already stored in the depth 126 | //local variable. 127 | if(depth >= otherDepth) 128 | { 129 | break; 130 | } 131 | i--; 132 | } 133 | //add one because we're going after the last item we checked 134 | //if we made it through all of them, i will be -1, and we want 0 135 | i++; 136 | if(i == queueLength) 137 | { 138 | currentQueue[queueLength] = control; 139 | } 140 | else 141 | { 142 | currentQueue.insert(i, control); 143 | } 144 | } 145 | else 146 | { 147 | currentQueue[queueLength] = control; 148 | } 149 | } 150 | 151 | /** 152 | * @private 153 | */ 154 | public function advanceTime(time:Float):Void 155 | { 156 | if(this._isValidating || !this._starling.contextValid) 157 | { 158 | return; 159 | } 160 | var queueLength:Int = this._queue.length; 161 | if(queueLength == 0) 162 | { 163 | return; 164 | } 165 | this._isValidating = true; 166 | this._queue.sort(queueSortFunction); 167 | while(this._queue.length > 0) //rechecking length after the shift 168 | { 169 | var item:IValidating = this._queue.shift(); 170 | if(item.depth < 0) 171 | { 172 | //skip items that are no longer on the display list 173 | continue; 174 | } 175 | item.validate(); 176 | } 177 | var temp:Array = this._queue; 178 | this._queue = this._delayedQueue; 179 | this._delayedQueue = temp; 180 | this._isValidating = false; 181 | } 182 | 183 | /** 184 | * @private 185 | */ 186 | private function queueSortFunction(first:IValidating, second:IValidating):Int 187 | { 188 | var difference:Int = second.depth - first.depth; 189 | if(difference > 0) 190 | { 191 | return -1; 192 | } 193 | else if(difference < 0) 194 | { 195 | return 1; 196 | } 197 | return 0; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IFocusDisplayObject.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | /** 10 | * Dispatched when the display object receives focus. 11 | * 12 | *

The properties of the event object have the following values:

13 | * 14 | * 15 | * 16 | * 20 | * 21 | * 25 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 17 | * event listener that handles the event. For example, if you use 18 | * myButton.addEventListener() to register an event listener, 19 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 22 | * it is not always the Object listening for the event. Use the 23 | * currentTarget property to always access the Object 24 | * listening for the event.
26 | * 27 | * @eventType feathers.events.FeathersEventType.FOCUS_IN 28 | */ 29 | ///[Event(name="focusIn",type="starling.events.Event")] 30 | 31 | /** 32 | * Dispatched when the display object loses focus. 33 | * 34 | *

The properties of the event object have the following values:

35 | * 36 | * 37 | * 38 | * 42 | * 43 | * 47 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 39 | * event listener that handles the event. For example, if you use 40 | * myButton.addEventListener() to register an event listener, 41 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 44 | * it is not always the Object listening for the event. Use the 45 | * currentTarget property to always access the Object 46 | * listening for the event.
48 | * 49 | * @eventType feathers.events.FeathersEventType.FOCUS_OUT 50 | */ 51 | ///[Event(name="focusOut",type="starling.events.Event")] 52 | 53 | /** 54 | * A component that can receive focus. 55 | * 56 | * @see feathers.core.IFocusManager 57 | */ 58 | interface IFocusDisplayObject extends IFeathersDisplayObject 59 | { 60 | /** 61 | * The current focus manager for this component. 62 | */ 63 | var focusManager(get, set):IFocusManager; 64 | //function get_focusManager():IFocusManager; 65 | 66 | /** 67 | * @private 68 | */ 69 | //function set_focusManager(value:IFocusManager):Void; 70 | 71 | /** 72 | * Determines if this component can receive focus. 73 | * 74 | *

In the following example, the focus is disabled:

75 | * 76 | * 77 | * object.isFocusEnabled = false; 78 | */ 79 | var isFocusEnabled(get, set):Bool; 80 | //function get_isFocusEnabled():Bool; 81 | 82 | /** 83 | * @private 84 | */ 85 | //function set_isFocusEnabled(value:Bool):Void; 86 | 87 | /** 88 | * The next object that will receive focus when the tab key is pressed. 89 | * If null, defaults to the next child on the display list. 90 | * 91 | *

In the following example, the next tab focus is changed:

92 | * 93 | * 94 | * object.nextTabFocus = otherObject; 95 | */ 96 | var nextTabFocus(get, set):IFocusDisplayObject; 97 | //function get_nextTabFocus():IFocusDisplayObject; 98 | 99 | /** 100 | * @private 101 | */ 102 | //function set_nextTabFocus(value:IFocusDisplayObject):Void; 103 | 104 | /** 105 | * The previous object that will receive focus when the tab key is 106 | * pressed while holding shift. If null, defaults to the 107 | * previous child on the display list. 108 | * 109 | *

In the following example, the previous tab focus is changed:

110 | * 111 | * 112 | * object.previousTabFocus = otherObject; 113 | */ 114 | var previousTabFocus(get, set):IFocusDisplayObject; 115 | //function get_previousTabFocus():IFocusDisplayObject; 116 | 117 | /** 118 | * @private 119 | */ 120 | //function set_previousTabFocus(value:IFocusDisplayObject):Void; 121 | 122 | /** 123 | * Used for associating focusable display objects that are not direct 124 | * children with an "owner" focusable display object, such as pop-ups. 125 | * A focus manager may use this property to influence the tab order. 126 | * 127 | *

In the following example, the focus owner is changed:

128 | * 129 | * 130 | * object.focusOwner = otherObject; 131 | */ 132 | var focusOwner(get, set):IFocusDisplayObject; 133 | //function get_focusOwner():IFocusDisplayObject; 134 | 135 | /** 136 | * @private 137 | */ 138 | //function set_focusOwner(value:IFocusDisplayObject):Void; 139 | 140 | /** 141 | * If the object has focus, an additional visual indicator may 142 | * optionally be displayed to highlight the object. Calling this 143 | * function may have no effect. It's merely a suggestion to the object. 144 | * 145 | *

Important: This function will not give focus to 146 | * the display object if it doesn't have focus. To give focus to the 147 | * display object, you should set the focus property on 148 | * the focus manager.

149 | * 150 | * 151 | * object.focusManager.focus = object; 152 | * 153 | * @see #hideFocus() 154 | * @see feathers.core.IFocusManager#focus 155 | */ 156 | function showFocus():Void; 157 | 158 | /** 159 | * If the visual indicator of focus has been displayed by 160 | * showFocus(), call this function to hide it. 161 | * 162 | *

Important: This function will not clear focus 163 | * from the display object if it has focus. To clear focus from the 164 | * display object, you should set the focus property on 165 | * the focus manager to null or another display object.

166 | * 167 | * @see #showFocus() 168 | * @see feathers.core.IFocusManager#focus 169 | */ 170 | function hideFocus():Void; 171 | } 172 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/text/TextInputRestrict.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils.text; 9 | #if 0 10 | import flash.utils.Dictionary; 11 | #end 12 | 13 | /** 14 | * Duplicates the functionality of the restrict property on 15 | * flash.text.TextField. 16 | * 17 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html#restrict Full description of flash.text.TextField.restrict in Adobe's Flash Platform API Reference 18 | */ 19 | class TextInputRestrict 20 | { 21 | /** 22 | * @private 23 | */ 24 | private static var REQUIRES_ESCAPE:Map = new Map(); 25 | //REQUIRES_ESCAPE[/\[/g] = "\\["; 26 | //REQUIRES_ESCAPE[/\]/g] = "\\]"; 27 | //REQUIRES_ESCAPE[/\{/g] = "\\{"; 28 | //REQUIRES_ESCAPE[/\}/g] = "\\}"; 29 | //REQUIRES_ESCAPE[/\(/g] = "\\("; 30 | //REQUIRES_ESCAPE[/\)/g] = "\\)"; 31 | //REQUIRES_ESCAPE[/\|/g] = "\\|"; 32 | //REQUIRES_ESCAPE[/\//g] = "\\/"; 33 | //REQUIRES_ESCAPE[/\./g] = "\\."; 34 | //REQUIRES_ESCAPE[/\+/g] = "\\+"; 35 | //REQUIRES_ESCAPE[/\*/g] = "\\*"; 36 | //REQUIRES_ESCAPE[/\?/g] = "\\?"; 37 | //REQUIRES_ESCAPE[/\$/g] = "\\$"; 38 | 39 | /** 40 | * Constructor. 41 | */ 42 | public function new(restrict:String = null) 43 | { 44 | this.restrict = restrict; 45 | } 46 | 47 | /** 48 | * @private 49 | */ 50 | private var _restrictStartsWithExclude:Bool = false; 51 | 52 | /** 53 | * @private 54 | */ 55 | private var _restricts:Array; 56 | 57 | /** 58 | * @private 59 | */ 60 | @:native("_restrict1") 61 | private var _restrict:String; 62 | 63 | /** 64 | * Indicates the set of characters that a user can input. 65 | * 66 | *

In the following example, the text is restricted to numbers:

67 | * 68 | * 69 | * object.restrict = "0-9"; 70 | * 71 | * @default null 72 | * 73 | * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html#restrict Full description of flash.text.TextField.restrict in Adobe's Flash Platform API Reference 74 | */ 75 | public var restrict(get, set):String; 76 | public function get_restrict():String 77 | { 78 | return this._restrict; 79 | } 80 | 81 | /** 82 | * @private 83 | */ 84 | public function set_restrict(value:String):String 85 | { 86 | if(this._restrict == value) 87 | { 88 | return get_restrict(); 89 | } 90 | this._restrict = value; 91 | if(value != null) 92 | { 93 | if(this._restricts != null) 94 | { 95 | this._restricts.splice(0, this._restricts.length); 96 | } 97 | else 98 | { 99 | this._restricts = new Array(); 100 | } 101 | if(this._restrict == "") 102 | { 103 | this._restricts.push(~/^$/); 104 | } 105 | else if(this._restrict != null) 106 | { 107 | var startIndex:Int = 0; 108 | var isExcluding:Bool = value.indexOf("^") == 0; 109 | this._restrictStartsWithExclude = isExcluding; 110 | do 111 | { 112 | var nextStartIndex:Int = value.indexOf("^", startIndex + 1); 113 | var partialRestrict:String; 114 | if(nextStartIndex >= 0) 115 | { 116 | partialRestrict = value.substr(startIndex, nextStartIndex - startIndex); 117 | this._restricts.push(this.createRestrictRegExp(partialRestrict, isExcluding)); 118 | } 119 | else 120 | { 121 | partialRestrict = value.substr(startIndex); 122 | this._restricts.push(this.createRestrictRegExp(partialRestrict, isExcluding)); 123 | break; 124 | } 125 | startIndex = nextStartIndex; 126 | isExcluding = !isExcluding; 127 | } 128 | while(true); 129 | } 130 | } 131 | else 132 | { 133 | this._restricts = null; 134 | } 135 | return get_restrict(); 136 | } 137 | 138 | /** 139 | * Accepts a character code and determines if it is allowed or not. 140 | */ 141 | public function isCharacterAllowed(charCode:Int):Bool 142 | { 143 | if(this._restricts == null) 144 | { 145 | return true; 146 | } 147 | var character:String = String.fromCharCode(charCode); 148 | var isExcluding:Bool = this._restrictStartsWithExclude; 149 | var isIncluded:Bool = isExcluding; 150 | var restrictCount:Int = this._restricts.length; 151 | //for(var i:Int = 0; i < restrictCount; i++) 152 | for(i in 0 ... restrictCount) 153 | { 154 | var restrict:EReg = this._restricts[i]; 155 | if(isExcluding) 156 | { 157 | isIncluded = isIncluded && restrict.match(character); 158 | } 159 | else 160 | { 161 | isIncluded = isIncluded || restrict.match(character); 162 | } 163 | isExcluding = !isExcluding; 164 | } 165 | return isIncluded; 166 | } 167 | 168 | /** 169 | * Accepts a string of characters and filters out characters that are 170 | * not allowed. 171 | */ 172 | public function filterText(value:String):String 173 | { 174 | if(this._restricts == null) 175 | { 176 | return value; 177 | } 178 | var textLength:Int = value.length; 179 | var restrictCount:Int = this._restricts.length; 180 | //for(var i:Int = 0; i < textLength; i++) 181 | var i:Int = 0; 182 | while(i < textLength) 183 | { 184 | var character:String = value.charAt(i); 185 | var isExcluding:Bool = this._restrictStartsWithExclude; 186 | var isIncluded:Bool = isExcluding; 187 | //for(var j:Int = 0; j < restrictCount; j++) 188 | for(j in 0 ... restrictCount) 189 | { 190 | var restrict:EReg = this._restricts[j]; 191 | if(isExcluding) 192 | { 193 | isIncluded = isIncluded && restrict.match(character); 194 | } 195 | else 196 | { 197 | isIncluded = isIncluded || restrict.match(character); 198 | } 199 | isExcluding = !isExcluding; 200 | } 201 | if(!isIncluded) 202 | { 203 | value = value.substr(0, i) + value.substr(i + 1); 204 | i--; 205 | textLength--; 206 | } 207 | 208 | i++; 209 | } 210 | return value; 211 | } 212 | 213 | /** 214 | * @private 215 | */ 216 | private function createRestrictRegExp(restrict:String, isExcluding:Bool):EReg 217 | { 218 | if(!isExcluding && restrict.indexOf("^") == 0) 219 | { 220 | //unlike regular expressions, which always treat ^ as excluding, 221 | //restrict uses ^ to swap between excluding and including. 222 | //if we're including, we need to remove ^ for the regexp 223 | restrict = restrict.substr(1); 224 | } 225 | //we need to do backslash first. otherwise, we'll get duplicates 226 | restrict = (~/\\/g).replace(restrict, "\\\\"); 227 | //for(var key:Object in REQUIRES_ESCAPE) 228 | for(keyRegExp in REQUIRES_ESCAPE) 229 | { 230 | //var keyRegExp:EReg = key; 231 | var value:String = REQUIRES_ESCAPE[keyRegExp.toString()]; 232 | restrict = new EReg(keyRegExp, "g").replace(restrict, value); 233 | } 234 | return new EReg("[" + restrict + "]", "g"); 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/util/StageUtil.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.util; 9 | 10 | import openfl.system.Capabilities; 11 | import openfl.display.Stage; 12 | import openfl.geom.Rectangle; 13 | import openfl.geom.Point; 14 | 15 | import starling.core.Starling; 16 | 17 | import starling.display.DisplayObject; 18 | import starling.utils.RectangleUtil; 19 | import starling.utils.ScaleMode; 20 | 21 | /** 22 | * Helper class to support multiple resolution 23 | * 24 | *

Example usage:

25 | * 26 | * 27 | * var stageUtil:StageUtil = new StageUtil(stage); 28 | * var size:Point = stageUtil.getScaledStageSize(); 29 | * var starling:Starling = new Starling(Game, stage, new Rectangle(0, 0, stageUtil.stageWidth, stageUtil.stageHeight)); 30 | * starling.stage.stageWidth = size.x; 31 | * starling.stage.stageHeight = size.y; 32 | * 33 | * @see http://wiki.starling-framework.org/builder/multiple_resolution Multiple resolution support 34 | * @see http://github.com/mindjolt/starling-builder-engine/tree/master/demo Starling Builder demo project 35 | */ 36 | class StageUtil 37 | { 38 | public var stageWidth(get, null):Int; 39 | public var stageHeight(get, null):Int; 40 | 41 | private var _stage:Stage; 42 | private var _designStageWidth:Int; 43 | private var _designStageHeight:Int; 44 | private var _supportRotation:Bool; 45 | 46 | /** 47 | * Constructor 48 | * @param stage flash stage 49 | * @param designStageWidth design stage width of the project 50 | * @param designStageHeight design stage height of the project 51 | */ 52 | 53 | public function new(stage:Stage, designStageWidth:Int = 640, designStageHeight:Int = 960, supportRotation:Bool = false) 54 | { 55 | _stage = stage; 56 | 57 | _designStageWidth = designStageWidth; 58 | _designStageHeight = designStageHeight; 59 | 60 | _supportRotation = supportRotation; 61 | } 62 | 63 | /** 64 | * Return stage width of the device 65 | */ 66 | 67 | public function get_stageWidth():Int 68 | { 69 | var iOS:Bool = isiOS(); 70 | var android:Bool = isAndroid(); 71 | 72 | if (iOS || android) 73 | { 74 | return _stage.stageWidth; 75 | } 76 | else 77 | { 78 | return _stage.stageWidth; 79 | } 80 | } 81 | 82 | /** 83 | * Return stage height of the device 84 | */ 85 | 86 | public function get_stageHeight():Int 87 | { 88 | var iOS:Bool = isiOS(); 89 | var android:Bool = isAndroid(); 90 | 91 | if (iOS || android) 92 | { 93 | return _stage.stageHeight; 94 | } 95 | else 96 | { 97 | return _stage.stageHeight; 98 | } 99 | } 100 | 101 | /** 102 | * Calculate the scaled starling stage size 103 | * 104 | * @param stageWidth stageWidth of flash stage, if not specified then use this.stageWidth 105 | * @param stageHeight stageHeight of flash stage, if not specified then use this.stageHeight 106 | * @return the scaled starling stage 107 | */ 108 | 109 | public function getScaledStageSize(stageWidth:Int = 0, stageHeight:Int = 0):Point 110 | { 111 | if (stageWidth == 0 || stageHeight == 0) 112 | { 113 | stageWidth = this.stageWidth; 114 | stageHeight = this.stageHeight; 115 | } 116 | 117 | var designWidth:Int; 118 | var designHeight:Int; 119 | 120 | var rotated:Bool = _supportRotation && ((stageWidth < stageHeight) != (_designStageWidth < _designStageHeight)); 121 | 122 | if (rotated) 123 | { 124 | designWidth = _designStageHeight; 125 | designHeight = _designStageWidth; 126 | } 127 | else 128 | { 129 | designWidth = _designStageWidth; 130 | designHeight = _designStageHeight; 131 | } 132 | 133 | var maxRatio:Float = 1.0 * designWidth / designHeight; 134 | 135 | var width:Float; 136 | var height:Float; 137 | 138 | var scale:Float; 139 | 140 | if (1.0 * stageWidth / stageHeight <= maxRatio) 141 | { 142 | scale = _designStageWidth / stageWidth; 143 | } 144 | else 145 | { 146 | scale = _designStageHeight / stageHeight; 147 | } 148 | 149 | width = scale * stageWidth; 150 | height = scale * stageHeight; 151 | 152 | return new Point(Math.round(width), Math.round(height)); 153 | } 154 | 155 | /** 156 | * @private 157 | */ 158 | 159 | public static function isAndroid():Bool 160 | { 161 | return Capabilities.manufacturer.indexOf("Android") != -1; 162 | } 163 | 164 | /** 165 | * @private 166 | */ 167 | 168 | public static function isiOS():Bool 169 | { 170 | return Capabilities.manufacturer.indexOf("iOS") != -1; 171 | } 172 | 173 | /** 174 | * Fit background to the center of the native stage, If the aspect ratio is different, some cropping may happen. 175 | * @param object background display object 176 | * @param stage native stage 177 | */ 178 | 179 | public static function fitNativeBackground(object:flash.display.DisplayObject, stage:Stage):Void 180 | { 181 | var objectRect:Rectangle = new Rectangle(0, 0, object.width, object.height); 182 | var stageRect:Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight); 183 | var rect:flash.geom.Rectangle = RectangleUtil.fit(objectRect, stageRect, ScaleMode.NO_BORDER); 184 | object.x = rect.x; 185 | object.y = rect.y; 186 | object.width = rect.width; 187 | object.height = rect.height; 188 | } 189 | 190 | /** 191 | * Fit background to the center of the Starling stage. If the aspect ratio is different, some cropping may happen. 192 | * @param object background display object 193 | */ 194 | 195 | public static function fitBackground(object:DisplayObject):Void 196 | { 197 | var stage:starling.display.Stage = Starling.current.stage; 198 | var objectRect:Rectangle = new Rectangle(0, 0, object.width, object.height); 199 | var stageRect:Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight); 200 | var rect:flash.geom.Rectangle = RectangleUtil.fit(objectRect, stageRect, ScaleMode.NO_BORDER); 201 | object.x = rect.x; 202 | object.y = rect.y; 203 | object.width = rect.width; 204 | object.height = rect.height; 205 | } 206 | } 207 | 208 | -------------------------------------------------------------------------------- /demo/src/feathers/core/IFeathersControl.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.core; 9 | import feathers.skins.IStyleProvider; 10 | 11 | import openfl.geom.Rectangle; 12 | 13 | /** 14 | * Dispatched after the control has been initialized, but before it has 15 | * drawn for the first time. Typically, the component's children will have 16 | * been created by this point. 17 | * 18 | *

The properties of the event object have the following values:

19 | * 20 | * 21 | * 22 | * 26 | * 27 | * 31 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 23 | * event listener that handles the event. For example, if you use 24 | * myButton.addEventListener() to register an event listener, 25 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 28 | * it is not always the Object listening for the event. Use the 29 | * currentTarget property to always access the Object 30 | * listening for the event.
32 | * 33 | * @eventType feathers.events.FeathersEventType.INITIALIZE 34 | */ 35 | ///[Event(name="initialize",type="starling.events.Event")] 36 | 37 | /** 38 | * Dispatched after the component has validated for the first time. Both 39 | * initialize() and draw() will have been called, 40 | * and all children will have been created. 41 | * 42 | *

The properties of the event object have the following values:

43 | * 44 | * 45 | * 46 | * 50 | * 51 | * 55 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 47 | * event listener that handles the event. For example, if you use 48 | * myButton.addEventListener() to register an event listener, 49 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 52 | * it is not always the Object listening for the event. Use the 53 | * currentTarget property to always access the Object 54 | * listening for the event.
56 | * 57 | * @eventType feathers.events.FeathersEventType.CREATION_COMPLETE 58 | */ 59 | ///[Event(name="creationComplete",type="starling.events.Event")] 60 | 61 | /** 62 | * Dispatched when the width or height of the control changes. 63 | * 64 | *

The properties of the event object have the following values:

65 | * 66 | * 67 | * 68 | * 72 | * 73 | * 77 | *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the 69 | * event listener that handles the event. For example, if you use 70 | * myButton.addEventListener() to register an event listener, 71 | * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; 74 | * it is not always the Object listening for the event. Use the 75 | * currentTarget property to always access the Object 76 | * listening for the event.
78 | * 79 | * @eventType feathers.events.FeathersEventType.RESIZE 80 | */ 81 | ///[Event(name="resize",type="starling.events.Event")] 82 | 83 | /** 84 | * Basic interface for Feathers UI controls. A Feathers control must also 85 | * be a Starling display object. 86 | */ 87 | interface IFeathersControl extends IValidating 88 | { 89 | /** 90 | * @copy feathers.core.FeathersControl#minWidth 91 | */ 92 | var minWidth(get, set):Float; 93 | //function get_minWidth():Float; 94 | 95 | /** 96 | * @private 97 | */ 98 | //function set_minWidth(value:Float):Void; 99 | 100 | /** 101 | * @copy feathers.core.FeathersControl#minHeight 102 | */ 103 | var minHeight(get, set):Float; 104 | //function get_minHeight():Float; 105 | 106 | /** 107 | * @private 108 | */ 109 | //function set_minHeight(value:Float):Void; 110 | 111 | /** 112 | * @copy feathers.core.FeathersControl#maxWidth 113 | */ 114 | var maxWidth(get, set):Float; 115 | //function get_maxWidth():Float; 116 | 117 | /** 118 | * @private 119 | */ 120 | //function set_maxWidth(value:Float):Void; 121 | 122 | /** 123 | * @copy feathers.core.FeathersControl#maxHeight 124 | */ 125 | var maxHeight(get, set):Float; 126 | //function get_maxHeight():Float; 127 | 128 | /** 129 | * @private 130 | */ 131 | //function set_maxHeight(value:Float):Void; 132 | 133 | /** 134 | * @private 135 | */ 136 | var clipRect(get, set):Rectangle; 137 | //function get_clipRect():Rectangle; 138 | 139 | /** 140 | * @private 141 | */ 142 | //function set_clipRect(value:Rectangle):Void; 143 | 144 | /** 145 | * @copy feathers.core.FeathersControl#isEnabled 146 | */ 147 | var isEnabled(get, set):Bool; 148 | //function get_isEnabled():Bool; 149 | 150 | /** 151 | * @private 152 | */ 153 | //function set_isEnabled(value:Bool):Void; 154 | 155 | /** 156 | * @copy feathers.core.FeathersControl#isInitialized 157 | */ 158 | var isInitialized(get, never):Bool; 159 | //function get_isInitialized():Bool; 160 | 161 | /** 162 | * @copy feathers.core.FeathersControl#isCreated 163 | */ 164 | var isCreated(get, never):Bool; 165 | //function get_isCreated():Bool; 166 | 167 | /** 168 | * @copy feathers.core.FeathersControl#styleNameList 169 | */ 170 | var styleNameList(get, never):TokenList; 171 | //function get_styleNameList():TokenList; 172 | 173 | /** 174 | * @copy feathers.core.FeathersControl#styleName 175 | */ 176 | var styleName(get, set):String; 177 | //function get_styleName():String; 178 | 179 | /** 180 | * @private 181 | */ 182 | //function set_styleName(value:String):Void; 183 | 184 | /** 185 | * @copy feathers.core.FeathersControl#styleProvider 186 | */ 187 | var styleProvider(get, set):IStyleProvider; 188 | //function get_styleProvider():IStyleProvider; 189 | 190 | /** 191 | * @private 192 | */ 193 | //function set_styleProvider(value:IStyleProvider):Void; 194 | 195 | /** 196 | * @copy feathers.core.FeathersControl#setSize() 197 | */ 198 | function setSize(width:Float, height:Float):Void; 199 | 200 | /** 201 | * @copy feathers.core.FeathersControl#move() 202 | */ 203 | function move(x:Float, y:Float):Void; 204 | } 205 | -------------------------------------------------------------------------------- /demo/assets/images/metalworks_mobile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /demo/src/feathers/utils/ScreenDensityScaleFactorManager.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.utils; 9 | import feathers.system.DeviceCapabilities; 10 | import feathers.utils.math.FeathersMathUtil.roundDownToNearest; 11 | import openfl.errors.Error; 12 | 13 | import flash.display.Stage; 14 | import flash.events.Event; 15 | import flash.geom.Rectangle; 16 | import flash.system.Capabilities; 17 | 18 | import starling.core.Starling; 19 | 20 | import starling.utils.Max; 21 | 22 | /** 23 | * Automatically manages the Starling view port and stage dimensions to 24 | * create an appropriate contentScaleFactor value for the 25 | * current mobile device using the screen density (sometimes referred to as 26 | * DPI or PPI). The stage and view port will be resized without 27 | * letterboxing. Additionally, the view port and stage will be automatically 28 | * updated if the native stage resizes or changes orientation. 29 | * 30 | *

The contentScaleFactor values calculated by this class 31 | * are based on a combination of the screen density buckets supported by 32 | * Google Android and the native scale factors used for Apple's iPhone:

33 | * 34 | * 35 | * 36 | * 37 | * 38 | * 39 | * 40 | * 41 | * 42 | *
NameDensityScale Factor
ldpi1200.75
mdpi1601
hdpi2401.5
xhdpi3202
xxhdpi4803
xxxhdpi6404
43 | * 44 | *

The density values in the table above are approximate. The screen 45 | * density of an iPhone 5 is 326, so it uses the scale factor from the 46 | * "xhdpi" bucket because 326 is closer to 320 than it is to 480.

47 | * 48 | *

Providing textures for every scale factor is optional. Textures from 49 | * another scale factor can be automatically scaled to fit the current scale 50 | * factor. For instance, since "ldpi" devices with a low screen density 51 | * typically aren't manufactured anymore, "mdpi" textures will probably be 52 | * "good enough" for these legacy devices, if your app encounters one. The 53 | * larger textures will be automatically scaled down, and the app will look 54 | * the same as it would if you were using lower resolution textures.

55 | * 56 | *

Special behavior has been implemented for iPads to give them scale 57 | * factors of 1 and 2, just like native apps. 58 | * Using Android's rules for DPI buckets, non-Retina iPads would have been 59 | * "ldpi" devices (scale factor 0.75) and Retina iPads would 60 | * have been "hdpi" devices (scale factor 1.5. However, because 61 | * it makes more sense to make Starling use the same scale factor as native 62 | * apps on iPad, this class makes a special exception just for them.

63 | * 64 | *

The following example demonstrates how to use 65 | * ScreenDensityScaleFactorManager:

66 | * 67 | * 68 | * this._starling = new Starling( RootClass, this.stage, null, null, Context3DRenderMode.AUTO, Context3DProfile.BASELINE ); 69 | * this._scaler = new ScreenDensityScaleFactorManager(this._starling); 70 | * 71 | *

When using this class, you should not attempt to manually resize the 72 | * Starling view port or stage manually. This class manages their dimensions 73 | * automatically on its own.

74 | */ 75 | class ScreenDensityScaleFactorManager 76 | { 77 | /** 78 | * @private 79 | */ 80 | inline private static var IOS_TABLET_DENSITY_SCALE_FACTOR:Float = 1.23484848484848; 81 | 82 | /** 83 | * Constructor. 84 | */ 85 | public function ScreenDensityScaleFactorManager(starling:Starling) 86 | { 87 | var nativeStage:Stage = starling.nativeStage; 88 | this._starling = starling; 89 | this._calculatedScaleFactor = this.calculateScaleFactor(); 90 | this.updateStarlingStageDimensions(); 91 | //this needs top priority because we don't want Starling's listener 92 | //to get this event first use have bad dimensions. 93 | nativeStage.addEventListener(Event.RESIZE, nativeStage_resizeHandler, false, Max.INT_MAX_VALUE, true); 94 | } 95 | 96 | /** 97 | * @private 98 | */ 99 | private var _starling:Starling; 100 | 101 | /** 102 | * @private 103 | */ 104 | private var _calculatedScaleFactor:Float; 105 | 106 | /** 107 | * @private 108 | */ 109 | private function calculateScaleFactor():Float 110 | { 111 | var nativeStage:Stage = this._starling.nativeStage; 112 | var screenDensity:Float = DeviceCapabilities.dpi; 113 | //workaround because these rules derived from Android's behavior 114 | //would "incorrectly" give iPads a lower scale factor than iPhones 115 | //when both devices have the same scale factor natively. 116 | if(Capabilities.version.indexOf("IOS") >= 0 && DeviceCapabilities.isTablet(nativeStage)) 117 | { 118 | screenDensity *= IOS_TABLET_DENSITY_SCALE_FACTOR; 119 | } 120 | var bucket:ScreenDensityBucket = BUCKETS[0]; 121 | if(screenDensity <= bucket.density) 122 | { 123 | return bucket.scale; 124 | } 125 | var previousBucket:ScreenDensityBucket = bucket; 126 | var bucketCount:Int = BUCKETS.length; 127 | //for(var i:Int = 1; i < bucketCount; i++) 128 | for(i in 1 ... bucketCount) 129 | { 130 | bucket = BUCKETS[i]; 131 | if(screenDensity > bucket.density) 132 | { 133 | previousBucket = bucket; 134 | continue; 135 | } 136 | var midDPI:Float = (bucket.density + previousBucket.density) / 2; 137 | if(screenDensity < midDPI) 138 | { 139 | return previousBucket.scale; 140 | } 141 | return bucket.scale; 142 | } 143 | return bucket.scale; 144 | } 145 | 146 | /** 147 | * @private 148 | */ 149 | private function updateStarlingStageDimensions():Void 150 | { 151 | var nativeStage:Stage = this._starling.nativeStage; 152 | var needsToBeDivisibleByTwo:Bool = Std.int(this._calculatedScaleFactor) != this._calculatedScaleFactor; 153 | var starlingStageWidth:Float = Std.int(nativeStage.stageWidth / this._calculatedScaleFactor); 154 | if(needsToBeDivisibleByTwo) 155 | { 156 | starlingStageWidth = roundDownToNearest(starlingStageWidth, 2); 157 | } 158 | this._starling.stage.stageWidth = Std.int(starlingStageWidth); 159 | var starlingStageHeight:Float = Std.int(nativeStage.stageHeight / this._calculatedScaleFactor); 160 | if(needsToBeDivisibleByTwo) 161 | { 162 | starlingStageHeight = roundDownToNearest(starlingStageHeight, 2); 163 | } 164 | this._starling.stage.stageHeight = Std.int(starlingStageHeight); 165 | 166 | var viewPort:Rectangle = this._starling.viewPort; 167 | viewPort.width = starlingStageWidth * this._calculatedScaleFactor; 168 | viewPort.height = starlingStageHeight * this._calculatedScaleFactor; 169 | try 170 | { 171 | this._starling.viewPort = viewPort; 172 | } 173 | catch(error:Error) {} 174 | } 175 | 176 | /** 177 | * @private 178 | */ 179 | private function nativeStage_resizeHandler(event:Event):Void 180 | { 181 | this.updateStarlingStageDimensions(); 182 | } 183 | 184 | private static var BUCKETS:Array = 185 | [ 186 | new ScreenDensityBucket(120, 0.75), //ldpi 187 | new ScreenDensityBucket(160, 1), //mdpi 188 | new ScreenDensityBucket(240, 1.5), //hdpi 189 | new ScreenDensityBucket(320, 2), //xhdpi 190 | new ScreenDensityBucket(480, 3), //xxhdpi 191 | new ScreenDensityBucket(640, 4) ///xxxhpi 192 | ]; 193 | } 194 | 195 | class ScreenDensityBucket 196 | { 197 | public function new(dpi:Float, scale:Float) 198 | { 199 | this.density = dpi; 200 | this.scale = scale; 201 | } 202 | 203 | public var density:Float; 204 | public var scale:Float; 205 | } -------------------------------------------------------------------------------- /src/starlingbuilder/engine/UIElementFactory.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine; 9 | 10 | import openfl.geom.Rectangle; 11 | import openfl.errors.Error; 12 | 13 | import starling.textures.Texture; 14 | 15 | /** 16 | * @private 17 | */ 18 | class UIElementFactory 19 | { 20 | private var _assetMediator:IAssetMediator; 21 | 22 | public function new(assetMediator:IAssetMediator) 23 | { 24 | _assetMediator = assetMediator; 25 | } 26 | 27 | private function setDefaultParams(obj:Dynamic, data:Dynamic):Void 28 | { 29 | } 30 | 31 | private function setDirectParams(obj:Dynamic, data:Dynamic):Void 32 | { 33 | var array:Array = []; 34 | var id:String; 35 | for (id in Reflect.fields(data.params)) 36 | { 37 | array.push(id); 38 | } 39 | sortParams(array, PARAMS); 40 | 41 | for (id in array) 42 | { 43 | var item:Dynamic = data.params[id]; 44 | 45 | if (item && Reflect.hasField(item, "cls")) 46 | { 47 | try 48 | { 49 | Reflect.setProperty(obj, id, create(item)); 50 | } 51 | catch (e:Error) {} 52 | } 53 | else 54 | { 55 | try 56 | { 57 | Reflect.setProperty(obj, id, item); 58 | } 59 | catch (e:Error) {} 60 | } 61 | } 62 | } 63 | 64 | private function setDefault(obj:Dynamic, data:Dynamic):Void 65 | { 66 | setDefaultParams(obj, data); 67 | setDirectParams(obj, data); 68 | } 69 | 70 | private function createTexture(param:Dynamic):Dynamic 71 | { 72 | var texture:Texture; 73 | var scaleRatio:Array; 74 | var cls:Class; 75 | var data:Dynamic; 76 | 77 | var clsName:String = param.cls; 78 | 79 | switch (clsName) 80 | { 81 | case "starling.textures.Texture": 82 | texture = _assetMediator.getTexture(param.textureName); 83 | 84 | if (texture == null) 85 | throw new Error("Texture " + param.textureName + " not found"); 86 | 87 | return texture; 88 | case "feathers.textures.Scale3Textures": 89 | texture = _assetMediator.getTexture(param.textureName); 90 | 91 | if (texture == null) 92 | throw new Error("Texture " + param.textureName + " not found"); 93 | 94 | scaleRatio = param.scaleRatio; 95 | 96 | var direction:String = "horizontal"; 97 | 98 | if (scaleRatio.length == 3) 99 | { 100 | direction = scaleRatio[2]; 101 | } 102 | 103 | var s3t:Dynamic; 104 | cls = Type.resolveClass("feathers.textures.Scale3Textures"); 105 | if (direction == "horizontal") 106 | { 107 | s3t = Type.createInstance(cls, [texture, texture.width * scaleRatio[0], texture.width * scaleRatio[1], direction]); 108 | } 109 | else 110 | { 111 | s3t = Type.createInstance(cls, [texture, texture.height * scaleRatio[0], texture.height * scaleRatio[1], direction]); 112 | } 113 | 114 | return s3t; 115 | case "feathers.textures.Scale9Textures": 116 | texture = _assetMediator.getTexture(param.textureName); 117 | 118 | if (texture == null) 119 | throw new Error("Texture " + param.textureName + " not found"); 120 | 121 | scaleRatio = param.scaleRatio; 122 | var rect:Rectangle = new Rectangle(texture.width * scaleRatio[0], texture.height * scaleRatio[1], texture.width * scaleRatio[2], texture.height * scaleRatio[3]); 123 | cls = Type.resolveClass("feathers.textures.Scale9Textures"); 124 | var s9t:Dynamic = Type.createInstance(cls, [texture, rect]); 125 | return s9t; 126 | case "__AS3__.vec.Vector.": 127 | return _assetMediator.getTextures(param.value); 128 | case "XML": 129 | data = _assetMediator.getXml(param.name); 130 | 131 | if (data == null) 132 | throw new Error("XML " + param.name + " not found"); 133 | 134 | return data; 135 | case "Object": 136 | data = _assetMediator.getObject(param.name); 137 | 138 | if (data == null) 139 | throw new Error("Object " + param.name + " not found"); 140 | 141 | return data; 142 | case "feathers.data.ListCollection": 143 | cls = Type.resolveClass(clsName); 144 | return Type.createInstance(cls, [param.data]); 145 | case "feathers.data.HierarchicalCollection": 146 | cls = Type.resolveClass(clsName); 147 | return Type.createInstance(cls, [param.data]); 148 | default: 149 | return null; 150 | } 151 | } 152 | 153 | public function create(data:Dynamic):Dynamic 154 | { 155 | var obj:Dynamic; 156 | var constructorParams:Array = data.constructorParams; 157 | 158 | var res:Dynamic = createTexture(data); 159 | if (res) return res; 160 | 161 | var cls:Class = null; 162 | 163 | if (data.customParams && data.customParams.customComponentClass && data.customParams.customComponentClass != "null") 164 | { 165 | try 166 | { 167 | cls = Type.resolveClass(data.customParams.customComponentClass); 168 | } 169 | catch (e:Error) 170 | { 171 | trace("Class " + data.customParams.customComponentClass + " can't be instantiated."); 172 | } 173 | } 174 | 175 | //hack: flash.geom.Rectangle only exists in flash target 176 | #if (display || !flash) 177 | if (data.cls == "flash.geom.Rectangle") 178 | { 179 | data.cls = "openfl.geom.Rectangle"; 180 | } 181 | #end 182 | 183 | if (cls == null) 184 | { 185 | cls = Type.resolveClass(data.cls); 186 | } 187 | 188 | var args:Array = createArgumentsFromParams(constructorParams); 189 | 190 | try 191 | { 192 | obj = Type.createInstance(cls, args); 193 | } 194 | catch (e:Error) 195 | { 196 | obj = Type.createInstance(cls, []); 197 | } 198 | 199 | setDefault(obj, data); 200 | return obj; 201 | } 202 | 203 | private function createArgumentsFromParams(params:Array):Array 204 | { 205 | var args:Array = []; 206 | 207 | if (params != null) 208 | { 209 | for (param in params) 210 | { 211 | 212 | if (Reflect.field(param, "cls")) 213 | { 214 | args.push(create(param)); 215 | } 216 | else 217 | { 218 | args.push(param.value); 219 | } 220 | } 221 | } 222 | 223 | return args; 224 | 225 | } 226 | 227 | public static var PARAMS = {x:1, y:1, width:2, height:2, scaleX:3, scaleY:3, rotation:4}; 228 | 229 | public static function sortParams(array:Array, params:Dynamic):Void 230 | { 231 | array.sort(function(e1:String, e2:String):Int 232 | { 233 | var value:Int = compare(Reflect.field(params, e1), Reflect.field(params, e2)); 234 | if (value != 0) return value; 235 | return e1 < e2 ? -1 : 1; 236 | }); 237 | } 238 | 239 | private static function compare(a:String, b:String) 240 | {return (a < b) ? -1 : (a > b) ? 1 : 0;} 241 | } 242 | 243 | -------------------------------------------------------------------------------- /src/starlingbuilder/engine/tween/DefaultTweenBuilder.hx: -------------------------------------------------------------------------------- 1 | /** 2 | * Starling Builder 3 | * Copyright 2015 SGN Inc. All Rights Reserved. 4 | * 5 | * This program is free software. You can redistribute and/or modify it in 6 | * accordance with the terms of the accompanying license agreement. 7 | */ 8 | package starlingbuilder.engine.tween; 9 | 10 | import Reflect; 11 | import starling.animation.Tween; 12 | import starling.core.Starling; 13 | import starling.display.DisplayObject; 14 | import starling.display.DisplayObjectContainer; 15 | 16 | import starlingbuilder.engine.UIBuilder; 17 | 18 | /** 19 | * Default implementation of ITweenBuilder 20 | * 21 | *

Example data1:

22 | *

{"time":1, "properties":{"scaleX":0.9, "scaleY":0.9, "repeatCount":0, "reverse":true}}

23 | *

Example data2:

24 | *

[{"properties":{"repeatCount":0,"scaleY":0.9,"reverse":true,"scaleX":0.9},"time":1},{"properties":{"repeatCount":0,"alpha":0,"reverse":true},"time":0.5}]

25 | *

Example data3:

26 | *

{"time":0.5,"properties":{"repeatCount":0,"reverse":true},"delta":{"y":-10}}

27 | * 28 | * @see ITweenBuilder 29 | * @see http://wiki.starling-framework.org/builder/tween Using tween 30 | */ 31 | class DefaultTweenBuilder implements ITweenBuilder 32 | { 33 | private var _saveData:Map; 34 | 35 | /** 36 | * Constructor 37 | */ 38 | 39 | public function new() 40 | { 41 | _saveData = new Map(); 42 | } 43 | 44 | /** 45 | * @inheritDoc 46 | */ 47 | 48 | public function start(root:DisplayObject, paramsDict:Map, names:Array = null):Void 49 | { 50 | stop(root, paramsDict, names); 51 | 52 | var array:Array = getDisplayObjectsByNames(root, paramsDict, names); 53 | 54 | for (obj in array) 55 | { 56 | var data:Dynamic = paramsDict[obj]; 57 | 58 | var tweenData:Dynamic = data.tweenData; 59 | 60 | if (tweenData) 61 | { 62 | if (Std.is(tweenData, Array)) 63 | { 64 | for (item in cast(tweenData, Array)) 65 | createTweenFrom(obj, item); 66 | } 67 | else 68 | { 69 | createTweenFrom(obj, tweenData); 70 | } 71 | } 72 | } 73 | } 74 | 75 | private function getDisplayObjectsByNames(root:DisplayObject, paramsDict:Map, names:Array):Array 76 | { 77 | var array:Array = []; 78 | 79 | if (names != null) 80 | { 81 | for (name in names) 82 | { 83 | array.push(UIBuilder.find(cast root, name)); 84 | } 85 | } 86 | else 87 | { 88 | for (obj in paramsDict.keys()) 89 | { 90 | if (Reflect.hasField(paramsDict[obj], "tweenData")) 91 | array.push(obj); 92 | } 93 | } 94 | 95 | return array; 96 | } 97 | 98 | private function createTweenFrom(obj:DisplayObject, data:Dynamic):Void 99 | { 100 | if (!Reflect.hasField(data, "time")) 101 | { 102 | trace("Missing tween param: time"); 103 | return; 104 | } 105 | 106 | var initData:Dynamic = saveInitData(obj, data.properties, data.delta, data.from, data.fromDelta); 107 | 108 | var properties:Dynamic = createProperties(obj, data, initData); 109 | 110 | var tween:Dynamic = Starling.current.juggler.tween(obj, data.time, properties); 111 | 112 | if (!_saveData[obj]) _saveData[obj] = []; 113 | 114 | _saveData[obj].push({tween:tween, init:initData}); 115 | } 116 | 117 | /** 118 | * @inheritDoc 119 | */ 120 | 121 | public function stop(root:DisplayObject, paramsDict:Map = null, names:Array = null):Void 122 | { 123 | if (paramsDict == null || names == null) 124 | { 125 | stopAll(root); 126 | } 127 | else 128 | { 129 | var array:Array = getDisplayObjectsByNames(root, paramsDict, names); 130 | 131 | for (obj in array) 132 | { 133 | stopTween(obj); 134 | } 135 | } 136 | } 137 | 138 | private function stopTween(obj:DisplayObject):Void 139 | { 140 | var array:Array = _saveData[obj]; 141 | 142 | if (array != null) 143 | { 144 | for (data in array) 145 | { 146 | var initData:Dynamic = data.init; 147 | recoverInitData(obj, initData); 148 | 149 | var tween:Dynamic = data.tween; 150 | 151 | if (Std.is(tween, Tween)) //Starling 1.x 152 | { 153 | Starling.current.juggler.remove(cast tween); 154 | } 155 | else //Starling 2.x 156 | { 157 | //Starling.current.juggler["removeByID"](cast tween); 158 | } 159 | } 160 | } 161 | 162 | _saveData.remove(obj); 163 | } 164 | 165 | private function createProperties(obj:Dynamic, data:Dynamic, initData:Dynamic):Dynamic 166 | { 167 | var fromData:Dynamic = {}; 168 | var name:String; 169 | 170 | //set from 171 | if (Reflect.hasField(data, "from")) 172 | { 173 | var from:Dynamic = data.from; 174 | for (name in Reflect.fields(from)) 175 | { 176 | Reflect.setProperty(obj, name, Reflect.field(from, name)); 177 | Reflect.setField(fromData, name, Reflect.field(initData, name)); 178 | } 179 | } 180 | 181 | //set fromDelta 182 | if (Reflect.hasField(data, "fromDelta")) 183 | { 184 | var fromDelta:Dynamic = data.fromDelta; 185 | for (name in Reflect.fields(fromDelta)) 186 | { 187 | Reflect.setProperty(obj, name, Reflect.getProperty(obj, name) + Reflect.field(fromDelta, name)); 188 | Reflect.setField(fromData, name, Reflect.field(initData, name)); 189 | } 190 | } 191 | 192 | //clone properties 193 | var properties:Dynamic; 194 | if (Reflect.hasField(data, "properties")) 195 | properties = UIBuilder.cloneObject(data.properties); 196 | else 197 | properties = {}; 198 | 199 | //set delta 200 | if (Reflect.hasField(data, "delta")) 201 | { 202 | var delta:Dynamic = data.delta; 203 | for (name in Reflect.fields(delta)) 204 | Reflect.setField(properties, name, Reflect.getProperty(obj, name) + Reflect.field(delta, name)); 205 | } 206 | 207 | //set init data for from and fromDelta (if not exist) 208 | for (name in Reflect.fields(fromData)) 209 | if (!Reflect.hasField(properties, name)) 210 | Reflect.setField(properties, name, Reflect.field(fromData, name)); 211 | 212 | return properties; 213 | } 214 | 215 | private function recoverInitData(obj:Dynamic, initData:Dynamic):Void 216 | { 217 | for (name in Reflect.fields(initData)) 218 | { 219 | Reflect.setField(obj, name, Reflect.field(initData, name)); 220 | } 221 | } 222 | 223 | private function saveInitData(obj:Dynamic, properties:Dynamic, delta:Dynamic, from:Dynamic, fromDelta:Dynamic):Dynamic 224 | { 225 | var data:Dynamic = {}; 226 | var name:String; 227 | 228 | for (name in Reflect.fields(properties)) 229 | { 230 | if (Reflect.hasField(obj, name)) 231 | { 232 | Reflect.setField(data, name, Reflect.field(obj, name)); 233 | } 234 | } 235 | 236 | for (name in Reflect.fields(delta)) 237 | { 238 | if (Reflect.hasField(obj, name)) 239 | { 240 | Reflect.setField(data, name, Reflect.field(obj, name)); 241 | } 242 | } 243 | 244 | for (name in Reflect.fields(from)) 245 | { 246 | if (Reflect.hasField(obj, name)) 247 | { 248 | Reflect.setField(data, name, Reflect.field(obj, name)); 249 | } 250 | } 251 | 252 | for (name in Reflect.fields(fromDelta)) 253 | { 254 | if (Reflect.hasField(obj, name)) 255 | { 256 | Reflect.setField(data, name, Reflect.field(obj, name)); 257 | } 258 | } 259 | 260 | return data; 261 | } 262 | 263 | private function stopAll(root:DisplayObject):Void 264 | { 265 | var container:DisplayObjectContainer = cast root; 266 | 267 | for (obj in _saveData.keys()) 268 | { 269 | if (root == obj || container != null && container.contains(cast obj)) 270 | stopTween(cast obj); 271 | } 272 | } 273 | 274 | } 275 | 276 | -------------------------------------------------------------------------------- /demo/src/feathers/textures/Scale3Textures.hx: -------------------------------------------------------------------------------- 1 | /* 2 | Feathers 3 | Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved. 4 | 5 | This program is free software. You can redistribute and/or modify it in 6 | accordance with the terms of the accompanying license agreement. 7 | */ 8 | package feathers.textures; 9 | import openfl.geom.Rectangle; 10 | import openfl.errors.ArgumentError; 11 | 12 | import starling.textures.Texture; 13 | 14 | /** 15 | * Slices a Starling Texture into three regions to be used by Scale3Image. 16 | * 17 | * @see feathers.display.Scale3Image 18 | */ 19 | class Scale3Textures 20 | { 21 | /** 22 | * @private 23 | */ 24 | inline private static var SECOND_REGION_ERROR:String = "The size of the second region must be greater than zero."; 25 | 26 | /** 27 | * @private 28 | */ 29 | inline private static var SUM_X_REGIONS_ERROR:String = "The combined height of the first and second regions must be less than or equal to the width of the texture."; 30 | 31 | /** 32 | * @private 33 | */ 34 | inline private static var SUM_Y_REGIONS_ERROR:String = "The combined width of the first and second regions must be less than or equal to the height of the texture."; 35 | 36 | /** 37 | * If the direction is horizontal, the layout will start on the left and continue to the right. 38 | */ 39 | inline public static var DIRECTION_HORIZONTAL:String = "horizontal"; 40 | 41 | /** 42 | * If the direction is vertical, the layout will start on the top and continue to the bottom. 43 | */ 44 | inline public static var DIRECTION_VERTICAL:String = "vertical"; 45 | 46 | /** 47 | * @private 48 | */ 49 | private static var HELPER_RECTANGLE:Rectangle = new Rectangle(); 50 | 51 | /** 52 | * Constructor. 53 | * 54 | * @param texture A Starling Texture to slice up into three regions. It is recommended to turn of mip-maps for best rendering results. 55 | * @param firstRegionSize The size, in pixels, of the first of the three regions. This value should be based on the original texture dimensions, with no adjustments for scale factor. 56 | * @param secondRegionSize The size, in pixels, of the second of the three regions. This value should be based on the original texture dimensions, with no adjustments for scale factor. 57 | * @param direction Indicates if the regions should be positioned horizontally or vertically. 58 | */ 59 | public function new(texture:Texture, firstRegionSize:Float, secondRegionSize:Float, direction:String = DIRECTION_HORIZONTAL) 60 | { 61 | if(secondRegionSize <= 0) 62 | { 63 | throw new ArgumentError(SECOND_REGION_ERROR); 64 | } 65 | var textureFrame:Rectangle = texture.frame; 66 | if(textureFrame == null) 67 | { 68 | textureFrame = HELPER_RECTANGLE; 69 | textureFrame.setTo(0, 0, texture.width, texture.height); 70 | } 71 | var sumRegions:Float = firstRegionSize + secondRegionSize; 72 | if(direction == DIRECTION_HORIZONTAL) 73 | { 74 | if(sumRegions > textureFrame.width) 75 | { 76 | throw new ArgumentError(SUM_X_REGIONS_ERROR); 77 | } 78 | } 79 | else if(sumRegions > textureFrame.height) //vertical 80 | { 81 | throw new ArgumentError(SUM_Y_REGIONS_ERROR); 82 | } 83 | this._texture = texture; 84 | this._firstRegionSize = firstRegionSize; 85 | this._secondRegionSize = secondRegionSize; 86 | this._direction = direction; 87 | this.initialize(); 88 | } 89 | 90 | /** 91 | * @private 92 | */ 93 | private var _texture:Texture; 94 | 95 | /** 96 | * The original texture. 97 | */ 98 | public var texture(get, never):Texture; 99 | public function get_texture():Texture 100 | { 101 | return this._texture; 102 | } 103 | 104 | /** 105 | * @private 106 | */ 107 | private var _firstRegionSize:Float; 108 | 109 | /** 110 | * The size of the first region, in pixels. 111 | */ 112 | public var firstRegionSize(get, never):Float; 113 | public function get_firstRegionSize():Float 114 | { 115 | return this._firstRegionSize; 116 | } 117 | 118 | /** 119 | * @private 120 | */ 121 | private var _secondRegionSize:Float; 122 | 123 | /** 124 | * The size of the second region, in pixels. 125 | */ 126 | public var secondRegionSize(get, never):Float; 127 | public function get_secondRegionSize():Float 128 | { 129 | return this._secondRegionSize; 130 | } 131 | 132 | /** 133 | * @private 134 | */ 135 | private var _direction:String; 136 | 137 | /** 138 | * The direction of the sub-texture layout. 139 | * 140 | * @default Scale3Textures.DIRECTION_HORIZONTAL 141 | * 142 | * @see #DIRECTION_HORIZONTAL 143 | * @see #DIRECTION_VERTICAL 144 | */ 145 | public var direction(get, never):String; 146 | public function get_direction():String 147 | { 148 | return this._direction; 149 | } 150 | 151 | /** 152 | * @private 153 | */ 154 | private var _first:Texture; 155 | 156 | /** 157 | * The texture for the first region. 158 | */ 159 | public var first(get, never):Texture; 160 | public function get_first():Texture 161 | { 162 | return this._first; 163 | } 164 | 165 | /** 166 | * @private 167 | */ 168 | private var _second:Texture; 169 | 170 | /** 171 | * The texture for the second region. 172 | */ 173 | public var second(get, never):Texture; 174 | public function get_second():Texture 175 | { 176 | return this._second; 177 | } 178 | 179 | /** 180 | * @private 181 | */ 182 | private var _third:Texture; 183 | 184 | /** 185 | * The texture for the third region. 186 | */ 187 | public var third(get, never):Texture; 188 | public function get_third():Texture 189 | { 190 | return this._third; 191 | } 192 | 193 | /** 194 | * @private 195 | */ 196 | private function initialize():Void 197 | { 198 | var textureFrame:Rectangle = this._texture.frame; 199 | if(textureFrame == null) 200 | { 201 | textureFrame = HELPER_RECTANGLE; 202 | textureFrame.setTo(0, 0, this._texture.width, this._texture.height); 203 | } 204 | var thirdRegionSize:Float; 205 | if(this._direction == DIRECTION_VERTICAL) 206 | { 207 | thirdRegionSize = textureFrame.height - this._firstRegionSize - this._secondRegionSize; 208 | } 209 | else 210 | { 211 | thirdRegionSize = textureFrame.width - this._firstRegionSize - this._secondRegionSize; 212 | } 213 | 214 | var hasTopFrame:Bool; 215 | var hasRightFrame:Bool; 216 | var hasBottomFrame:Bool; 217 | var hasLeftFrame:Bool; 218 | var firstRegion:Rectangle; 219 | var firstFrame:Rectangle; 220 | var secondRegion:Rectangle; 221 | var secondFrame:Rectangle; 222 | var thirdRegion:Rectangle; 223 | var thirdFrame:Rectangle; 224 | if(this._direction == DIRECTION_VERTICAL) 225 | { 226 | var regionTopHeight:Float = this._firstRegionSize + textureFrame.y; 227 | var regionBottomHeight:Float = thirdRegionSize - (textureFrame.height - this._texture.height) - textureFrame.y; 228 | 229 | hasTopFrame = regionTopHeight != this._firstRegionSize; 230 | hasRightFrame = (textureFrame.width - textureFrame.x) != this._texture.width; 231 | hasBottomFrame = regionBottomHeight != thirdRegionSize; 232 | hasLeftFrame = textureFrame.x != 0; 233 | 234 | firstRegion = new Rectangle(0, 0, this._texture.width, regionTopHeight); 235 | firstFrame = (hasLeftFrame || hasRightFrame || hasTopFrame) ? new Rectangle(textureFrame.x, textureFrame.y, textureFrame.width, this._firstRegionSize) : null; 236 | this._first = Texture.fromTexture(texture, firstRegion, firstFrame); 237 | 238 | secondRegion = new Rectangle(0, regionTopHeight, this._texture.width, this._secondRegionSize); 239 | secondFrame = (hasLeftFrame || hasRightFrame) ? new Rectangle(textureFrame.x, 0, textureFrame.width, this._secondRegionSize) : null; 240 | this._second = Texture.fromTexture(texture, secondRegion, secondFrame); 241 | 242 | thirdRegion = new Rectangle(0, regionTopHeight + this._secondRegionSize, this._texture.width, regionBottomHeight); 243 | thirdFrame = (hasLeftFrame || hasRightFrame || hasBottomFrame) ? new Rectangle(textureFrame.x, 0, textureFrame.width, thirdRegionSize) : null; 244 | this._third = Texture.fromTexture(texture, thirdRegion, thirdFrame); 245 | } 246 | else //horizontal 247 | { 248 | var regionLeftWidth:Float = this._firstRegionSize + textureFrame.x; 249 | var regionRightWidth:Float = thirdRegionSize - (textureFrame.width - this._texture.width) - textureFrame.x; 250 | 251 | hasTopFrame = textureFrame.y != 0; 252 | hasRightFrame = regionRightWidth != thirdRegionSize; 253 | hasBottomFrame = (textureFrame.height - textureFrame.y) != this._texture.height; 254 | hasLeftFrame = regionLeftWidth != this._firstRegionSize; 255 | 256 | firstRegion = new Rectangle(0, 0, regionLeftWidth, this._texture.height); 257 | firstFrame = (hasLeftFrame || hasTopFrame || hasBottomFrame) ? new Rectangle(textureFrame.x, textureFrame.y, this._firstRegionSize, textureFrame.height) : null; 258 | this._first = Texture.fromTexture(texture, firstRegion, firstFrame); 259 | 260 | secondRegion = new Rectangle(regionLeftWidth, 0, this._secondRegionSize, this._texture.height); 261 | secondFrame = (hasTopFrame || hasBottomFrame) ? new Rectangle(0, textureFrame.y, this._secondRegionSize, textureFrame.height) : null; 262 | this._second = Texture.fromTexture(texture, secondRegion, secondFrame); 263 | 264 | thirdRegion = new Rectangle(regionLeftWidth + this._secondRegionSize, 0, regionRightWidth, this._texture.height); 265 | thirdFrame = (hasTopFrame || hasBottomFrame || hasRightFrame) ? new Rectangle(0, textureFrame.y, thirdRegionSize, textureFrame.height) : null; 266 | this._third = Texture.fromTexture(texture, thirdRegion, thirdFrame); 267 | } 268 | } 269 | } 270 | --------------------------------------------------------------------------------