How to extend class that is inside a loaded swf - actionscript-3

I've got an swf loaded externally to my app with loader component. It is loaded to the Application Domain of my loader. I've got a class in that swf wich I would like to extend and override some functions from it. Is it possible somehow?
Here is some code to explain what I want(of course, it is fully incorrect and wold not work):
public var ClassFromLoadedSwf:Class = ApplicationDomain.currentDomain.getDefinition("path.to.needed.class") as Class;
public class MyClass extends ClassFromLoadedSwf
{
override protected function initMovie() : void
{
//function logic goes here
}
}
Thank you for your answers and sorry for my bad english.

No you can't. Basically you don't understand the meaning of ApplicationDomain. Using a loader and Applicaiton Domain you just merge some code to your SWF in Runtime. Before it reaches the Runtime state, it can't be accessed. So at the Compile time you can't do what you're trying to do now. But you can try to use SWC instead of SWF. You just include it in your Project Library and that's all. You'll be able to access all the classes at compile time. Try reading this Article. It will help you understand the meaning of SWCs.

Related

Need some help getting started with OOD in ActionScript 3

So being new to AS3 but not development in general, during a recent project that I just started I hit an immediate snag where my normal method of OOD is causing errors in AS3.
I created a layer in Adobe Flash called code just to keep everything separate and in frame one under actions I used the following code to get started:
var GameContainerSize:int = 400;
class GameInfo {
var GameID:int;
var HomeTeam:String;
var VisitingTeam:String;
function GameInfo()
{
}
}
This simple code immediately causes an error though
Scene 1, Layer 'Code', Frame 1, Line 4 1131: Classes must not be nested.
And my best guess is this is because the timeline and all code on it exists within a class already. So what should I be doing if I want to develop this program using class objects, or is this even possible in flash?
You can't define classes on the timeline. Each timeline is exported as a class, var and function declarations become members of the class, and frame code is moved to its own frame functions which are called when the timeline reaches that frame. Thus the error is saying "you can't put a class in a class" because the timeline already is a class.
To define classes you must use external .as files with package blocks:
// GameInfo.as
package {
public class GameInfo {
public var GameID:int;
public var HomeTeam:String;
public var VisitingTeam:String;
public function GameInfo(){ }
}
}
In Flash Pro you can link a class to a timeline (document or symbols). Such a class must extend Sprite or MovieClip.
You can also refer to any of your classes from any frame script. For example, you could put on frame 1 of your main timeline:
var gameInfo:GameInfo = new GameInfo();
Typical OOP would involve using external .as class files for almost everything, with only minimal function calls on your timeline frames, like stop() at the end of a timeline or calling a custom function you've added to the class linked to the timeline.
I created a layer
That's not ideal. The problem is that it will not get you any closer to understanding the code, because it isn't code. It's a feature of the flash authoring environment. You might as well spend a day with the drawing tool drawing something.
to keep everything separate and in frame one under actions
Organisation is important, but layers aren't the way to go. As each class definition goes into its own external file, you have to create additional files anyway if you want to create more classes. And you want to create more classes because having only one is horrible object oriented design. Being consistent here is important. That's why people in the comments suggested to use a document class and have no code on any frames. All code is organised in classes. No exceptions1.
Having said all that, I highly advice against using Adobe Flash to learn As3. There's too much obfuscation going on behind the scenes. If you want to learn how to code As3, use a code editor. (or plain text editor + compiler if you prefer). Learning what settings dialog has to be adjusted in order to get what you want is not going to get you any closer to understanding OOD in As3.
I also see package, is this kind of like a namespace and does it need to be named, if not what is its purpose?
No, packages are packages and namespaces are namespaces. Apples and oranges.
Packages are used to organize classes just like a structure of
folders is used to organize the .as fiels of those classes. In fact,
the package is pretty much exactly that folder structure, for example:
flash.display is for all display related classes
flash.events is for events
A namespace allows you to control access to members of a class. Namespaces are very rarely used in As3. Here's an article from grant skinner about namespaces. Personally, I never needed to use namespaces. If you are jsut getting started, you can very well ignore them for now.
That sounds perfect! except I cannot get it to launch on my Win10 machine. I may just end up outsourcing this at this ratio
flash develop is the alternative editor. It's free, fast and lightweight.
my normal method of OOD
You want to extend your definition of normal with
always explicitly specify the access control modifiers
member names start with small letters
public class GameInfo {
private var gameID:int;
private var homeTeam:String;
private var visitingTeam:String;
function GameInfo()
{
}
}
1admittedly, there are top level functions that are pretty much free floating functions without a class. If you want to do oop, this is not what you want. It's for the occasional independent utility function. Stick to classes for now.

Actionscript 3 getDefinitionByName not seeing classes

I've worked around this with a hack for now, but would rather know if there's a right way to do it. I have a function that churns out MovieClips, which are tiles for a map that I then attach to the stage. It determines which class of tile to use based on a string variable, like this:
// symbolID holds our class name, determined by logic above
var newClass:Class = getDefinitionByName(symbolID) as Class;
var newtile:MovieClip = new newClass();
This works, but only if an instance of the class already exists somewhere else in the code. It could be anywhere-- in the document class, in some buried function of a helper class, it doesn't seem to matter. If not, Flashdevelop throws error 1065, "Variable (the variable) is not defined". I mention that I'm using Flashdevelop because it seems like it might be compiler-specific, but I'm not sure.
My hack fix is to do this:
var a:baseTile;
a as anotherTile;
a as aThirdTile;
and so on, which works, but definitely isn't ideal if I'm going to have hundreds of these tile classes eventually.
Edit: I should add that these movieclips are coming from a .swc file, which comes from Flash Professional.
You have to use the 'hack'.
getDefinitionByName() can only work with classes that exist at runtime. Unfortunately, if you don't make use of a class, it won't be compiled and won't exist at runtime.
Library symbols make getting around this a little easier. If you check the box that has them available automatically at a given frame, you can just make sure your getDefinitionByName() calls are done during or after that frame.
While SWC libraries can include specific classes to include in the build path, Flash compiler will not link unreferenced classes to a SWF; therefore, requires a linkage library.
Example linkage to retain classes:
/** linkage library */
private static const classA:ClassA;
private static const classB:ClassB;
private static const classC:ClassC;
Another option would be to load the classes from a RSL (Runtime Shared Library).
Basically yes, you need to have a strict reference of that class somewhere in your code. You can even make that reference "unreferenced" elsewhere. I have a hundred of classes like this, and I had to make a single Array of these classes, located somewhere inside the project. I have placed it aside the function that calls getDefinitionByName() to make sure the classes are available in that function.
private static const dummy:Array=[Rock01, Rock02,...,Gem01,Gem02,...];
So you can use such an Array listing all your tiles that you have in your project and want to be accessible by getDefinitionByName().

actionscript 3.0 referencing a custom class of a main swf from a loaded swf's custom class

