상세 컨텐츠

본문 제목

[AS] swc 안의 class를 getDefinition, getDefinitionByName 으로 불러내기 관련

ADOBE/ ActionScript

by AlrepondTech 2020. 9. 22. 01:56

본문

반응형

 

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

출처: http://www.thegrego.com/2012/03/20/swc-file-as-embedded-runtime-asset-library/

SWC File as Embedded Runtime Asset Library

March 20, 2012

 

 

This post is really for myself so that I have somewhere that I can look this up again. Maybe it’ll be helpful to someone else in to the future too.

When working in flash (which I find myself doing less and less now a days), one of my favorite ways to work with assets is through the use of swc files. That’s what they’re there for anyways right? Well what’s not so obvious is how to use swc files to load assets at runtime without using the import command. There are times that it’s useful to refer to an asset at runtime by name that you may or may not use, so you don’t want to explicitly go through the hassle of writing the lines to embed it. This often happens with sounds or items that are easier to loop through to use, such as when using a map of the US. It’s much easier to write a loop vs writing 51 embed statements (yes, I know that there are a million different ways of doing this without writing all of that).

When you do something like going through a loop and saying getDefinitionByName(“state_”+i) to grab a library item that resides in the swc asset file, there are no compiletime errors because Flash Builder can find that swc in the library. But once it runs, the debugger will yell at you. To fix this, you need to embed the swc file at compile time. In Flash Builder, this is done in the Actionscript Compiler settings and all you have to do is add this line (replacing it with the path to your asset swc file obviously)

-include-libraries /assets/assets.swc

Now when you run your swf, it’ll work like a charm and you’ll have those assets available without having to import them in the head of your class file. That being said, be sure to only do this when it makes sense. This embeds the swc file into your swf. So if there are assets in the library that are outdated and set to export at compile time, they’ll be included adding extra senseless bloat. As I write this, I’m using this method for a prototype where bloat doesn’t really matter, but just be mindful of that

 

 

 

 

=================================

=================================

=================================

 

 

 

 

Quick Tip: Understanding getDefinitionByName()

By Joseph Clover,21 Oct 2011

In this Quick Tip, you'll learn how to construct a reference to a class from a String, and then create an instance of that class, using a built-in AS3 function calledgetDefinitionByName(). You'll also learn the best methods for using this in different situations.

Why Is getDefinitionByName() Useful?

getDefinitionByName() is very useful if you need to make new instances of classes by using a String. For example, if you had seven different tiles - each represented by a class called Tile1, Tile2, etc - and you needed to create an instance of each, you would have to write the following code:

private function createTiles():void
{
    var tile1:Tile1 = new Tile1();
    var tile2:Tile2 = new Tile2();
    var tile3:Tile3 = new Tile3();
    var tile4:Tile4 = new Tile4();
    var tile5:Tile5 = new Tile5();
    var tile6:Tile6 = new Tile6();
    var tile7:Tile7 = new Tile7();
    stage.addChild( tile1 );
    stage.addChild( tile2 );
    stage.addChild( tile3 );
    // You get the idea, it is very lengthy!
}

getDefinitionByName() allows you to solve this problem!

How to Use It

Now, the above code was a little messy and we had to type many lines just to make a few different tiles. This is how we could achieve the same goal usinggetDefinitionByName():

private function createTiles():void
{
    for( var i:int = 1; i < 8; i++ )
    {


        var tileRef:Class = getDefinitionByName( "Tile" + i ) as Class;
        var tile:Sprite = new tileRef();
        stage.addChild( tile );


    }
}

In line 6, getDefinitionByName() returns a reference of the class called "Tile + the current value of i in the for-loop". So, when i is equal to 1,getDefinitionByName("Tile" + i); returns a reference to the class Tile1. We then create the tile and add it to the stage.

(We can't write var tile:tileRef because tileRef does not refer to anything at compile time; if you try, you'll get a compiler error.)

