Записки о Flash

AS2 магия

Сегодня ко мне в аську обратился Алексей «Vooparker» Аникутин с проблемой подгрузки 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

  1. magius September 25th, 2007 06:18

    ээээ
    эм.. я не совсем понял смысл этих приседаний

    /**
    * @param container reference to _root
    */
    public static function main ( container: MovieClip ): Void {

    }

  2. Юрий Яровой September 25th, 2007 10:57

    magius, откуда у тебя эти данные? =)

  3. Юрий Яровой September 25th, 2007 11:08

    Упоминания об этой тонкости нет в русскоязычном MTASC FAQ, но оно просто обязано быть там! magius, спасибо за наводку.

  4. vooparker September 25th, 2007 11:13

    Спасибо. Вчера весь вечер потратил на поиск решения с вызовом main с переданной ссылкой на клип. Официальная дока партизански промолчала про эту возможность.

  5. __etc September 25th, 2007 11:18

    Тем не менее, магия имеет место быть :)
    Я, честно говоря, mtasc не пользовал и документацию к нему не читал :D

  6. SHAGGYSMILE September 25th, 2007 13:03

    мда… век живи век учись :)

  7. ALFer September 25th, 2007 15:29

    Шаманы…

  8. Akel September 26th, 2007 01:06

    >>Буду рад, если кто-нибудь расскажет с научной точки >>зрения, почему это работает.
    Вы ведь сами сказали, в чем она :)

    “статический метод main() основого класса приложения, не передавая никаких параметров”
    Почему не написать разработчику, и показать свой код… интересно, что он скажет…
    http://tech.motion-twin.com/contact.html

  9. __etc September 26th, 2007 01:43

    Да нет, разработчик mtasc тут непричем. Я сам mtasc-ом не пользовался и документацию к нему не читал. Просто поверил на слово, но оказалось, что он все таки передает в параметрах ссылку на нужный таймлайн, просто это явно не было указано в FAQ или хелпе.

    А вот мой хак работает независимо от компилятора. Вопрос касался именно данного момента, почему эта конструкция вообще заработала и работает.
    В этой конструкции много неясностей, она работает ровно в таком виде, в котором написана и никак иначе.

  10. Garbage Collector » Архив » MTASC FAQ September 26th, 2007 04:04

    [...] -main — производит автоматический вызов метода main, для всех зарегистрированных классов. Внимание: метод main должен принимать один параметр container:MovieClip, в качестве которого MTASC передаст ссылку на основную временную диаграмму _root ролика. Чтобы понять почему это важно, прочитайте эту статью; [...]

  11. magius September 27th, 2007 18:55

    [голосом доктора зойдберга] ура! я пригодился! :)

Leave a reply