Showing posts with label proxy. Show all posts
Showing posts with label proxy. Show all posts

Monday, October 24, 2011

Actionscript 2: Catching when an instance of a Class that extends MovieClip is made visible

You just don't get blog post titles as precise as that every day!

I have been telling a story today about trying to catch when a movieclip's _visible property is set.  First, I showed how we create classes that extend MovieClip.  Next, I described the problems that I am having writing a set and get function for _visibleThird, I showed how MovieClipProxy could be used on a simple MovieClip to catch the setting of _visible.  Now, I am going to finish the story and show how it can be done for a class like ubSquare.

The first step is to make a slight adjustment to MovieClipProxy.   Its constructor is written to either take 3 parameters and create an empty MovieClip or 4 parameters and attach a movieclip from the library.  I changed it so that if it is sent more, it will use the first parameter to create the movieclip.

In the first post's example, we created the ubSquare using:

this.mySquare_ubS = ubSquare.create(this, "mySquare_mc", {_x:50, _y:75, _side:10});

So if we change the constructor of MovieClipProxy to read:

 function MovieClipProxy(a,b,c,d,e) {
  var mc, mc2;
  if (arguments.length == 3) {
   mc = __initEmpty(a,b,c);
  } else if (arguments.length == 4){
   mc = __initAttached(a,b,c,d);
  } else {
   mc = a(b,c,d,e);
  }
  __applyPrototyped(mc);
 }

Then we can invoke it with:
 var mcp:MovieClipProxy = new MovieClipProxy(ubSquare.create, container, instanceName, initObj, depth);

and the created MovieClip will now be a ubSquare.

But, ubSquare had a side property and a scale method that are not handled by MovieClipProxy.  I can create a ubSquareProxy Class

import edu.clips.test.MovieClipProxy;
import edu.clips.test.ubSquare;

class edu.clips.test.ubSquareProxy extends MovieClipProxy {
 
 public static function create(container:MovieClip, instanceName:String,
         initObj:Object, depth:Number) {
  if (depth == undefined) depth = container.getNextHighestDepth();
  var mcp:MovieClipProxy = new MovieClipProxy(ubSquare.create, container, instanceName, initObj, depth);

  //define all the ubSquare properties, methods and functions
  mcp["scale"] = function(newScale:Number){
   trace("in ubSquareProxy.scale "+ mcp._mc);
   mcp._mc.scale(newScale);
  }
  mcp.addProperty("side", 
      function(){trace("addProperty getter");return this._mc.side}, 
      function(newSide){trace("addProperty setter");this._mc.side = newSide});
  return mcp;
 }
}

and create it using:

this.mySquare_ubS = ubSquareProxy.create(this, "mySquare_mc", {_x:50, _y:75, _side:10});

Now the questions that I am left with are these:
  1. Is it worth the time to apply this method to my ubPod class with 80 documented properties, 23 methods and 7 event handlers just to capture when the one MovieClip property, _visible, changes?
  2. Is there a way to use __proto__ or prototype or constructor to access the MovieClip's setter for _visible and just change that to broadcast an event?
  3. Should ubSquareProxy extend MovieClipProxy, MovieClip or nothing?

Actionscript 2: One Way to catch when a MovieClip becomes visible

In my previous post, I outlined the difficulties that I have been having reacting to when a MovieClip becomes visible.  I think the big reason for these difficulties is that _visible is a MovieClip property that is impossible to override with getters and setters.

However, I happened to be trolling around Senocular's site and found his MovieClipProxy class.  This class creates an object with all of the standard MovieClip properties with getter and setter functions and all the standard MovieClip methods together with the standard functions, like onEnterFrame, envoked using the call statement and the correct scope.

If I change the setter and getter for _visible as follows:

 function get _visible():Boolean {
  trace("get _visible");
  return _mc._visible; 
 }
 function set _visible(v:Boolean):Void {
  trace("set _visible");
  this._xscale *=2;
  _mc._visible = v; 
 }

Note that I am just setting the _xscale when _visible is set just for a double visual confirmation.

If you create a new Actionscript 2 .fla tester file with the code:

import edu.clips.test.MovieClipProxy;

var mcp:MovieClipProxy = 
 new MovieClipProxy(this, "test", 1);

trace("_xscale before first set _visible "+mcp._xscale);
mcp._visible = false;

mcp.clear();
mcp.lineStyle(2, 0x0000FF, 100, true);
mcp.moveTo(0, 0);
mcp.lineTo(200, 100);

trace("_xscale before second set _visible "+mcp._xscale);
mcp._visible = false;
trace("_xscale after second _visible "+mcp._xscale);

this.test._visible = true;
trace("_xscale after movieClip set _visible "+mcp._xscale);
trace("or "+this.test._xscale);

and test it, you get the output:

_xscale before first set _visible 100
set _visible
get _visible
_xscale before second set _visible 200
set _visible
get _visible
_xscale after second _visible 400
_xscale after movieClip set _visible 400
or 400

When you reference the MovieClipProxy object mcp, the setters and getters are used and applied to the  MovieClip this.test.  When you reference this.test._visible directly, the setter is not used.

Now you are in the position to capturing the setting of _visible and do something more sensible than upscaling, as long as you create a MovieClipProxy and reference it.

This still leaves the question of whether this approach can be bolted on to the method we are using to create Classes that extend MovieClip.