However, when you run this code, it will not work! You'll get a variable is undefinederror message, in most cases, because "Tile1" might not be enough information for Flash to find the class. Let's look at some workarounds.

Make It Work

There are a few commonly-used methods to solve the problem of the variable is undefined error you'll get when you run the above code, and I am going to teach you what they are. I would also like to give credit to Gert-Jan van der Well of Floorplanner Tech Blog for this blog post.

Here are some of the methods you can use:

  • Use a Dummy Variable
  • Use short notation of Class name
  • Include the full path in the String
  • Include the class's SWC in your project

Using a Dummy Variable

In this method, you just create some dummy variables with references to the classes you want to refer to with getDefinitionByName() later:

private var dummyTile1:Tile1;
private var dummyTile2:Tile2;
//etc


private function createTiles():void
{
    //Create the tiles
}

This works, but it is very ugly. If you have the Tile classes in another package, you would also have to import them!

Short Notation

This is much like the Dummy Variable method, but you don't bother setting up a dummy variable for each class; you just drop a few explicit references to the classes themselves:

Tile1;Tile2;Tile3;Tile4;Tile5;Tile6;Tile7;
//etc


private function createTiles():void
{
    //Create the tiles
}

Now, this may look neater, but the fact that you will have to update this list everytime you make a new Tile remains.

Including the Full Path Name

Another method, which is the tidiest (if you have classes in another package) is to include the full path name in your String:

//Let's say my Tiles are all in the package 'project.Tiles'


private function createTiles():void
{
    for( var i:int = 1; i < 8; i++ )
    {


        var tileRef:Class = getDefinitionByName( "project.Tiles.Tile" + i ) as Class;
        var tile:tileRef = new tileRef();
        stage.addChild( tile );


    }
}

Much tidier! However, this only works if the classes are in a separate package from this class.

Using a SWC

If the Tiles are held in an SWC, you can make this much easier, without needing to use any imports or dummy variables. I would like to give credit to v0id from Dreaming in Flash for this blog post that explained to me how to use this method:

  • In the project properties choose "ActionScript Compiler"
  • To the "Additional compiler arguments" field, add the following: include-libraries PATH_TO_SWC

The PATH_TO_SWC must be the absolute path and not the relative path!

Great, all these methods have now been explained. Unfortunately, there are no fantastic magical methods to use if you have all the tiles in the same package as all the other AS Files. I would recommend you make a new package called Tiles or something if you want to use the good methods!

Conclusion

Well, today you should have learnt how to use getDefinitionByName() and the best methods of using it. I hope this will help you in any future projects and if you have any questions, leave them in the comments section below!

 

 

 

=================================

=================================

=================================

 

 

Flash compiler arguments - force SWC inclusion

 

'm trying to write a compiler argument for FDT to force the inclusion of one of my SWCs. It looks kind of like this (App name changed, but the real one also contains mixed case and a space):
Problem is that the compiler claims it is unable to open this file. Is there a problem maybe with using a full path like this? Ideally I would prefer to use a token to represent the project folder, something like -include-libraries "${project}/libs/site.swc", but I don't seem able to find a token list in the docs.
flash flex compiler fdt
add comment

1 Answer

activeoldestvotes

I didnt understand which tool you are using to compile flex If you are using
ANT this link is useful Working with compiler options
for Command Line Compiler option see this About the application compiler options
and for Flex/Flash builder you can include lib from project propertied
Properties>>Flex Build Path>>Library Path
EDITED for Command Line Compiler
You can use configuration files for command-line utilities and bulider
using these files you can define custom tokens like ${flexlib}
and for Tokens in services-configuration files see About configuration files
Hopes that helps
 

 

 

=================================

=================================

=================================

 

 

