Cant call function from within object after saving with SharedObject - function

tl;dr --- I'm trying to create an object and have the name of a function inside that object, then save the object, load it later, and be able to call the function e.g. myFunction on the Main.as, based on the obj.fun() where obj.fun = myFunction or obj.fun = "myFunction";
I create a global variable
var master = {};
I create an object thusly
createMyObject():Object
{
obj = {
name:"myObject",
fun:myFunctionInMain
}
return obj
}
I then push the obj into an Array
master.myArray.push(obj);
Then I save
save.data.master = master;
Then I load
master = save.data.master;
Then I trace my object name like this:
trace(master.myArray[0].name) // output is correct "myObject" so the save and load worked
but when I call the function
master.myArray[0].fun();
it says value is not a function.
This works fine until I save then load... It's as if it isn't saving the function inside the object.... so I tried to put the function in quotes, inside the object and it saves the string, but I can't figure out how to call the function from that after I save it.
I've tried
master.myArray[0][master.myArray[0]]() // didn't work
I've tried
var fun:String = master.myArray[0]fun;
master.myArray[0][fun]() // didn't work
I've tried
var fun:Function = master.myArray[0].fun;
fun(); // didn't work
I thank you very much for any insight here... I've been calling functions from within objects for a while now, but now that I want to save and load, I am seeing this isn't going to work like that.

I think I found it.
var functionName:String = master.myArray[0].fun; // where master was saved in save.data.master
var newFun:Function = this[functionName];
newFun();
Seems to work.

Related

save load error 1010 array objects with sharedObjects as3

