Пишем дебаггер для работы с mtasc и вывода логов из trace().
Для компиляции ActionScript 2.0 очень удобно использовать mtasc (http://mtasc.org/). Он точный и работает очень быстро, к тому же open source и выпущен под операционные системы Linux, MacOS и Windows. Его можно прописать в любом редакторе кода, поддерживающем функции compile и build. Ошибки при компиляции выводит в стандартный поток, они отображаются в консоли. А вот насчет функции trace() в ActionScript у него есть собственное решение. Он позволяет программисту назначить любую статическу функцию для перенаправления функции trace(). Другими словами - все логи, что мы выводим в trace() - автоматически попадают в назначенную функцию. А в ней делаем с логами что хотим.
Вот что именно можно с ними делать, сейчас и разберемся.
Для начала почитаем матчасть (http://mtasc.org/#trace) чтобы вспомнить или ознакомиться с подробностями применения этой возможности. Итак, в одном из своих классов (я обычно использую главный класс) добавляем функцию, которая будет принимать логи. Сразу в функции main для теста выведем какой нибудь лог:
class Test {
static function main(mc) {
trace("hello world");
}
static function traceLog(log:String) {
// TODO
}
}
В строке компиляции добавим такую опцию:
... -trace Test.traceLog
При желании, функцию traceLog можно сделать более информативной, добавив несколько аргументов в функцию. Дело в том что mtasc, вызывая эту функцию, на самом деле передает не один а целых четыре аргумента:
1. текст лога
2. полное название класса с названием метода, из которого был вызван trace()
3. название файла
4. номер строки
для этого пишем функцию traceLog() вот так:
static function traceLog(log:String, func:String, file:String, line: Number) {
// TODO
}
Эти аргументы можно использовать как нам удобно.
Теперь когда базовый механизм сделан, нужно в функции traceLog обеспечить отображение этих логов. Ведь нам надо их как-то увидеть. Для этого часто используют простой способ - вывод в текстовое поле. Действительно, что нам стоит сотворить на руте текстовое поле и кидать туда лог простой строчкой вроде:
_root.logger.text += log + "\n";
или вот так:
_root.logger.text += func + ": " + log + "\n";
Но мы пойдем другим путем, более практичным и универсальным. Ведь текстовое поле будет мешать просмотру основного ролика и после публикации на сайте использовать его будет некрасиво. Мы сделаем связь между роликами через LocalConnection. Идея в том, что создав один раз «приемный» ролик (далее - «приемник»), который принимает логи и отображает в своем текстовом поле, потом можем его использовать для различных проектов, как в отдельно запущенных флеш-плеерах, так и в браузерах. Просто для каждого нового проекта нужно будет добавить в класс одну и ту же функцию, а в строку компиляции добавить одну и ту же опцию.
Идея эта на самом деле не нова, и ее используют многие программисты, и даже есть готовые решения на AIR. Но, думаю, интересно будет сделать самому, так как это очень простая штука, зато очень гибкая. Мы можем сделать приемник любого, удобного нам размера. Можем сделать его «резиновым» и вставлять в HTML-фрейм. Запускать отдельно в standalone flash-плеере. Использовать в трех популярных операционных системах (Lin, Mac, Win). Можно сделать его самозапускающимся роликом (прожектор) и запускать там где нету standalone flash-плеера. В общем простой, но вместе с тем удобный дебаггер для вывода trace().
Все что нам нужно сделать - создать приемник и дописать функцию traceLog() там где мы оставили TODO.
Начнем с первого.
Сделаем для примера простой приемник, который имеет только текстовое поле по всей площади.
Сразу пишу целиком весь код, так как предисловие здесь абсолютно излишне:
class tracer {
static var app : tracer;
private var m_LC:LocalConnection;
public function tracer() {
_root.createTextField("logger",10,10,0,480,780);
m_LC = new LocalConnection();
m_LC.writeLog = function(str:String) {
_root.logger.text += str + "\n";
};
m_LC.connect("TraceLogger");
}
// entry point
static function main() {
app = new tracer();
}
} // end class
строка компиляции:
mtasc -swf tracer.swf -main tracer.as -header 500:800:25:DFDFDF
Мы создали главный и единственный класс для приемника, он содержит входную функцию main() в котором вызывается конструктор tracer(). В конструкторе создаем текстовое поле, размер и положение подгоняем под заданный в опции компилятора -header размер ролика. Также в конструкторе создаем экземпляр LocalConnection и назначаем ему приемную функцию writeLog. Потом методом connect создаем локальное соединение и придумываем ему какой-нибудь уникальный идентификатор. Этот идентификатор запоминаем и никому не говорим ))
Компилируем и получаем файл tracer.swf. Приемник готов. Теперь нужно доделать статическую функцию traceLog для наших проектов. Пишем примерно так:
static function traceLog(str:String) {
var trace_lc:LocalConnection = new LocalConnection();
trace_lc.send("TraceLogger", "writeLog", str);
}
в функции send - первый параметр - идентификатор локального соединения, второй - название приемной функции, третий - выводимый лог. При желании в третем параметре можем добавить к переменной str другие данные, описанные выше. Собственно все. Осталось тестировать и применять на здоровье.
Как используем. Очень просто. Создавая новый проект, добавляем готовую функцию traceLog(), ничего не меняя в ней. А в строку компиляции соответственно добавляем
-trace <название_класса>.traceLog
Во время работы с проектом у нас должен быть запущен где-то на этом же компьютере наш приемник-дебаггер. Его можно разместить справа или внизу от окна редактора. Или в браузере, как удобно.
При желании и фантазии приемник можно снабдить кнопкой очистки логов (полезная штука). Также его можно снабдить приятным дизайном и подключить моноширинный шрифт. Наворотить можно много чего, главное чтобы оно приносило пользу и экономило время.
