AS2 магия
Сегодня ко мне в аську обратился с проблемой подгрузки swf-роликов, скомпиленных через mtasc. Дело в том, что mtasc вызывает статический метод main() основого класса приложения, не передавая никаких параметров, содержащих ссылку на таймлайн клипа, в котором, собственно, и содержатся сами классы. Т.е. единственный вариант аттача клипа — в _root. Тут же возникает проблема подгрузки таких роликов: _root ссылается на таймлайн родительского клипа, а не загруженного. В итоге работоспособность флешки нарушается.
А как же _lockroot, скажете вы? Да, его можно использовать, но только непосредственно в клипе-загрузчике, что не подходит под условия задачи. Необходимо включить _lockroot изнутри загруженного клипа. Как это сделать? Читайте далее.
Решение оказалось неочевидным, нетривиальным и совершенно не поддающиеся никакой логике:
This content requires Adobe Flash Player.
Типичный входной класс для mtasc. Будучи загруженным, такой ролик верно определяет свой _root.
Как работает?
Точного ответа я дать не могу. Начнем с того, что eval(eval('_target')); не заработает, будет ошибка there is no property with the name '_target'.
eval(targetString) возвращает строку (!) "/". Но при этом, если мы захотим использовать что-то вроде:
var root:String = '/';
var target:MovieClip = eval(root);
То это не будет работать, вернется ссылка на _root родительского клипа, он же _level0. Именно здесь проявляется магия eval(targetString), который возвращает магический String, eval которого дает нам ссылку на таймлайн загруженного клипа, а не _root родительского.
Далее просто включаем _lockroot, либо используем полученный target в своих целях.
Каким образом было получено данное решение?
Методом тыка. В основе сего действа лежит знание того, что инициализация классов происходит в клипах. В результате экспериментов получился сей работающий код. Да, это грязный хак, но работать оно не перестанет.
Буду рад, если кто-нибудь расскажет с научной точки зрения, почему это работает.
11 comments
11 Comments so far
Leave a reply
ээээ
эм.. я не совсем понял смысл этих приседаний
/**
* @param container reference to _root
*/
public static function main ( container: MovieClip ): Void {
}
magius, откуда у тебя эти данные? =)
Упоминания об этой тонкости нет в русскоязычном MTASC FAQ, но оно просто обязано быть там! magius, спасибо за наводку.
Спасибо. Вчера весь вечер потратил на поиск решения с вызовом main с переданной ссылкой на клип. Официальная дока партизански промолчала про эту возможность.
Тем не менее, магия имеет место быть
Я, честно говоря, mtasc не пользовал и документацию к нему не читал
мда… век живи век учись
Шаманы…
>>Буду рад, если кто-нибудь расскажет с научной точки >>зрения, почему это работает.
Вы ведь сами сказали, в чем она
“статический метод main() основого класса приложения, не передавая никаких параметров”
Почему не написать разработчику, и показать свой код… интересно, что он скажет…
http://tech.motion-twin.com/contact.html
Да нет, разработчик mtasc тут непричем. Я сам mtasc-ом не пользовался и документацию к нему не читал. Просто поверил на слово, но оказалось, что он все таки передает в параметрах ссылку на нужный таймлайн, просто это явно не было указано в FAQ или хелпе.
А вот мой хак работает независимо от компилятора. Вопрос касался именно данного момента, почему эта конструкция вообще заработала и работает.
В этой конструкции много неясностей, она работает ровно в таком виде, в котором написана и никак иначе.
[...] -main — производит автоматический вызов метода main, для всех зарегистрированных классов. Внимание: метод main должен принимать один параметр container:MovieClip, в качестве которого MTASC передаст ссылку на основную временную диаграмму _root ролика. Чтобы понять почему это важно, прочитайте эту статью; [...]
[голосом доктора зойдберга] ура! я пригодился!