I am writing educational software that utilizes a single "application" swf, which loads external "topic" swf files (containing library items specific to the topic). Each of these external "topic" swf files also utilizes custom classes that solve calculations specific to the topic (ex. trigonometry class for the trigonometry.swf topic file).
I want the trigonometry class of the trigonometry.swf to be able to reference a custom class method that exists in the main "application" swf. If it helps to know the context, I want the user working on trigonometry to be able to type in the trig function the believe to be correct (sin, cos, or tan) and "check" to see if they are right. The "indicate_right_wrong" method exists in a "grader" custom class of the main "application" swf (so that any changes I make to this class will be updated throughout all topics). So...how do I reference a custom class method of a main swf FROM an externally loaded swf file's own custom class?
I DO have the result working when I import the "grader" custom class into each "topic" swf and reference it directly, but I don't want to have to re-publish each topic swf if I make a change to the "grader" custom class. Thus, I'm trying to have each topic capable of referencing the "grader" custom class when it exists within the main "application" swf.
The error I get when I try using variations of parent or parent.parent are property grader_class not found on flash.display.Stage (for parent) and Cannot access a property or method of a null object reference. (when using parent.parent).
Thank you for any help you can provide.
You can't compile code that calls methods not found in the code being compiled. However, you can make runtime calls by evaluating a method. For example:
stage["myfunction"](args);
However, while you could create some sort of pathing logic to reference your methods, as George Profenza indicated, your success will be much higher (and easier to work with) if you simply pass a function listener to a dispatched event or method call.
For example, let's assume you have a custom CHECK_ANSWER event that fires when the user enters an answer. Your gradeAnswer() function (that exists in your "application.swf") would need to register for that event after the child "trigonometry.swf" was loaded. Subsequently, and the data would be passed through.
This, however, may not be ideal as it can cause the child SWF to not unload from memory properly due to a parent registration to a child object (all registrations must be removed first).
Personally, I'd recommend creating a static class which serves as a directory for your application. Each swf loads this class, and lists their pertinent methods as needed. For example:
package com.atriace {
public class Directory {
public static var methods:Object = {
}
}
}
When the application.swf loads, it populates the methods object with your grading function. Subsequent child swfs also load this static class, and expect to find your grade method pre-populated.
Application.swf
import com.atriace.Directory;
Directory.methods["grade"] = gradeAnswer;
Child.swf
import com.atriace.Directory;
Directory.methods["grade"](answers);
Don't know if the quiet is because this kind of question has been answered many times before on Stack Overflow. Anyways here is my take on it..
I want the user working on trigonometry to be able to type in the trig
function the believe to be correct (sin, cos, or tan) and "check" to
see if they are right.
I'm assuming since they have to type the answer you have an input textbox? Also when they have answered they press a button to "submit" their answer? Assuming I'm on the right lines we can do that this way...
note: answer_txt (string) = answer given in external class by user, input_txt = textfield for user input
In the main class have something like
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.*;
import ExternalClass; //your class file attached to relevant topic swf
public class Main extends MovieClip
{
private var _extClass = new ExternalClass(); //create reference to external Class
public function Main()
{
//Ref 1 means do that function when trigger event received from external class
stage.addChild(_extClass); //gives access to "stage" for ExternalClass.as
_extClass.addEventListener("Check_Answer", indicate_right_wrong); //see Ref 1
}
private function indicate_right_wrong (e:Event)
{
//your answer checking code.
//Access answer_txt variable from external class like example below
//_extClass.answer_txt.text = " ";
}
Now in the external class (Trigonometry.as??) you can set up something like this. Make sure answer_txt exists (public var answer_txt:String;)..
public function Question_1 () : void
{
//your code for question + set submit button
submit_BTN.addEventListener(MouseEvent.CLICK, send_Answer);
}
function send_Answer(e:MouseEvent):void
{
answer_txt = input_txt.text; //set input text as final answer
trace("final answer is..." + answer_txt); //just to test it's there
dispatchEvent (new Event ("Check_Answer")); //Main class is waiting for this event (ref 1)
trace ("event dispatched.." + dispatchEvent); //to confirm it was despatched
}

ActionScript Frame metadata not working

I know there exist a lot of posts about the Frame metadata tag in ActionScript,
but I still didn't find an answer to my question.
The problem is, I have specified a Frame metadata tag above my Main class header:
package gameUI {
...
[Frame(factoryClass="gameUI.MyPreloader")]
public class Main extends Sprite {
public function Main()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{ ...
I also have a preloader class in the same package (gameUI) called MyPreloader.as
package gameUI
{
// imports..
public class MyPreloader extends MovieClip
{
// private vars ..
public function MyPreloader()
{
trace('preloader START');
...
In my IDE, i don't get any errors or warnings. It compiles without problems.
But when I run it, it just skips over the Frame meta tag and just runs the code of the Main class. (The trace in the constructor of MyPreloader is never printed out).
I'm thinking maybe it has something to do with some arguments specified in the compiler settings. I've tried some couple of things, aditional compiler arguments but it never worked.
Does anyone know why he ignores the Frame metatag?
I'm really frustrated right now..
I'm using Flash Builder 4.6.
Compiling with Flex SDK 4.6.
thanks.
Your Main Class is a Sprite, so it can't have two frames. That may be part of your problem.
However, it might be that you can use a process that's easier to debug to accomplish the ultimate goal. For example, this is one approach. I personally usually just set my default export frame as 10, put a spinner on frame 1 and issue a play().
The only assets that need to be compiled on Frame 1 are in the spinner. It will then pause while the spinner spins and the assets load (because it has to load everything compiled there before it can proceed). Once all the assets have loaded, it will naturally advance to Frame 10. I will have an instance on the timeline at Frame 10 that has an associated getter and setter, so when the setter triggers, I know that loading is complete.
I only check "Export in Frame 10" for assets that absolutely have to be loaded at startup (for example, sounds or visual objects that are never used on the timeline).
The advantage of this approach is that you can get to the real content earlier (because only assets compiled on your default frame have to load before you can show anything), but the disadvantage is that it makes no sense to show % progress, since you have no idea what percent of the movie is compiled on frame 10 and needs to load before it will start.
So, in summary:
Try making the Base Class for your fla a MovieClip
If that doesn't work, consider changing approach

how to access class from embedded swf

I am trying to get an instance of a specific class from an embedded swf, it so happens the class I need is also the Default Application extending Sprite for the swf. I am able to do this successfully if I load the swf however I want to embed it instead.
The class I want to load is also extending a custom interface. Here is what I have tried but is not working:
[Embed(source="resources/MySwf.swf")]
private var MySwf:Class;
private function someFunction() : void
{
var inst:ISomeInterface = new MySwf() as ISomeInterface;
}
I appreciate any pointers.
Thanks.
Docs for embedding are here:
http://livedocs.adobe.com/flex/3/html/help.html?content=embed_4.html
You should be able to do something like:
[Embed(source='resources/MySwf.swf', symbol='TheExportNameInMyFlaLibrary')]
public var MySwf:Class;
Personally, I prefer to use the Flash IDE publish settings to be have Export as SWC checked. That way, you can just drop the SWC into your FlashBuilder projects' lib folder and be done. Don't have to worry about manually setting each class up like this.