|
| ... | Среда, 25.12.2024, 20:54
Приветствую Вас Гость | RSS |
Tips And Hints по поводу приборов (С/С++ Only)
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:33 | Сообщение # 1 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| Ну-с... с сакраментального В.: "что делать если грузятся два экземпляра одного прибора и дерутся между собой, вызывая ошибки в работе панели? И что делать если логика прибора не стартует, пока прибор не будет показан на экране" О.: Отвязать логику (работы прибора/системы) от представления (от того, что в симе называется gauge). Как это сделать? Сначала экскурс в основы. Многие начинающие прибористы воспроизводят шаблон, предложенный разработчиками сима в SDK. т.е. Quote (g) GAUGE_TABLE_BEGIN() GAUGE_TABLE_ENTRY(&gaugehdr_attitude) GAUGE_TABLE_ENTRY(&gaugehdr_control_surfaces) GAUGE_TABLE_ENTRY(&gaugehdr_fuel) GAUGE_TABLE_ENTRY(&gaugehdr_fuel_selector) GAUGE_TABLE_ENTRY(&gaugehdr_temperature) GAUGE_TABLE_ENTRY(&gaugehdr_whiskey) GAUGE_TABLE_ENTRY(&gaugehdr_flightmap) GAUGE_TABLE_END()
|
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:34 | Сообщение # 2 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| и не задумываются, что стоит за этими мудрыми словами, до тех пор пока... пока не начинают делать что-то более сложное, и не сталкиваются с проблемами наподобие вышеописанной. Собственно, данный шаблон предназначен для сокрытия программной машинерии, которая обеспечивает загрузку и отображение приборов симом. Пытаясь остатся в пределах использования этого шаблона, начинаются навороты со статическими переменными, отслеживанием многократной загрузки и тд и тп, что не способствует устойчивости модели вообще. Решение же лежит в другом, и решение это более изящно - а именно - развязывание непосредственно представления (gauges) от логики модели той или иной системы ВС. Но для этого - необходимо прекратить использовать вышеприведеннный шаблон, и начать использовать ту самую внутреннюю машинерию приборного модуля. Так что же скрывает вышеприведенный шаблон? А вот что Quote (Kilderd) //GAUGE_TABLE_BEGIN() extern GAUGEHDR gauge_header; void FSAPI module_init(void){} //вот оно!!! void FSAPI module_deinit(void){} //и это!!!! BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) { return TRUE; } GAUGESIMPORT ImportTable = { { 0x0000000F, (PPANELS)NULL }, { 0x00000000, NULL } }; /* This is the module's export table. */ GAUGESLINKAGE Linkage = { 0x00000013, module_init, module_deinit, 0, 0, FS9LINK_VERSION, { //GAUGE_TABLE_ENTRY(&gaugehdr_attitude) (&gaugehdr_attitude), //GAUGE_TABLE_END() 0 }};
|
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:34 | Сообщение # 3 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| Итак, что мы тут видим? А видим, что шаблон скрывает определение трех функций и двух структур. Первую структуру (ImportTable) оставляем без изменений, она обеспечивает доступ к функциям сима наподобие lookup_var(). Вторая структура содержит заголовок приборного модуля, в котором указывается магическое число 0x13 (19 в десятичной системе), обозначающую для сима то, что это приборный модуль, два адреса функций, определенных ранее (module_init, module_deinit), два магических числа, нам не интересных, номер версии сима, для которой предназначен данный приборный модуль, ну а дальше идет список адресов заголовков описаний непосредственно представлений приборов (gauges), завершающееся еще одним магическим числом - 0, поскольку именно его сим ожидает увидить при загрузке списка представлений из приборного модуля, в конце означенного списка представлений. Более детально нас интересуют именно определенные шаблоном функции. DllMain оставим в стороне, она в приборных модулях дополняется своим кодом в очень редких случаях. Более подробно интересуют две другие функции - module_init и module_deinit. Что они делают? В шаблоне по умолчанию они не делают ничего! Но! функция module_init вызывается один раз при загрузке приборного модуля, и module_deinit вызывается один раз при выгрузке модуля симом. При этом совершенно не важно, был ли отображен прибор на экране, или не был. Т.е. эти две функции выполняются всегда. Вот сюда-то нам и надо поместить инициализацию логики наших систем, загрузку всех требуемых ресурсов, а так же запуск цикла расчетов обновлений логики (в тч и асинхронное, если ваши знания позволяют это реализовать). В представлении же мы оставляем только отображение конкретных значений и прием управляющих воздействий от пользователя (мышеклики). При этом одинаковых представлений может быть любое множество, в каких угодно местах (на 2Д панели, в ВК или на внешнем компьютере). Конкретные способы реализации самой модели я сейчас рассматривать не буду. Итак, что же надо сделать? конкретно - прекратить использовать шаблон, предложенный SDK, и использовать ту внутреннюю машинерию, которую скрывает этот шаблон. Выполнив это, вы способны внедрить в функции, вызываемые симом при загрузке приборного модуля (не отдельного прибора, события откладываемого до непосредственного отображения прибора, а всего модуля!) и при выгрузке, необходимый вам код инициализации и запуска логики, независимой от представления.
|
|
| |
fogot | Дата: Четверг, 07.01.2010, 06:36 | Сообщение # 4 |
Полковник
Группа: Персонал
Сообщений: 108
Награды: 0
Репутация: -4
Замечания: 20%
Статус: Не в сети
| В связи с периодически поднимающимися вопросами о плавных приборах, выкладывается собранный на коленке примерчик. В 2 прикрепленных файлах готовая сборка авиагоризонтоподобного прибора для цессны-172 и соответственно исходники. В исходниках оставлены за кадром некоторые хитрушки для стимуляции головного мозга начинающих писателей
|
|
| |
Спец_Блатной | Дата: Четверг, 07.01.2010, 06:44 | Сообщение # 5 |
Подполковник
Группа: Персонал
Сообщений: 95
Награды: 0
Репутация: 0
Замечания: 0%
Статус: Не в сети
| Quote (fogot) В связи с периодически поднимающимися вопросами о плавных приборах, выкладывается собранный на коленке примерчик. В 2 прикрепленных файлах готовая сборка авиагоризонтоподобного прибора для цессны-172 и соответственно исходники. В исходниках оставлены за кадром некоторые хитрушки для стимуляции головного мозга начинающих писателей А чем рисование через GDI+ решит проблему с рефрешем текстур в вк? Собственно главная проблема в виртуальном кокпите - это несколько более тормознутое обновление текстур - на которых собственно приборы то и рисуются - по сравнению с обновлением подложки 2д панели (ну поставили мы флаг SET_OFF_SCREEN - ну узнал сим что хорошо бы перечитать подложку - ну и когда он по вашему этот сделает? Незамедлительно? Да не факт...). И лечится это вообще-то только одним путем - уменьшением размерности текстур в вк. Чем меньше обновлять - тем быстрее сим это сделает (речь ведем о 2004, фсх вроде в этом плане помягче работает). Ну или рисовать объекты как 3д - но чем больше полигонов в кадре - тем тормознутее собственно работа симулятора.
|
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:45 | Сообщение # 6 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| Олег, речь идет о плавности в 2Д Битмапные приборы (особенно если их размер мелковат) - иногда получаются дискретными, причем дискретность изменения положения битмапки заметна визуально.
|
|
| |
Спец_Блатной | Дата: Четверг, 07.01.2010, 06:45 | Сообщение # 7 |
Подполковник
Группа: Персонал
Сообщений: 95
Награды: 0
Репутация: 0
Замечания: 0%
Статус: Не в сети
| Ну знаете ли - и из пушки по воробьям (сиречь gdi+ для стрелочников пользовать) - это тоже не вариант :-) Ибо рисование через гди - изначально вещь затратная. Кстати помнится я с подобным сталкивался, уж не помню на каком проекте - так вот, MAKE_NEEDLE имеет какие-то проблемы, а вот спрайт работал плавненько.
|
|
| |
fogot | Дата: Четверг, 07.01.2010, 06:46 | Сообщение # 8 |
Полковник
Группа: Персонал
Сообщений: 108
Награды: 0
Репутация: -4
Замечания: 20%
Статус: Не в сети
| Олег, я в курсе пример представлен как вариант. если стандартные симовские варианты прокатывают, скажем, для курсовой (у нас на одной машине ГИК тож скачет через 2-3 градуса рывками ), то для АГР, например, луче отрисовать ПММ конечно же. Понятно, что для высотомера например вполне хватит и NEEDLE или SPRITE
|
|
| |
Миша | Дата: Четверг, 07.01.2010, 06:47 | Сообщение # 9 |
Полковник
Группа: Сотрудник
Сообщений: 117
Награды: 0
Репутация: -1
Замечания: 20%
Статус: Не в сети
| А можно задать маленький и глупый вопрос? Если сделать модель под одну версию FS без использования шаблонов SDK, не приведет ли это к тому, что, при переходе на следующие версии FS придется не просто перекомпилировать исходники с использованием gauges.h из нового SDK, а переписывать куски кода в каждом приборе?
|
|
| |
мировая_авиация | Дата: Четверг, 07.01.2010, 06:48 | Сообщение # 10 |
Лейтенант
Группа: Персонал
Сообщений: 38
Награды: 0
Репутация: -20
Замечания: 0%
Статус: Не в сети
| Вряд ли сильно много. Денис просто раскрыл макросы, описывающие "голову" прибора. Если уж прям так напрягает - условную компиляцию никто не отменял
|
|
| |
fogot | Дата: Четверг, 07.01.2010, 06:48 | Сообщение # 11 |
Полковник
Группа: Персонал
Сообщений: 108
Награды: 0
Репутация: -4
Замечания: 20%
Статус: Не в сети
| Спасибо. У меня два вопроса. 1. В любой гау баблиотеке должен быть хотя бы один прибор с именем, которое, в свою очередь, нужно прописать в Panel.cfg, для того, чтобы сим мог подцепить библиотеку. Сам же прибор требует наличия макроса GAUGE_HEADER_FS700, который в свою очередь, требует обязательного списка элементов. Вот и приходится в прибор логики добавлять такой список, хотя бы с одним элементом, к примеру, MAKE_STATIC, содержащий в качестве параметров нули. В принципе, ничего особо страшного в этом нет, но может есть способ обойтись без таких заглушек? 2. Необходимо написать программный модуль обработки ввода пользователя. Ввод пользователя осуществляется через клавиатуру, джойстик, мышь. С джойстиком понятно - пишем с использованием DirectInput, отключаем в симе джойстик и получаем нечто похожее на ПТ. Мышь. Мышиные события и так обрабатываются в пользовательском коде. Остается клавиатура. И тут мне известны два возможных варианта: DirectInput и SetWindowsHookEx. Собственно клавиатурный хук пока вполне справляется с задачей, то есть клавиатурное событие прехватывается перед симулятором, и в коде определяется что с ним делать: а) обработать самостоятельно и "погасить"; б) обработать самостоятельно и передать симу; в) просто передать симу без обработки. Собственно вопрос: нужно ли смотреть в сторону DirectInput (с которым я никогда не работал применительно к клавиатуре)?
|
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:51 | Сообщение # 12 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| Quote (fogot) У меня два вопроса. 1. В любой гау баблиотеке должен быть хотя бы один прибор с именем, которое, в свою очередь, нужно прописать в Panel.cfg, для того, чтобы сим мог подцепить библиотеку. Сам же прибор требует наличия макроса GAUGE_HEADER_FS700, который в свою очередь, требует обязательного списка элементов. Вот и приходится в прибор логики добавлять такой список, хотя бы с одним элементом, к примеру, MAKE_STATIC, содержащий в качестве параметров нули. В принципе, ничего особо страшного в этом нет, но может есть способ обойтись без таких заглушек? Можно. Способ для FS9 называется "модуль". Собственно гау есть частный случай обычного модуля, несколько более специфицированный. Для FSX нужно работать через SimConnect. Как сделать модуль FS9? да точно так же как и gau. С одним отличием - в Linkage первый параметр ("магическое число 0x00000013) заменяется либо на 0, либо на любое не занятое симовскими модулями (ага, они имеют такую же структуру, те же ImportTable и Linkage символы) число. Впрочем, отличное от нуля число необходимо только тогда, когда предполагается загрузка вашего модуля другими компонентами сима (ну например - вашими приборами) посредством штатных механизмов ФС. Ну и дальше в Linkage, где у вас идут списки приборов, будет стоять простой сакраментальный 0, обозначающий пустой список функций. Такой модуль надобно будет положить в папочку modules, сим при запуске его загрузит. Что с этим делать дальше и как взаимодействовать с симом? нууу, это большой и сложный вопрос, который уходит в сторону "грязных" хаков и использования штатных, но немножко недокументированных функций Quote (fogot) 2. Необходимо написать программный модуль обработки ввода пользователя. Ввод пользователя осуществляется через клавиатуру, джойстик, мышь. С джойстиком понятно - пишем с использованием DirectInput, отключаем в симе джойстик и получаем нечто похожее на ПТ. Мышь. Мышиные события и так обрабатываются в пользовательском коде. Остается клавиатура. И тут мне известны два возможных варианта: DirectInput и SetWindowsHookEx. Собственно клавиатурный хук пока вполне справляется с задачей, то есть клавиатурное событие прехватывается перед симулятором, и в коде определяется что с ним делать: а) обработать самостоятельно и "погасить"; б) обработать самостоятельно и передать симу; в) просто передать симу без обработки. Можно и не смотреть, достаточно клавиатурного хука. Дальше - смотрите сами. там опять начинается грязный хакинг и пошлая недокументарщина. В плане FSX все куда проще - возможность маппить свои события на клавиатуру и перехватывать штатные, с "гашением" любых симовских событий - заложена в SimConnect по дефолту.
|
|
| |
Ту-144 | Дата: Четверг, 07.01.2010, 06:52 | Сообщение # 13 |
Полковник
Группа: Персонал
Сообщений: 114
Награды: 0
Репутация: 734
Замечания: 0%
Статус: Не в сети
| можно я добавлю? такие модули будут висеть постоянно в памяти, в отличии от гауги, которая грузится только при загрузки крафта и выгружается при его выгрузки (ну например смене самолёта, который данную гаугу не использует). я не знаю, важно это знать или нет.
|
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:53 | Сообщение # 14 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| С помощью тех самых недокументированных функций можно реализовать и модуль с загрузкой по запросу. В FS9 ессесно. в FSX SimConnect нивелирует все различия.
|
|
| |
Dokone | Дата: Четверг, 07.01.2010, 06:55 | Сообщение # 15 |
Антесемит
Группа: Сотрудник
Сообщений: 271
Награды: 0
Репутация: 3
Замечания: 0%
Статус: Не в сети
| Доброго времени суток. Ребята, кто подскажет в чем может быть проблема, если после компиляции стандартных файлов из SDK (папка /sample), то файл .gau не создается вообще...? Компилятор не ругается только с параметром /I. (nmake MVC++2008 EE).
Search Engine
|
|
| |
Матрос | Дата: Четверг, 07.01.2010, 06:56 | Сообщение # 16 |
Генералиссимус
Группа: Персонал
Сообщений: 503
Награды: 0
Репутация: 287
Замечания: 0%
Статус: Не в сети
| а файл .dll есть? на что ругается без /I?
Привет всем, кто из Ярославля!
|
|
| |
Dokone | Дата: Четверг, 07.01.2010, 06:57 | Сообщение # 17 |
Антесемит
Группа: Сотрудник
Сообщений: 271
Награды: 0
Репутация: 3
Замечания: 0%
Статус: Не в сети
| Привет. Хоть кто-то отозвался... В том то и проблема, что не создается никаких папок и файлов вообще, а компилер ошибок не выдает. Без /I пишет "fatal error U1077". А с указанным параметром "link..." и т.д. - т. е. вроде все Ок. ??? Не понятно.
Search Engine
Сообщение отредактировал Dokone - Четверг, 07.01.2010, 06:57 |
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 06:59 | Сообщение # 18 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| Возможно в PATH нужно еще прописать папки какие-то? Я прописал нахождение cl и rc ... можно make файл в студию. и ещё один вопрос - а почему собсно из консоли компиляем? чем живая студия плоха? и ещё, если работаешь из консоли, vcvars32 запускал?
|
|
| |
Kilderd | Дата: Четверг, 07.01.2010, 07:00 | Сообщение # 19 |
Генерал-полковник
Группа: Персонал
Сообщений: 252
Награды: 0
Репутация: 168
Замечания: 0%
Статус: Не в сети
| Quote (Kilderd) # makefile # Copyright © 2000 Microsoft Corporation. All rights reserved. INCDIR = ..\inc DESTDIR = ..\inc INCS = -I$(INCDIR) LIBS = user32.lib gdi32.lib kernel32.lib !IFDEF DEBUG C_FLAGS = /Z7 L_FLAGS = /DEBUG !ELSE C_FLAGS = L_FLAGS = !ENDIF goal: SDK.gau SDK.obj: $(INCDIR)\gauges.h \ SDK.c \ SDK.h \ SDK.Attitude.c \ SDK.Control_Surfaces.c \ SDK.Fuel.c \ SDK.Fuel_Selector.c \ SDK.Temperature.c \ SDK.Wiskey.c \ SDK.FlightMap.c cl $(C_FLAGS) -c $(INCS) SDK.c SDK.res: SDK.rc \ SDK.h \ res\SDK.Attitude.bg.BMP \ res\SDK.Attitude.card1.BMP \ res\SDK.Attitude.mask1.BMP \ res\SDK.Attitude.card2.BMP \ res\SDK.Attitude.mask2.BMP \ res\SDK.Control_Surfaces.bg.bmp \ res\SDK.Control_Surfaces.Ailerons.bmp \ res\SDK.Control_Surfaces.Elevator.bmp \ res\SDK.Control_Surfaces.Rudder.bmp \ res\SDK.Control_Surfaces.Trim.bmp \ res\SDK.Fuel.bg.bmp \ res\SDK.Fuel.needle.bmp \ res\SDK.Fuel_Selector.Off.BMP \ res\SDK.Fuel_Selector.Left.BMP \ res\SDK.Fuel_Selector.Right.BMP \ res\SDK.Fuel_Selector.Both.BMP \ res\SDK.Temperature.bg.bmp \ res\SDK.Temperature.F.bmp \ res\SDK.Temperature.C.bmp \ res\SDK.Whiskey.bg.BMP \ res\SDK.Whiskey.card.BMP \ res\SDK.Whiskey.mask.BMP \ res\SDK.FlightMap.BMP rc -r $(INCS) SDK.rc SDK.gau: SDK.obj \ SDK.res link $(L_FLAGS) /dll /out:$(DESTDIR)\SDK.gau SDK.obj SDK.res $(LIBS) clean: del $(DESTDIR)\*.exp del $(DESTDIR)\*.gau del $(DESTDIR)\*.lib del *.obj del *.res /////////////////////////////////////////////// В студии я не компилирую потому, что не компилировал никогда при помощи <makefile> - файлов (работал в СиБилдере и Делфи, и всегда использовал встроенный компилер). К тому же руководствовался только SDK. vcvars32 запускал - все по-прежнему..
|
|
| |
|