i cant figure out this one so maby you guys can help me out.
i store some data in the form of a array filled with Objects in this example cards.
in my main class i have the following code:
deckSprite.savedData = SharedObject.getLocal("cardsdata");
deckSprite.savedData.data.savedArray = deckSprite.deckArr;
deckSprite.savedData.flush();
trace(deckSprite.savedData.data.savedArray);
the trace will output something like [object card1, object card2, object card3]
now in a static class called "deckSprite" i have this:
savedData = sharedObject.getLocal("cardsdata");
if (savedData.data.savedArray == undefined)
{
trace("no save yet");
}
{
else
{
trace("save loaded");
deckArr = savedData.data.savedArray;
trace(savedData.data.savedArray);
now my trace data turns out only ", ," (somehow the cards are gone).
now after i got saved data i restart my application and whenever he tryes to acces the deckArr it crashes giving me the error "A term is undefined and has no properties".
how is it possible that when i save the array it saves all the cards inside the array and when i restart the application its suddenly only ",,"but the cards are gone?
When serializing objects in AS3, you have to register their class using registerClassAlias() from package flash.net. So you have to call something like
registerClassAlias('com.example.deck', Deck)
in the program before any saving or loading happens.
See full reference at AS3 API Reference
NOTE: As pointed out by #BadFeelingAboutThis in comments, you have to register all referenced class in your Deck, i.e. if your deck looks like this:
class Deck {
var firstCard:Card;
var type:DeckType;
}
to be able to save Deck to SharedObject you have to call
registerClassAlias('com.example.deck', Deck);
registerClassAlias('com.example.card', Card);
registerClassAlias('com.example.decktype', DeckType);
before any saving/loading is done.
EDIT
Everything depends on content of your array
If I assume, your deckSprite is declared like this:
var deck1:Deck = new Deck();
var deck2:Deck = new Deck();
var deckArr:Array = new Array(deck1, deck2);
var deckSprite:DeckSprite = new DeckSprite()
deckSprite.setDeckArr(deckArr);
then before adding deckArray to SharedObject, you have to call registerClassAlias(). Sou your save code will look like this:
registerClassAlias('com.example.deck', Deck);
deckSprite.savedData = SharedObject.getLocal("cardsdata");
deckSprite.savedData.data.savedArray = deckSprite.deckArr;
deckSprite.savedData.flush();
trace(deckSprite.savedData.data.savedArray);
(replace the Deck with actual class you use for representing your decks)
Similarly the first line has to be called before you do any loading.
Of course it is best not to repeat yourself, so you should call registerClassAlias('com.example.deck', Deck); only once in your program, so for example in some init() method in your main class, if you have something like that.

Trying to understand a function

Im trying to understan a function that I found on the web.
Iknow what the function does, It get the information about the webcam in your computer and post it on the textArea,
But the individual line are just a bit confused.
Any help ?
Thanks
private var camera:Camera;
private function list_change(evt:ListEvent):void {
var tList:List = evt.currentTarget as List;
var cameraName:String = tList.selectedIndex.toString();
camera = Camera.getCamera(cameraName);
textArea.text = ObjectUtil.toString(camera);
}
private var camera:Camera;
This line creates a variable of the class type Camera. It does not create an instance of the variable.
private function list_change(evt:ListEvent):void {
This line is a standard function heading. Because the argument is a ListEvent, it makes me think that this function is probably written as an event handler. Because of the name of the function, it is most like listening to the change event on a list.
var tList:List = evt.currentTarget as List;
This line creates a reference to the list that dispatched the event, which caused this handler to be executed.
var cameraName:String = tList.selectedIndex.toString();
This line converts the selectedIndex to a string. It's a bit odd to convert an index to a string, as opposed to some value. But the reason they do that looks to be on the next line..
camera = Camera.getCamera(cameraName);
This uses that camera variable (defined back in line 1) and actually gets an instance of the camera. It uses the "cameraName" which makes me think that the list that dispatched this change event contains a list of cameras available on the system.
textArea.text = ObjectUtil.toString(camera);
This converts the camera object to a string and displays it in a text area. Normally you wouldn't try to do this as it provides no valuable data. A default object will display strings as [Object object] or something similar. Perhaps the camera object has a custom string function; I don't have experience with that. Normally, you'd want to access properties of the object to get useful information, not try this on the object itself.
}
This line is the end of the function. The open bracket was in the 2nd line of code in the function definition.

AS3 Putting function blah(){ around code generates errors on lines of code I dont have

I've got a block of code that's doing what I want - it generates a grid of MC's.
As soon as I put something like function blah() around it, it starts generating errors indicating lines of code I don't have e.g.
TypeError: Error #1010: A term is undefined and has no properties.
at flightCellMaker_fla::MainTimeline/myXMLtrace() [flightCellMaker_fla.MainTimeline::frame1:87]
at flightCellMaker_fla::MainTimeline/processFPBxml() [flightCellMaker_fla.MainTimeline::frame1:52]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
When I take the function out, it does what I want it to do. What's up with that?
var testXML:XML;
var myFPBxml:XML;
// Initialise a URLLoader to get XML data from XML file
var myFPBLoader:URLLoader = new URLLoader();
myFPBLoader.load(new URLRequest("flightPlannerBoard.xml"));
// Check XML data fully loaded
myFPBLoader.addEventListener(Event.COMPLETE, processFPBxml);
// Once the flight board planning data is loaded, save it to a variable
function processFPBxml(e:Event):void {
myFPBxml = XML(e.target.data);
myXMLtrace();
}
// Grab the XML data load completed and make it available elsewhere
function myXMLtrace(){
testXML = XML(myFPBxml);
}
trace("***********************" + testXML.*); This throws an error (not within myXMLtrace tho)
OK, so here's the rest of the code that will run correctly on it's own but not in a function:
// Create and place all the flight cells for planning and drag and drop
// Setup 2 loops: j for columns and i for Rows
for (var j:Number =0; j < rowNum; j++){
for (var i:Number =0; i<9; i++){
// Create copies of flightCell for board grid
var my_mc = new flightCell();
my_mc.name = "mc"+i+j;
addChild(my_mc);
// Set event Listeners on all Child objects
my_mc.myDragShape.addEventListener(MouseEvent.MOUSE_OVER, fl_MouseOverHandler);
my_mc.myDragShape.addEventListener(MouseEvent.MOUSE_OUT, fl_MouseOutHandler);
my_mc.myDragShape.addEventListener(MouseEvent.MOUSE_DOWN, fl_MouseDownHandler);
my_mc.myDragShape.addEventListener(MouseEvent.MOUSE_UP, fl_MouseUpHandler);
Object(this).my_mc.yellowHiLite.visible = false;
//cellPos[j] = myXML.cellPosX[j];
//trace(stage.myXML.*);
//trace(my_mc.name);
my_mc.x = (100 + colWidth);
my_mc.y = myRowHeight;
colWidth = colWidth + 155;
//trace(myXML.*);
cellArray[arrayCount] = [my_mc.x, my_mc.y];
trace("CellArrayCount = " + cellArray[arrayCount]);
arrayCount = arrayCount + 1;
}
myRowHeight = myRowHeight + 105;
colWidth = 50;
}
Your trace is throwing an error because it is being executed before the XML is loaded.
ActionScript is asyncronous, which means that while the XML is being loaded, the program execution carries on going, and looks something like this:
Declare testXML:XML and myFPBxml:XML
Create loader and start loading
Add a listener for load completion
Trace testXML
Execute processFPBxml when the XML is loaded
If you move your trace into the myXMLTrace function then it will work correctly.
With the newly added code, the problem is with this line:
Object(this).my_mc.yellowHiLite.visible = false;
There is no need to use the this keyword at all here. This will work inside or outside a function:
my_mc.yellowHiLite.visible = false;
The reason your code fails inside a function is because inside and outside the function this will be the scope of the object in which this code resides. However, when you put the code into a function, the reference you create - my_mc - is scoped locally to the function, not to the parent object, and so this.my_mc is undefined, because this is not the function scope.
Are you taking the code out of the function it's currently in and calling the new function from where the code used to be? Or are you trying to define a function variable?
If you're only putting function blah() { ... } around code in the same place it is currently running, you'll get a syntax error for sure. In that case, try:
var blah:Function= function() { ... };
blah();
If you declare variables within a function they fall inside the scope of the function only.
It sounds like you are trying to access variables from elsewhere in your code.
So what you need to do is declare your variables outside of the function. e.g.
var one:VarType;
var two:VarType;
function blah():void {
trace(one);
}

ActionScript: How to Import XML data as a variable (not as an Event)

I am attempting to import some simple XML data into Flash ActionScript 3.0. I can easily do this as an import that is posted to the stage, but I want to save it as a global variable instead. Here is the XML file that I am pulling from:
<utilitySavings>
<nameof file="academicWaterSavings">
<waterValue>100</waterValue>
<elecValue>200</elecValue>
</nameof>
<nameof file="dormWaterSavings">
<waterValue>300</waterValue>
<elecValue>400</elecValue>
</nameof>
<nameof file="greekWaterSavings">
<waterValue>500</waterValue>
<elecValue>600</elecValue>
</nameof>
<nameof file="totalWaterSavings">
<waterValue>1500</waterValue>
<elecValue>1600</elecValue>
</nameof>
...and here is the actionscript:
var req:URLRequest = new URLRequest("data.xml");
var loader:URLLoader = new URLLoader();
var utilitySavings:XML;
function xmlLoaded(event:Event):void
{
utilitySavings = new XML(loader.data);
academicWater.text = utilitySavings.nameof[0].waterValue;
academicElec.text = utilitySavings.nameof[0].elecValue;
var dormWater:String = utilitySavings.nameof[1].waterValue;
trace (dormWater);
}
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(req);
trace(academicWater.text);
Notice the 'trace (dormWater)' I want to trace this outside of the function so it is accessible in later in my script. I can trace within the function, but this does me no good. I also am able to get the dynamic text to show up on the stage but, likewise, this does me little good.
I appreciate any help or insights.
I can see a couple of ways of achieving this , if you want to create a globally accessible Object, create a Singleton( not recommended ) , load your XML data into it then every object in your app will be able to access the loaded XML data.
http://www.gskinner.com/blog/archives/2006/07/as3_singletons.html
The resulting code would give you something like this:
//Available throughout your app after the XML has been loaded & parsed
var dormWater:String = Singleton.dormWater;
Although you state you don't want Events, I think that using Signals could be a better approach. Load your XML and dispatch a Signal containing the relevant String to the object that needs it, when receiving the Signal , assign the String to a variable.
http://www.peterelst.com/blog/2010/01/22/as3-signals-the-best-thing-since-sliced-bread/
//In a specific class
private var _dormWater:String;
private function signalListener(value:Object ):void
{
_dormWater = value.dormWater;
}

Actionscript - Variable Assignment without reference?

Should be easy. I have an object. I want to modify it, but before i do I want to save a copy of it that I can go back to. I tried setting copy = original but when i modify the attributes of the original the copy also shows the changes. I am assuming this is because in actionscript any time you assign, it really just stores a reference to the original object. So whats the best way for me to store a copy of the original object for later use?
var newObj:Object = Object(ObjectUtil.copy(oldObj));
"Copies the specified Object and returns a reference to the copy. The copy is made using a native serialization technique. This means that custom serialization will be respected during the copy.
This method is designed for copying data objects, such as elements of a collection. It is not intended for copying a UIComponent object, such as a TextInput control. If you want to create copies of specific UIComponent objects, you can create a subclass of the component and implement a clone() method, or other method to perform the copy."
http://livedocs.adobe.com/flex/3/langref/mx/utils/ObjectUtil.html#copy()
What you are looking for is a deep copy of the object rather then passing by reference. I found the answer here which uses the new ByteArray class in AS3:
http://www.kirupa.com/forum/showthread.php?p=1897368
function clone(source:Object):* {
var copier:ByteArray = new ByteArray();
copier.writeObject(source);
copier.position = 0;
return(copier.readObject());
}
Which you then use like this:
newObjectCopy = clone(originalObject);
Cheers!
// duplicate any given Object (not MCs)
Object.prototype.copy = function()
{
ASSetPropFlags(Object.prototype,["copy"],1);
var _t = new this.__proto__.constructor(this) //
for(var i in this){
_t[i] = this[i].copy()
}
return _t
};
Usage
x = ["1","2","3",[4,5],[{a:1,b:2}]]
y = x.copy()
y[0] = 0
y[3][0]="d"
trace(x)
trace(y)