Using Flash CS4, I am making a game that has a dozen or so sounds and a couple of music tracks. To cut down on publish/compile time, I have moved the sounds and music into an (external) SWC, which is located in a "Library Path" for the project. This works, but with a caveat...
Until before I externalised the assets, I had been dynamically instantiating the Sound objects of the embedded sound by getting their classes with getDefinitionByName.
But now that they're located in an external SWC, I need to have "concrete" references to the classes in order to load them like this, otherwise they are not included in the published SWF, and there is a runtime error when getDefinitionByName tries to get a class that doesn't exist.
So, my question: in Flash Professional CS4, is there any way to force a library's assets to be included, regardless of whether they are statically linked?
FlashDevelop has a compiler option "SWC Include Libraries", which is exactly what I want, and is distinct from the "SWC Libraries" option. The description of the "SWC Include Libraries" option is "Links all classes inside a SWC file to the resulting application SWF file, regardless of whether or not they are used."
(Also, it's important to me that all the assets are contained within the one compiled SWF. Linking at runtime isn't what I'm after.)
flex flash actionscript-3 swc
 

4 Answers

activeoldestvotes

Unfortunately, I don't think so. I hope this is fixed in CS5, but I wouldn't bet on it...
The current (aggravating) standard is to have a manifest class in your SWC that references all the root classes in the rest of the library:
Then, somewhere in your main .fla...
 
There's no way to pull in and embed every class in an SWC by default in Flash CS4/CS5, but you may be able to do this with:

FlashDevelop

As you already know, this program's project properties has compiler options that differentiate between:
  • SWC Libraries: "Links SWC files to the resultin gapplication SWF file. The compiler only links in those classes for the SWC file that are required."
  • SWC Include Libraries: "Links ALL classes inside a SWC file to the resulting application SWF file, regardless of whether or not they are used."
That second option "SWC Include Libraries" could be useful, because if you simply compile your FLA as-is into a SWC, then put that SWC and your other SWC into FlashDevelop as SWC Include Libraries, it should compile/merge them into a single SWF that will work like you want.
FlashDevelop could also simply help you build a hard-coded list of Classes in an SWC, because if you link in the SWC as a SWC Library, it will show up in the project explorer, and you can see a list of all the classes in the SWC. You can also right click each class and choose "Insert Into Document", and it will insert the full class name. If you do that, then press semi-colon enter, you will have your first class reference. Keep your mouse over the class list in the project settings and repeat this for every class in the list. It only takes a few minutes to do this for hundreds of classes, which makes creating such a list easier. It would be even faster if the thing would let you insert more than one at once, but it doesn't seem to.
Your only other option, which you said you weren't interested in for no given reason, is Runtime Shared Libraries (RSLs). It's really not that big a deal to load the file in separately, but only if you properly handle the load process and any errors that might occur. It will add some complexity to your project, and may require some extra thought, but I'd seriously consider it as an option. See the "Application Domain Inheritance" section at www.senocular.com/flash/tutorials/contentdomains/?page=2 for more information.
 
You can supply the path of your assets.swc file, in ActionScript Properties, and that should work and load assets at runtime.
 
in flex, and whenever you have access to compiler options, you can use: -include YourClass to force the linking of the class from swc even if its not referenced from the main swf.
but i dont know if you can change compiler options from flash cs4...

 

 

 

=================================

=================================

=================================

 

 

출처: http://streammx.tistory.com/9

문제

main.swf 에서 sub.swf 를 불러와서 어떻게 상호제어 할 수 있을까?

AS2.0에서는 인스턴트네임을 이용해서 바로 접근이 가능했지만 3.0에 와서는 더 이상 그런 기능을 사용할 수 없습니다. 대신 인스턴스 네임이 아닌 getDefinition("클래스네임") 메서드를 이용해 해당 객체를 참조할 수 있습니다.

 

사용법

/******************************************

 * Main.as : 이벤트리스너 클래스

 * Sub.as : 이벤트를 발생하는 이벤트소스클래스

 ******************************************/

 

//Sub.as 클래스 -------------------------------------------

package

{
    import flash.display.Sprite;

    public class Sub extends Sprite
    {
        public function Sub()
        {
        }

        /**

         * @Func : init      main.swf 에서 제어할 메서드  

         **/

        public function init():String {
            trace( "Good Morning" );
        }

        /**

         * @Func : sentEventToMainSWF      main.swf 에서 Sub.swf로 이벤트를 보낼 메서드

         **/

        private function sentEventToMainSWF(): void

        {

            dispatchEvent( new Event( Event.CHANGE ));

        }
    }
}

 

//Main.as 클래스 -------------------------------------------

package

{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.events.Event;

    public class Main extends Sprite {
        private var _loader:ClassLoader;


        public function Main () {            
            this._loader = new ClassLoader();
            this._loader.addEventListener( ClassLoader.LOAD_ERROR,loadErrorHandler );
            this._loader.addEventListener( ClassLoader.CLASS_LOADED,classLoadedHandler );
            this._loader.load( "Sub.swf" );
        }
        private function loadErrorHandler( e:Event ):void {
            throw new IllegalOperationError("Cannot load the specified file.");
        }
        private function classLoadedHandler( e:Event ):void {

            var runtimeClassRef:Class = this._loader.getClass("Sub");

 

            //스테이지에 addChild 하려면...

            //var displaySub: DisplayObject = runtimeClassRef() as DisplayObject;

            //var sub: Object = displaySub as DisplayObject;


            var sub: Object = new runtimeClassRef(); 

            //Sub.swf 내부 init() 메서드 제어

          sub.init(); 

          //Sub.swf 에서 이벤트를 받을 리스너 등록

          sub.addEventListener( Event.CHANGE, onChangeHandler );
        }

        private function onChangeHandler ( e: Event ): void

        {

            //메서드 구현

        }

    }
}

 

//ClassLoader 클래스( 외부자원 로드클래스 )

package {
    import flash.display.Loader;
    import flash.errors.IllegalOperationError;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;

    class ClassLoader extends EventDispatcher {
        public static var CLASS_LOADED:String = "classLoaded";
        public static var LOAD_ERROR:String = "loadError";
        private var loader:Loader;
        private var swfLib:String;
        private var request:URLRequest;
        private var loadedClass:Class;

        public function ClassLoader() {
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
            loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
        }
        public function load(lib:String):void {
            swfLib = lib;
            request = new URLRequest(swfLib);
            var context:LoaderContext = new LoaderContext();
            context.applicationDomain = ApplicationDomain.currentDomain;

            //다른 폴더 같은 클래스명일 경우 사용.
            //context.applicationDomain = new ApplicationDomain();
            loader.load(request,context);
        }

 


        public function getClass(className:String):Class {
            try {

                 //Sub 클래스에 접근하기 위한 핵심 구문

                return loader.contentLoaderInfo.applicationDomain.getDefinition(className)  as  Class;
            } catch (e:Error) {
                throw new IllegalOperationError(className + " definition not found in " + swfLib);
            }
            return null;
        }


        private function completeHandler(e:Event):void {
            dispatchEvent(new Event(ClassLoader.CLASS_LOADED));
        }


        private function ioErrorHandler(e:Event):void {
            dispatchEvent(new Event(ClassLoader.LOAD_ERROR));
        }
        private function securityErrorHandler(e:Event):void {
            dispatchEvent(new Event(ClassLoader.LOAD_ERROR));
        }

    }
}

 

 

 

=================================

=================================

=================================

 

 

var l:Loader = (e.currentTarget as LoaderInfo).loader;

var homeClass:Class = l.contentLoaderInfo.applicationDomain.getDefinition"ui.HomeBtn" )  as  Class; //패키지.클래스명으로 찾는다.

homeBtn = new homeClass() as MovieClip;

 

 

=================================

=================================

=================================

 

 

 

반응형


관련글 더보기

댓글 영역