You are not logged in.
Да, я думал об этом, просто не хотелось использовать еще один большой массив (если учесть, что меток в оригинале несколько десятков тысяч) только ради одного сообщения. Я посмотрю, что можно сделать.
Offline
2Seemann:
1. Увеличение/Уменьшение шрифта по Ctrl+Num+ / Ctrl+Num-
2. Переход на строку по Gtr+G
3. Пост #21, #22
4. Поддержка плагинов
Last edited by Sanchez (27-08-2007 18:42)
Offline
2. Переход на строку по Gtr+G
Это уже есть.
4. Поддержка плагинов
Над этим работаю. Заодно спрошу, какая система плагинов была бы лучшей? С какой существующией программы можно было бы скопировать / подсмотреть? Сам я склоняюсь к идее написания плагинов на языке Lua (как в программе SciTe). С одной стороны, это более быстро, чем программирование библиотек на C++/Delphi, с другой - любой может написать новый плагин в обычном блокноте, не обязательно иметь упомянутые средства программирования. Да и в принципе никто не мешает реализовать вызов библиотечных функций в Lua.
Приму любые идеи/замечания на этот счет.
1. Увеличение/Уменьшение шрифта по Ctrl+Num+ / Ctrl+Num-
Это можно будет реализовать плагинами.
3. Пост #21, #22
Угу, помню. Возможно в следующих обновлениях попробую-таки встроить тот компилятор, который я делал для трешки, как дополнительный, для обкатки.
Offline
С какой существующией программы можно было бы скопировать?
Больше всего мне нравиться OllyDbg и PDK хороший и скопировать можно.
Сам я склоняюсь к идее написания плагинов на языке Lua (как в программе SciTe). С одной стороны, это более быстро, чем программирование библиотек на C++/Delphi, с другой - любой может написать новый плагин в обычном блокноте, не обязательно иметь упомянутые средства программирования.
C++/Delphi гораздо лучше, чем LUA, вроде бы LUA скриптовый язык - это что все плагины будут как обычный текст? Можно сделать поддержку LUA скриптов плагином.
Offline
вроде бы LUA скриптовый язык - это что все плагины будут как обычный текст?
Да, и чем это плохо?
Вот пример луа-плагина (то, что я пока смог реализовать). Выводит по Ctrl+С сообщение с именем открытого файла:
bind("Ctrl+C", "TestMessage") function TestMessage() local e = GetActiveEditor() -- get editor if (e) then -- test if any file is open ShowMessage(GetEditorTitle(e), "Title") -- show editor's title end end
Реализовать С++ -плагины почти нереально по той причине, что санник написан на дельфи. Там просто нельзя выложить интерфейсные файлы (.h) и сделать как в IDA/OllyDbg.
Offline
Да, и чем это плохо?
А если придется создать навороченную форму?
Offline
А если придется создать навороченную форму?
Можно разместить ее в DLL и вызвать через Lua. Ближайшая аналогия - CLEO-опкоды 0AA2-0AA3.
В принципе, можно весь плагин - формы, функции, реализовывать в отдельной DLL (на C++ или чем угодно), и вызывать его, используя команды Lua, как я показал в примере. Lua в этом плане станет промежуточным интерфейсом между санником и плагинами.
Offline
Я тут подумал, можно реализовать еще другую систему плагинов.
Проблема заключается, конечно, не в загрузке DLL или, скажем, в добавлении в меню или на панель инструментов новой кнопки. Основная трудность состоит в обмене данными между программой и плагином. Т.е. плагин должен быть способен реагировать на события внутри программы (нажатие кнопки, старт компиляции, выход и т.д.), а также управлять данными программы (например, менять положение курсора, текст в редакторе).
Есть следующие варианты (кроме LUA).
1. Экпорт функций.
Можно экспортировать набор функций из sanny.exe и потом использовать его в DLL. Например,
char* _stdcall GetLine(int num)
будет возвращать указатель на строку с номером num.
Но этот не решает вопрос с передачей данных из плагина в программу.
2. Передача сообщений в обе стороны.
К примеру, в плагине будут минимум три функции: InitPlugin, FreePlugin и TranslateMessage. С первыми двумя все ясно, а TranslateMessage будет служить для обработки посланий от .exe к плагину. К примеру, при нажатии на один из пунктов меню во всех плагинах вызывается функция TranslateMessage с параметрами тип сообщения (OnMenuClick), и 2 дополнительных параметра, меняющих свое значение в зависимости от сообщения (в данном случае один из параметров будет равен ID нажатого пункта меню). Эта функция (как впрочем и любая другая из этих трех обязательных) возвращает одно из трех возможных значений:
-1 указывает на возникшую ошибку при обработке сообщения (при этом плагин должен заполнить опр. структуру информацией об ошибке, чтобы приложение могло отобразить, что произошло - вывести сообщение и т.д.)
0 - указывает на корректную обработку сообщения (либо отсутствие какой-либо обработки), при этом приложение может продолжить работу с ним.
Любое положительное значение указывает на корректную обработку сообщения, при этом приложение само его уже не обрабатывает. Например, посылка сообщения OnMenuClick с параметром MENU_NEWFILE будет указывать, что пользователь кликнул по кнопке "Новый файл" (в меню, на панели, или нажал Ctrl+N). Если плагин вернул значение 0, значит программа может продолжить выполнение этой команды и создать новый файл. Если возвращается положительное число, то новый файл не создается (предполагается, что плагин по опр. причинам запретил это, например если плагин реализует окно с выбором вариантов создания файла и сам создает новый файл). В опр. случаях, в зависимости от вида сообщения, возвращаемое значение может каким-то образом использоваться, например служить указателем на блок данных, которые будут читаться приложением.
Посылка сообщений в приложение осуществляется следующим образом. В функции InitPlugin передается указатель на callback-функцию в приложении вида function(int Msg; int * Data)
Плагин, если он собирается передавать сообщения в программу (инициировать какие-нибудь процессы), должен присвоить этот указатель на свою функцию такого типа. После этого он вызывает ее (а точнее функцию в exe) с параметрами Вид сообщения и указатель на опр. блок данных, тип которых зависит от сообщение.
Например, при посылке сообщения OPEN_FILE, вторым параметром будет являться указатель на путь к файлу, который должна открыть программа.
Как такие варианты?
Offline
2Seemann:
Зачем использовать TranslateMessage, если есть APIшные функции GetMessage, SendMessage.
Offline
Это уже вопросы реализации, главное система в целом.
К тому же для этих функций нужно, чтобы приемник постоянно проверял эти сообщения (в цикле, потоке). Для них же нужно отдельное окно? Не факт, что в плагине будет это самое окно.
TranslateMessage позволит вызывать обработчик сообщений в плагине, только когда это нужно программе.
Offline
2Seemann:
Реализовать можно по разному, главное чтобы PDK был хорошо документирован с примерами на разных языках.
Offline
Я долго медитировал над проблемой плагинов, даже попытался накидать более-менее внятный (в моем представлении) API.
Потом решил взглянуть на проблему в целом.
А что вообще планируется поключать плагинами? Как они должны взаимодействовать? Какие данные могут им понадобиться и что они могут возвращать?
Offline
Ну, я выше описал примерную структуру работы плагинов, как я себе это представляю. В приложении есть набор определенных ключевых событий, о которых оповещаются все загруженные плагины. Они каким-то образом на эти события реагируют. Также, если надо, они либо отправляют сообщение-запрос в программу и получают в ответ указатель на какие-то данные, с которыми они будут работать; либо сообщение-команду, которая указывает программе выполнить какое-то действие, например закрыть текущий файл.
Ключевые события: старт, выход, нажатие кнопки (в т.ч. мыши), движение мыши, клик по меню, открытие/закрытие файла, старт/прекращение (де)компиляции, появление нового окна (типа окна поиска или OST). Список открытый.
Насчет взаимодействия друг с другом, не думаю, что это очень важно. Максимум, что может пригодиться - это получение списка загруженных плагинов и их версии.
Данные?
Строки редактора (массив строк?): активная строка, выделенный текст.
Список опций (структура): папка игры, .
Версия программы.
Список пользовательских инструментов (меню Сервис-Инструменты).
Возможно пригодятся специфические данные, типа байт-кода текущего опкода при (де)компиляции, или целый дамп main.scm в конце компиляции, для построения продвинутых отчетов или оптимизаторов кода.
Все это передается указателями в ответ на сообщение-запрос в программу, соответсвенно плагин может не только читать, но и менять данные.
Offline
2Seemann:
Этого-то я и боялся... В таком виде, задача неразрешима в принципе.
лирическое отступление
В любом проекте больше "Hello, world", на который нет четко написанного ТЗ (а, временами, и при наличии такового), наступает момент, когда нужно спросить себя "Что я пишу?" и "Что я хочу этим добиться?" (не путать с вопросом "Зачем?", который задавать категорически нельзя).
Если так не делать - в один прекрасный момент можно обнаружить, что написана куча как-то работающего кода, который не поддается ни оптимизации, ни модификации.
/лирическое отступление
Итак, Sanny Builder. Редактор, ассемблер и дизассемблер. (Называть то, что есть, компилятором, конечно, приятно, но, на самом деле это хороший, умный, продвинутый макроассемблер. За счет того, что SCM-байткод досататочно высокоуровневый, ассемблер у него вполне читабелен, и, на первый взгляд, вполне может сойти за язык высокого уровня).
Что можно добавить к этим трем компонентам? Немного. Можно добавить каких-то дополнительных редакторов/вьюверов (например, GXT editor или инструмент для подбора координат). Для этой цели вышепредложенный механизм хорош и достаточен. Содержимое текущей текстовой строки редактора - это максимум, который может понадобиться (например, преусловнутому GXT editorу).
Чего добавить нельзя в принципе? Оптимизатор кода (вообще, оптимизатор ассемблерного кода - вещь сама по себе странная). Сколько-нибудь продвинутый рефакторинг к редактору. И вообще, любой инструмент, которому, в качестве входных данных, недостаточно plain-text.
Почему это сделать нельзя? Из-за того же plain-text. Возможности анализа и модификации текста сильно ограничены. Сколь бы то ни было продвинутый анализ требует построенных графов программы, а ним доступиться через какой-то общий механизм плагинов крайне тяжело, если вообще возможно.
Резюме:
1) описанный механизм работаь будет, хотя и с ограничениями
2) по-хорошему, начать надо с того, что описать все возможные команды/способы взаимодействия плагина с программой и хотя бы парочку сценариев работы плагинов
3) если хочется чего-то большего чем плагин к редактору/инструмент в соответствущем меню - нужно плотно садиться за редизайн SB, как системы простых модулей, к которым/между которыми могут подключаться плагины. Впрочем, это уже будет перспектива SB4
По выполнении пункта 2 в полном объеме, структура интерфейса плагинов должна стать ясна и очевидна.
PS. Как обычно, любое вышеизложенное утверждение можно развернуть подробнее.
Offline
Хорошо бы добавить в CLEO нормальные опкоды выбора случайного актера, объекта, машины.
GTA VC - ЭТО НАСТОЯЩАЯ ГТА!
Offline
Для этого есть Interceptor и стандартные опкоды. Я лучше добавлю опкоды на "получение" ближайшего к актеру(игроку) прохожего/машины, благо адреса мне известны.
Offline
1.Когда следуищий релиз CLEO?
2.Как Interceptor в клео скрипты вставлять?
3.Покажи пожалуйста мне эти опкоды.
4.
Я лучше добавлю опкоды на "получение" ближайшего к актеру(игроку) прохожего/машины
А на объекты адресов не знаеш?
GTA VC - ЭТО НАСТОЯЩАЯ ГТА!
Offline
1.Когда следуищий релиз CLEO?
Я думаю, скоро. Релиз CLEO будет одновременно с обновлением для Sanny Builder.
2.Как Interceptor в клео скрипты вставлять?
так же как и в обычный поток (вставляешь код в файл, делаешь gosub, потом проверяешь переменную 9@). Interceptor, насколько я понимаю, вполне может работать внутри CLEO-потока.
3.Покажи пожалуйста мне эти опкоды.
0327, 09C0, 073F, 089E и т.д.
А на объекты адресов не знаеш?
К сожалению, нет. Однако, Interceptor умеет работать с объектами.
Могу озвучить список новых опкодов в следующем релизе CLEO3:
0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 0@ closest_ped_to 1@ 0AB6: store_target_marker_coords_to 0@ 1@ // IF_AND_SET 0AB7: get_vehicle 0@ number_of_gears_to 1@ 0AB8: get_vehicle 0@ current_gear_to 2@
Offline
У меня чёто с Interceptor'rom не получилось.
0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 0@ closest_ped_to 1@
0AB6: store_target_marker_coords_to 0@ 1@
Э-э что он делает и что будет в обновлении для санника?
И опкод 0AB5 имеет функцию пропуска предыдущего актёра если поиск проводится от того же актёра?
GTA VC - ЭТО НАСТОЯЩАЯ ГТА!
Offline
0AB6 записывает в переменные координаты XY того места, которое отмечено на карте красной точной (правый клик мыши по карте => Player Target). Очень полезно для написания скрипта телепортации в указанную точку.
И опкод 0AB5 имеет функцию пропуска предыдущего актёра если поиск проводится от того же актёра?
0AB5 записывает в переменную ближайших актера и машину. Они могут быть только в одном экземпляре, либо не быть совсем, если игрок далеко от всех.
что будет в обновлении для санника?
так, мелочи. Станет еще удобнее компилировать CLEO-скрипты.
Offline
Доброго времени суток!
Подскажите кое-что. Во-первых, для чего все-таки нужен опкод 0AB1:? Я было подумал, что он вызывает функцию из самого main.scm, но не тут то было (
И во-вторых почему при работе с массивами из CLEO-скриптов некоторые значения произвольно могут менятся, причем это зависит от main.scm (редакатирован или оригинал)?
Offline
2kasper:
Во-первых, для чего все-таки нужен опкод 0AB1:?
все правильно, он и есть для вызова функции из SCM. В справке описан пример использования. А что, есть какие-то проблемы с использованием?
почему при работе с массивами из CLEO-скриптов некоторые значения произвольно могут менятся, причем это зависит от main.scm (редакатирован или оригинал)?
массивы локальные или глобальные? Если глобальные, то возможно что происходит наложение, и некоторые ячейки (имена переменных) используются и в майне и в CLEO.
Offline
Проблема в том, что SB ругается на то, что не может найти указанную метку. Все согласно примера, в чем может быть причина?
Массивы глобальные. Решение проблемы есть? А то не хочется вставлять скрипт в мейн.
Offline
Проблема в том, что SB ругается на то, что не может найти указанную метку.
а метка в этом же CLEO-скрипте (файле)?
Массивы глобальные. Решение проблемы есть? А то не хочется вставлять скрипт в мейн.
использовать локальные массивы (0@(10@,5i) например). Других вариантов нет. Глобальные переменные использовать нельзя.
Offline