Adobe Director: Type overloading using ancestorsFeb-1-07, 12:12 am by HanfordFile under: Misc., Macromedia, Director, Adobe, Shockwave, Lingo Warning! This is a heavily geeky Adobe Director post! This is something I've messed around with in Director for a while now, and I recently brought it up on Direct-L. A lot of people there hadn't heard about it so I thought I'd blog about it here. An object's ancestor property allows you to attach a secondary object that will get events that the original object doesn't get. For example you can attach a "car" child object as an ancestor to a "Probe" child object. Once you've done that, any events sent to "Probe" that the probe script doesn't process will be passed on to "car". If you're confused, look it up in the help docs, because it's only going to get , um, confusinger. I discovered a while back that you can assign other types to a child object's ancestor property and have the resulting object act like the ancestor's ilk. And by "ilk" I mean lists, property lists, rect(), point(), image objects ... you name it and it probably works. Here's an example. Let's say I wanted a list that returned void whenever an out of bounds index was referenced. From a usage standpoint I'd want it to look like this: ilist = [1, 2, 3]
So that's how we want it to work. But currently if you try this with Director, you'll get errors if you try to access invalid pointers. However, using this trick we can build an overloaded list that will work the way we want to. Here's some code that goes in a parent script:
-- Parent Script: "BetterList" property ancestor on new me ancestor = [] return me end on getat me, iposition if iposition <1 or iposition > ancestor.count then return void return ancestor[iposition] end Notice how all this really does is assign an empty list to the ancestor, and a getat function that checks to see if the requested index is out of bounds. Now, if we do this: ilist = new(script "betterlist") ilist[1] = "hello" ilist[2] = "there" put ilist[1] -- "hello" put ilist[3] -- Void The ilist variable operates as a normal list: we can address it with brackets, and we can add items to the list like normal. However, when calling an out of bounds index, the list returns void. This is because the GetAt function (which bracket syntax is shorthand for) is being processed not by the list, but by my script. However, all other functions are unused by the child object and are therefore passed to the ancestor. On Direct-L Valentin Schmidt took my script and modified it to create a way to make a list that starts at 0 instead of one. This could be very useful when porting code from other languages where arrays start with zero: --- parent script "zero_list"
property ancestor
on new me
l = []
repeat with i = 2 to the paramcount
l.append(param(i))
end repeat
ancestor = l
return me
end
on getAt me, pos
if pos < 0 or iposition >= ancestor.count then return void
return ancestor[pos+1]
end
on setAt me, pos, val
ancestor[pos+1] = val
end
--- test
l = script("zero_list").new(1,2,3)
put l[0]
-- 1
l[0] = 23
put l[0]
-- 23
How useful is this hidden functionality? Only time will tell. It has worked with every data type I've tried. Drop me a comment if you've used this before or have any insight as to what can be done with it. Feedback - 5 responsesDisplayed newest to oldest. Leave a comment.Phylobates wrote: Jun-21-07, 8:30 am I'm been using director for years and you think you got it pretty much sussed when a little gem of knowledge like that pops up.. interesting. Tried with "rect" and it works beautifully. I'm sure I'll find some use for it... -- New rect object in script customRect on new me me.ancestor = rect(0,0,0,0) return me end on diagonalLength me return sqrt((me.width*me.width) + (me.height * me.height)) end -- and lo and behold.. myrect = new script("customRect") myrect.top = 50 myrect.right = 50 put myrect.diagonalLength() -- 71 ahoeben wrote: Feb-1-07, 4:25 am The 'on put me' approach does not seem to work. Your reply got me thinking though, and the solution is as simple as: myList = new(script(“BetterList”),[11,22,33]) put myList.ancestor -- [11,22,33] put myList.ancestor * 4 -- [44,88,132] put myList.ancestor + [1,2,3] -- [12,24,36] Hanford wrote: Feb-1-07, 2:51 am Interesting about losing those aspects of list functionality. You can, of course write your own "put", like this: on put me trace(ancestor) end I like the change you made to the "new" handler. Valentin does something similar, but in my original example I wanted it to be as simple as possible. ahoeben wrote: Feb-1-07, 2:09 am If you change the 'new' handler slightly, you can set initial list values upon script initialisation: on new me, aList if not listP(aList) then aList = [] ancestor = aList return me end usage: myList = new(script("BetterList"),[11,22,33]) put myList[2] -- 22 While this technique is very usefull to add 'methods' to the list datatype (such as an 'addOnce' method to only add an item to a list if it is not already in the list, or an 'append' to append another list to this list, etc), you also loose a lot of list functionality: - you can no longer 'put' the list - you can no longer do arithmetics on the full list (eg multiply all list items by 2) I think that's the reason why acestors aren't used more to extend datatypes... Leave a commentComments are displayed on posts and visible to all site visitors. |
|
I design things in Silicon Valley; mostly consumer electronics media players. Perhaps I can design things for you. Check out my UI Portfolio. When I'm not making things for other people, I'm usually making video games. more
Please use our contact form.
|
|
Test.