Wednesday, October 26, 2011

Improving MovieClipProxy.as?

This is the fifth post in a series.  I made a couple of  "improvements" to MovieClipProxy.as and found out a thing or two before abandoning the idea due to our sloppy coding practices that would require more fixing than I was prepared to do.

I was also happy to receive a reply from Senocular indicating that there was not a simpler way just to override the _visible setter.  He wrote:
AS3 supports native implementation overrides for getter/setters, but not AS1/AS2
In the last post, I left off wondering whether I was willing to write a getter/setter for all the properties, methods and functions of my ubPod class.

I wrote two functions for MovieClipProxy.as to add additional properties and functions to a MovieClipProxy instance, namely addProp and addFunction:

public function addProp(propName:String){
 var getterFunction:Function = function(){
  return this._mc[arguments.callee.name];
 }
 getterFunction.name = propName;
 var setterFunction:Function = function(newVal):Void{
  this._mc[arguments.callee.name] = newVal;
 }
 setterFunction.name = propName;

 this.addProperty(propName, getterFunction, setterFunction);
}
public function addFunction(propName:String){
 this[propName] = function(a, b, c, d, e, f, g, h, i, j){
  return this._mc[arguments.callee.name].call(arguments.callee.mcp_instance, a, b, c, d, e, f, g, h, i, j);
 }
 this[propName].name = propName;
 this[propName].mcp_instance = this._mc;

 //no luck getting getters and setters to work for functions
    /*
 var getterFunction:Function = function(){
  trace("in mcp getter function with name "+arguments.callee["name"]+" from "+arguments.callee);
  trace("addFunction getter");
  return this._mc[arguments.callee.name];
 }
 getterFunction.name = propName;
 var setterFunction:Function = function(f:Function){
  trace("in mcp setter function with name "+arguments.callee["name"]+" from "+arguments.callee);
  trace("addFunction setter");
  //this._mc[arguments.callee.name] = newVal;
  this._mc[arguments.callee.name] = function(a, b, c, d, e, f, g, h, i, j){return f.call(arguments.callee.mcp_instance, a, b, c, d, e, f, g, h, i, j)};
 }
 setterFunction.name = propName;
 setterFunction.mcp_instance = this._mc;

 this.addProperty(propName, getterFunction, setterFunction);
 */
}

which are invoked pretty simply with code like:

mcp.addProp("side");
mcp.addFunction("scale");

Next, I wondered if there was a way to get my ubPod class to reveal more of its properties and methods in a for..in loop. The new learning here relates to ASSetPropFlags (of which the compiler is unaware) which allowed me to write a function like:

_global["ASSetPropFlags"](ubPod.prototype,null,6,true);

for (var i in ubPod.prototype){    
    var thing = ubPod.prototype[i];
    var typeThing:String = typeof(thing)
    if (typeThing == "function" && i != "__constructor__"){
        mcp.addFunction(i);
    } else if (typeThing == 'number' || typeThing == 'string' || typeThing == 'boolean' || (typeThing == 'object' && i != "__proto__")){
        mcp.addProp(i);
    } else {
        trace("did nothing for "+i);
    }
}

Maybe some of this will help folks still in AS2 land.  I am left still pretty foggy about __proto__, prototype, extends and casting.

Here are two challenges:
  1. Find the error in the code shared in the previous post.
  2. Modify my addFunction method to allow for a getter and setter as well as a function definition to be established.

No comments: