actionscript-3apache-flexflex4.6flex-mobilefxg

Select an FXG file at the runtime - by its name


I have a test case demonstrating my problem.

It runs instantly, when you add the following 4 short files into a new Flex Mobile project in Flash Builder 4.6:

Screenshot

src/TestFXG.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    firstView="Home">
</s:ViewNavigatorApplication>

src/assets/en/Star.fxg:

<?xml version='1.0' encoding='UTF-8'?>
<fxg:Graphic xmlns:fxg="http://ns.adobe.com/fxg/2008" version="2">    
    <fxg:Path x="9.399" y="10.049" data="M 82.016 78.257 L 51.895 69.533 L 27.617 89.351 L 26.621 58.058 L 0.231 41.132 L 29.749 30.52 L 37.714 0.241 L 56.944 24.978 L 88.261 23.181 L 70.631 49.083 Z">
        <fxg:fill>
            <fxg:SolidColor color="#FFFFFF"/>
        </fxg:fill>
        <fxg:stroke>
            <fxg:SolidColorStroke 
                caps="none" 
                color="#FFFF66" 
                joints="miter" 
                miterLimit="4" 
                weight="10"/>
        </fxg:stroke>
    </fxg:Path>
</fxg:Graphic>

src/Home.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:my_components="*"
        title="Display random amount of stars">

    <fx:Script>
        <![CDATA[
            import Star;
            import spark.core.SpriteVisualElement;

            private static const STAR:SpriteVisualElement = new Star();
        ]]>
    </fx:Script>    

    <my_components:MyComp />
</s:View>

src/MyComp.as:

package {
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.utils.getDefinitionByName;
    import mx.core.UIComponent;
    import spark.core.SpriteVisualElement;
    import assets.Star;

    public class MyComp extends UIComponent {
        private static const WHAT:String = "assets.en.Star";

        override protected function createChildren():void {
            super.createChildren();

            for (var i:uint = 0; i < 3; i++) {
                var star:Star = new Star();
                //var star:SpriteVisualElement = new (getDefinitionByName(WHAT) as Class)();
                star.x = Math.random() * 100;
                star.y = Math.random() * 100;
                addChild(star);
            }
        }
    }
}

My question is: provided I have many appropriately named FXG files in the assets sub-directory (in my real application I have spades_queen.fxg, spades_king.fxg, spades_ace.fxg etc.) - how can I select an FXG file at the runtime?

The commented line above gives me the runtime error:

ReferenceError: Error #1065: Variable Star is not defined.
    at global/flash.utils::getDefinitionByName()

When I move the src/assets/en/Star.fxg to src/Star.fxg everything works...


Solution

  • I'm guessing you're getting this runtime error because the Star.fxg is not compiled into the finished app because it is not used by name. It is confusing why moving the location of the file would bypass the error.

    But, try adding the file reference in their. Import it:

    import assets.en.Star
    

    And create a dum instance that you never use just so the file is sure to be compiled into the app:

    private var myStart :Star;
    

    Then this line, should work:

    var star:SpriteVisualElement = new (getDefinitionByName(WHAT) as Class)();
    

    You can also use a compiler argument to force the FXG class to be compiled into your finished application.

    I use this same exact approach in my Casual Game, built in Flex.

    However, the weird thing is why moving the file to a different directory causes things to work w/o issues. That is a puzzler, unless you were referencing the wrong package. (AKA assets.en.Star--as you use in code--verse src/assets/Star which you reference in the question).